Use STM8 to Control nRF24L01

7 篇文章 0 订阅
2 篇文章 0 订阅

※The complete code is available in here.

 In my previous post, I used nRF24LE1, which is an 8051 microcontroller(MCU) integrated nRF24L01 function, to operate Enhanced Shockburst™ (ESB) transceiving. If your MCU would tackle only some simple tack with wireless function, nRF24LE1 is a good selection. However, in some case, nRF24LE1 may be not a choice. For example, nRF24LE1 computing power is limited and does not support CAN bus, pins of nRF24LE1 would be conflicted for your application, multi-channels ADC/I2C/SPI are required,  or just existing product must not be totally reforged..etc. Hence, In here, I would to show how to use STM8L to manipulate nRF24L01.

 

The STM8L I use here is STM8L101F3P3 features its low price (STM8L10X series is lowest product line of STM8 series.). Because the STM101F1  flash size is not adequate to containing the firmware operating nRF24L01, I use the chip postfix being -F3 rather than -F1.

 

 

 To detail explain how to deal with the porting, I start from my another post code of folder nRF24LE1, which has been completely implemented ESB send and receive functions.

 

 

 零.

    Download ST Visual develop IDESTM8 Cosmic compiler, and  STM8L10x standard peripheral library. you need to provide your email to STMicroelectronics.

 

   Install those software,  crack the compiler, and set ST Visual develop using the compiler : Tools → Option :

 

 

 

一. Download my the code for nRF24LE1 :

 

Download the code from here, you should extract those :

esb_app.c

esb_app.h

hal\nordic_common.h

hal\nrf24l01p\hal_nrf.c

hal\nrf24l01p\hal_nrf.h

hal\nrf24l01p\hal_nrf_reg.h

hal\nrf24le1\hal_nrf_hw.c

hal\nrf24le1\hal_nrf_hw.h

 

compiler\c51\stdin.h

 

 

And create a folder to contain those code, in structure:

 

esb_app.c

esb_app.h

nRF24L01_hal\nordic_common.h

nRF24L01_hal\nrf24l01p\hal_nrf.c

nRF24L01_hal\nrf24l01p\hal_nrf.h

nRF24L01_hal\nrf24l01p\hal_nrf_reg.h

nRF24L01_hal\stm8L10x\stdin.h

nRF24L01_hal\stm8L10x\hal_nrf_hw.c

nRF24L01_hal\stm8L10x\hal_nrf_hw.h

 

 

二 .  Modify the necessary code:

The firmware architecture diagram is as below, The blocks framed purple  is the code you need to modify/implement.

 

 

 

 

 

esb_app.h :

export esb_irq function :

 

 

:

void esb_receiving_event_has_been_handled(void);


/*nRF24L01 IRQ*/
#if !defined(NRF24LE1_H_) && !defined(NRF24LU1P_H)
void esb_irq(void);
#endif

 

esb_app.c :

 

comment out the line to set register RFCKEN and RF, and remove the keyword "static"  of function esb_irq.

 

void esb_init(void)
:
#if defined(NRF24LE1_H_) || defined(NRF24LU1P_H)
 RFCKEN = 1;  //enable RF timer
#endif
:
#if defined(NRF24LE1_H_) || defined(NRF24LU1P_H)
 RF = 1; //enable rf interrupt
#endif
:
}/*enhanced_shockburst_init*/

:

/*static */ void esb_irq(void)
{
:

 

 

As the diagram shows, the hal_nrf,c and  hal_nrf.h  would be intact, but  hal_nrf_hw.c and hal_nrf_hw.h need to be completely implemented. Is is because the SPI operations are high MCU-dependency, and pin definition is high board-dependency.

 

The schematic of my board is :

 

 

keypoints:

 

PC0 pin is for nRF24L01 IRQ.

PB4 pin is for nRF24L01 CSN.

PB3 pin is for nRF24L01 CE.

 

In this manner,  hal_nrf_hw.h as :

 

 

#ifndef HAL_NRF_STM8L101XX_H__
#define HAL_NRF_STM8L101XX_H__
#include "STM8l10x_conf.h"

#define data     
#define pdata
#define xdata

/** Macro that set radio's CSN line LOW.
 *
 */
#define CSN_LOW() do {  GPIO_ResetBits( GPIOB, GPIO_Pin_4);} while(false)
/** Macro that set radio's CSN line HIGH.
 *
 */
#define CSN_HIGH() do { GPIO_SetBits( GPIOB, GPIO_Pin_4);} while(false)

/** Macro that set radio's CE line LOW.
 *
 */
#define CE_LOW() do {GPIO_ResetBits(GPIOB, GPIO_Pin_3);} while(false)

/** Macro that set radio's CE line HIGH.
 *
 */
#define CE_HIGH() do {GPIO_SetBits(GPIOB, GPIO_Pin_3);} while(false)

/** Macro for writing the radio SPI data register.
 *
 */
#define HAL_NRF_HW_SPI_WRITE(d) do{\
                 while (SPI_GetFlagStatus(SPI_FLAG_TXE) == RESET);\
                 SPI_SendData(d);\
                } while(false)

/** Macro for reading the radio SPI data register.
 *
 */
#define HAL_NRF_HW_SPI_READ()  SPI_ReceiveData()
  
/** Macro specifyng the radio SPI busy flag.
 *
 */
#define HAL_NRF_HW_SPI_BUSY   (RESET == SPI_GetFlagStatus(SPI_FLAG_RXNE))

/**
 * Pulses the CE to nRF24L01 for at least 10 us
 */

#define CE_PULSE() do { \
  uint8_t count; \
  count = 20; \
  CE_HIGH();  \
  while(count--){} \
  CE_LOW();  \
  } while(false)

 
#endif // HAL_NRF_STM8L101XX_H__

/** @} */

 

 

Those lines to define data, pdata and xdata are for avoiding compilation error.

 

hal_nrf_hw.c:

 

 

#include <stdint.h>
#include "hal_nrf.h"
#include "STM8l10x_conf.h"

uint8_t hal_nrf_rw(uint8_t value)
{
 while (RESET == SPI_GetFlagStatus(SPI_FLAG_TXE));
 SPI_SendData(value);
 
 //wait for receiving a byte
 while(RESET == SPI_GetFlagStatus(SPI_FLAG_RXNE));
 return SPI_ReceiveData();
}

 

 

三. Create the project.

 

  Create a workspace of ST Visual Develop with what the chip you use, and create a project inside it. the project folder in this structure:

 

 

stm8_interrupt_vector.c and stm8l10x_conf.h are auto-generated files. The  STM8L10x_StdPeriph_Driver folder contains the driver files of of STM8L10x standard peripheral library, in directory STM8L10x_StdPeriph_Lib\Libraries\STM8L10x_StdPeriph_Driver, for inc and src folder respectively.

 

 

 

The next stuff I need to do,  is to complete the nRF24L01 initialization. Pay attention :: it is not ESB initializtion function, which has been implemented in esb_app.c. The nRF24L01 initialization is for initializing the interface resources used in communicated with nRF24L01.

 

There are two part: initialize the Serial Peripheral Interface Bus(SPI), and the General-purpose input/output(GPIO).

 

The pins:

 

PB7 pin is SPI_MISO, input, high = 1.

PB6 pin is SPI_MOSI, output, high = 1.

PB5 pin is SPI_SCK, output, high = 1.

 

PB4 pin is for nRF24L01 CSN. output, set = 1.

PB3 pin is for nRF24L01 CE, output, set =1.

 

PC0 pin is for nRF24L01 IRQ, input,  external interrupt, active-low.

 

According to above definition, the the data sheet of nRF24L01 for SPI timing explanation(CPOL= low, CPHA = rising edge, more detail explanation about CPOL and CPHA you could refer to here) , the code for nRF24L01 initialization is :

 

 

void spi_init(void)
{
 //Config the GPIOs for SPI bus
 
 /*
  GPIOB::GPIO_Pin_7  -> SPI_MISO   
  GPIOB::GPIO_Pin_6  -> SPI_MOSI  
  GPIOB::GPIO_Pin_5  -> SPI_SCK   
 */
 GPIO_Init( GPIOB, GPIO_Pin_7, GPIO_Mode_In_PU_No_IT);
 GPIO_Init( GPIOB, GPIO_Pin_5 | GPIO_Pin_6, 
  GPIO_Mode_Out_PP_High_Slow);
  
 SPI_DeInit();
 //enable clock for SPI bus
 CLK_PeripheralClockConfig(CLK_Peripheral_SPI, ENABLE);

/*SPI BAUDRATE should not be over 5MHz*/
#define SPI_BAUDRATEPRESCALER   (SPI_BaudRatePrescaler_4)

 //Set the priority of the SPI
 SPI_Init( SPI_FirstBit_MSB, SPI_BAUDRATEPRESCALER,
            SPI_Mode_Master, SPI_CPOL_Low, SPI_CPHA_1Edge,
            SPI_Direction_2Lines_FullDuplex, SPI_NSS_Soft);
 //Enable SPi
 SPI_Cmd(ENABLE); 
 
}/*spi_init*/


void nrf24l01_init(void)
{  
 spi_init();
 
 /*GPIOB::GPIO_Pin_4 -> SPI::NSS -> NRF24l01::CSN*/
 GPIO_Init( GPIOB, GPIO_Pin_4, GPIO_Mode_Out_PP_High_Fast);
 
 /*GPIOB::GPIO_Pin_3 -> NRF24l01::CE*/
 GPIO_Init( GPIOB, GPIO_Pin_3, GPIO_Mode_Out_PP_High_Fast);

 /*GPIOC::GPIO_Pin_0 -> NRF24l01::IRQ*/ 
 GPIO_Init(GPIOC, GPIO_Pin_0, GPIO_Mode_In_PU_IT); 
 EXTI_SetPinSensitivity(GPIO_Pin_0, EXTI_Trigger_Falling_Low);
 EXTI_ClearITPendingBit(GPIO_Pin_0);
}/*spi_init*/

 

 

The last stuff to do is to register an external interrupt function for nRF24L01's IRQ in file stm8_interrupt_vector.c.

 

 In my board, pin PC0 is the pin for nRF24L01 IRQ.  According to the STM8L101xx datasheet( in section "interrupt vector mapping", p.32), the PX0 interrupt number is 8.

 

Therefore, add the interrupt function in stm8_interrupt_vector.c :

 

struct interrupt_vector const _vectab[] = {
 {0x82, (interrupt_handler_t)_stext},
:
:
 {0x82, NonHandledInterrupt}, /* irq6  */
 {0x82, NonHandledInterrupt}, /* irq7  */
 
 {0x82, external_interrupt0_handler}, /* irq8  */
 
 {0x82, NonHandledInterrupt}, /* irq9  */

 

 

The interrupt function definition is:

 

@far @interrupt void external_interrupt0_handler(void)
{
 EXTI_ClearITPendingBit(GPIO_Pin_0); 
 esb_irq();
}/*external_interrupt0_handler*/

 

This very clear that once the interrupt is triggered, function esb_irq, which is as the same as nRF24LE1's, will be called to deal with the callback events of send/receive/max re-try.

 

 

It is all.

 

I have upload the complete code on Github, you are able to access that in here.

 

below is the uart output of this STM8L101F3PU + nRF24L01 while this device is communicating with nRF24LE (the original one, before this porting).

 

 

If I turn off the nRF24LE1, the uart output is :

 

 

It is compatible with ,y previous works totoally. Of course, this porting is able to communicate with my previous work on nRF5X.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本遥控小车是使用STM8S105K4T6为主控芯片设计的一款遥控接收玩具小车,采用nrf24l01模块作为发射及接收,OLED 屏幕可以实时关注系统电量以及系统状态,是一个完完整整的从底层硬件撸到demo和3D结构的完整项目,遥控板和接收板都是自行设计,接口丰富,二次开发省时省力。为了方便二次开发,写了一个使用手册文档和录制了两个视频教程,一个是代码整体架构简介(16分钟),另一个是如何编译并下载程序到遥控板及接收板(5分钟),视频讲的很一般,但看明白应该问题不大。小车支持控制两路电机的前进后退左转右转加减速(使用TB6612作为驱动ic);支持四路舵机控制(小车目前只使用两路舵机);支持三路开关通断控制,在小车上则其中一路作为激光,一路作为水弹枪开关,预留一路(使用mos管作为开关管);支持超声波距离检测;电量显示(遥控板有OLED 屏幕)等。每个功能遥控板都有对应的按键或电位器控制,接收板有对应的接口。同时也可以根据自己的意愿在原代码基础上开发出自己想要的特殊功能的遥控车,这可以减少大家的宝贵时间。接出了串口2接口可方便开发。虽然小车的默认功能是水弹枪遥控小车,而且只使用了两路的舵机接口,但可以轻松实现为4通道械臂小车,遥控消防小车,遥控船等其他不同功能的遥控作品。 注:小车遥控板采用1个18650电池供电,使用LDO降压供电方式,非常省电,同时,电路板上有tp4056电池充电电路,没电时直接用USB线插入板上充电口,连接手机充电器即可实现充电,充满电板上的LED由红变绿。 接收板没有设计充电电路,小车的供电为两个18650串联组成8.4V电池组。但为了方便,特别设计了一个双路充电板,分别支持单节锂电4.2V充电和双节锂电8.4V充电。其中单节锂电充电电路采用tp4056充电ic,和遥控板上的一样,而5V转8.4V充电电路则采用专门的5V转8.4V充电ic,可以将手机充电器的5V输出转化为8.4V给两串的电池组充电,充电电流为1A,该电路板支持安卓口,USB2.0和USB typeC三种接口,基本上用我们手机的充电线和手机充电器就可以给小车充电,非常方便。使用方法也很简单,将电池插头和接收板拔开,再将电池插头和这个充电器预留的8.4V插头接好,再用手机充电器给这个充电板供电即可,充满电充电板上的LED会自动熄灭。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值