目录--点击可快速直达

MCU:KEAZ64A

MDK:CodeWarrior 11.0

写在前面

因为最近在重写之前项目的代码,以提升系统的稳定性和代码的可读性,所以重新选择了一块nRF24L01P,进行调试。

以下算是一些调试的备忘录吧,如有问题可以通过私信或者邮箱联系我。

什么是nRF24L01P?

nRF24L01P是一颗工作在 2.4GHz ISM 频段,专为低功耗无线场合设计,集成嵌入式 ARQ基带协议引擎的无线收发器芯片。

工作频率范围为 2400MHz-2525MHz,共有 126 个 1MHz带宽的信道。

简单来说,就是一块基于民用频段的无线通信芯片,可以用于无线鼠标、无线键盘、遥控器、工业传感器等应用。

后面我要使用的模块是在某宝上买的泽耀的nRF24L01P无线通信模块,以下的一些图片也是截取自它家的产品资料。

nRF24L01P模块的简单介绍

nRF24L01P模块一共有八个引脚,其中4个SPI引脚,一共工作模式切换引脚和一个终端引脚。

推荐与MCU的连接图

nRF24L01P的工作模式

nRF24L01P使用SPI进行通讯,可以通过SPI设置nRF24L01P的寄存器来改变nRF24L01P的工作模式。

如图所示,nRF24L01P的工作模式有如上几种,我们主要使用的就是接收模式、发射模式以及在两者之间过渡的待机模式II。

通过改变CONFIG寄存器中的PRIM_RX的值和模块引脚CE的高低电平,就可以切换工作模式了。

工作模式之间切换是有延时的,如果不加延时,可能导致未知的问题。一定要按照芯片手册中的资料来增加延时。

nRF24L01P模块的初始化简易配置

(一对一模式,使用接收通道0,禁止自动重发)

寄存器 位名 推荐值 备注
TX_ADDR None 0x34 0x43 0x10 0x10 0x01 发射地址
RX_ADDR_P0 None 0x34 0x43 0x10 0x10 0x01 接收通道0地址
EN_AA None 0 禁止自动应答
SETUP_RETR None 0 禁止自动重发
EN_RXADDR ERX_P0 0x01 使能通道0
RF_CH None 40 设置通道频率
RX_PW_P0 None 0x05 设置P0通道的数据宽度
RF_SETUP None 0x07 设置发射功率以及数据传输数率
CONFIG None 0x3e 禁止发射中断,使能发射模式

注:

1.配置寄存器时,一定要按照SPI的指令格式进行配置。如下图。

nRF24L01P模块调试的一些小技巧

1.刚开始调试的时候一定要选择一个模块为发射模式,一个模块为接收模式。发射的开启发射中断,接收的开启接收中断。这样就可以用过在中断中加入显示(例如LED)开观察是否发射成功或者接收成功。

2.刚开启中断的时候一定要记得清除中断标志位,中断标志位有两个,一个是模块的中断标志位,一个是MCU的中断标志位。

3.对于发射模式,切换发射模式的时候,最好把发射地址(TX_ADDR)也重新写一遍,因为我在调试的时候发现,如果不重写一遍地址,就会出问题。当然,这个可能是模块的BUG,因人而异把。

4.如果有问题,记得使用示波器查看SPI引脚、CE和IRQ的运行情况。

5.写入寄存器的时候记得拉低CE引脚。

6.如果还是有未知的问题,可以试试延长一下操作IO的时间。

附上源码

软件模拟的SPI通信,方便移植。

  1. /**
  2. ******************************************************************************
  3. * @file drv_spi.c
  4. * @author xxx
  5. * @version V1.0
  6. * @date 2020-1-04
  7. * @brief SPI配置C文件
  8. ******************************************************************************
  9. */
  10. #include "common.h"
  11. /*
  12. * PTB2->SCK PTF0->CE
  13. * PTB3->MOSI PTE2->MISO
  14. * PTD2->CSN IRQ->PTA6
  15. *
  16. * PTE0->SCK PTG3->CE
  17. * PTE1->MOSI PTE2->MISO
  18. * PTE3->CSN IRQ->PTC7
  19. */
  20. void spi_set_clk_low( )
  21. {
  22. //GPIO_Set_IO_Value(PORT_B,GPIO_PIN_2,OUTPUT_LOW);
  23. GPIO_Set_IO_Value(PORT_E,GPIO_PIN_0,OUTPUT_LOW);
  24. }
  25. void spi_set_clk_high( )
  26. {
  27. //GPIO_Set_IO_Value(PORT_B,GPIO_PIN_2,OUTPUT_HIGH);
  28. GPIO_Set_IO_Value(PORT_E,GPIO_PIN_0,OUTPUT_HIGH);
  29. }
  30. void spi_set_mosi_low( )
  31. {
  32. GPIO_Set_IO_Value(PORT_E,GPIO_PIN_1,OUTPUT_LOW);
  33. }
  34. void spi_set_mosi_hight( )
  35. {
  36. GPIO_Set_IO_Value(PORT_E,GPIO_PIN_1,OUTPUT_HIGH);
  37. }
  38. unsigned char spi_get_miso( )
  39. {
  40. return GPIO_Get_IO_Value(PORT_E,GPIO_PIN_2);
  41. }
  42. void spi_set_nss_low( )
  43. {
  44. GPIO_Set_IO_Value(PORT_E,GPIO_PIN_3,OUTPUT_LOW);
  45. }
  46. void spi_set_nss_high( )
  47. {
  48. GPIO_Set_IO_Value(PORT_E,GPIO_PIN_3,OUTPUT_HIGH);
  49. }
  50. /** 软件SPI */
  51. /**
  52. * @brief :SPI初始化(软件)
  53. * @param :无
  54. * @note :无
  55. * @retval:无
  56. */
  57. void drv_spi_init( void )
  58. {
  59. /*GPIO_Init_IO(PORT_B,GPIO_PIN_2,OUTPUT);
  60. GPIO_Init_IO(PORT_B,GPIO_PIN_3,OUTPUT);
  61. GPIO_Init_IO(PORT_E,GPIO_PIN_2,INPUT);
  62. GPIO_Init_IO(PORT_D,GPIO_PIN_2,OUTPUT);*/
  63. GPIO_Init_IO(PORT_E,GPIO_PIN_0,OUTPUT);
  64. GPIO_Init_IO(PORT_E,GPIO_PIN_3,OUTPUT);
  65. GPIO_Init_IO(PORT_E,GPIO_PIN_2,INPUT);
  66. GPIO_Init_IO(PORT_E,GPIO_PIN_1,OUTPUT);
  67. }
  68. /**
  69. * @brief :SPI收发一个字节
  70. * @param :
  71. * @TxByte: 发送的数据字节
  72. * @note :非堵塞式,一旦等待超时,函数会自动退出
  73. * @retval:接收到的字节
  74. */
  75. uint8_t drv_spi_read_write_byte( uint8_t TxByte )
  76. {
  77. uint8_t i = 0, Data = 0;
  78. spi_set_clk_low( );
  79. for( i = 0; i < 8; i++ ) //一个字节8byte需要循环8次
  80. {
  81. /** 发送 */
  82. if( 0x80 == ( TxByte & 0x80 ))
  83. {
  84. spi_set_mosi_hight( ); //如果即将要发送的位为 1 则置高IO引脚
  85. }
  86. else
  87. {
  88. spi_set_mosi_low( ); //如果即将要发送的位为 0 则置低IO引脚
  89. }
  90. TxByte <<= 1; //数据左移一位,先发送的是最高位
  91. spi_set_clk_high( ); //时钟线置高
  92. asm ("nop; nop");
  93. asm ("nop; nop");
  94. /** 接收 */
  95. Data <<= 1; //接收数据左移一位,先接收到的是最高位
  96. if( 1 == spi_get_miso( ))
  97. {
  98. Data |= 0x01; //如果接收时IO引脚为高则认为接收到 1
  99. }
  100. spi_set_clk_low( ); //时钟线置低
  101. asm ("nop; nop");
  102. asm ("nop; nop");
  103. }
  104. return Data; //返回接收到的字节
  105. }
  106. /**
  107. * @brief :SPI收发字符串
  108. * @param :
  109. * @ReadBuffer: 接收数据缓冲区地址
  110. * @WriteBuffer:发送字节缓冲区地址
  111. * @Length:字节长度
  112. * @note :非堵塞式,一旦等待超时,函数会自动退出
  113. * @retval:无
  114. */
  115. void drv_spi_read_write_string( uint8_t* ReadBuffer, uint8_t* WriteBuffer, uint16_t Length )
  116. {
  117. spi_set_nss_low( ); //片选拉低
  118. while( Length-- )
  119. {
  120. *ReadBuffer = drv_spi_read_write_byte( *WriteBuffer ); //收发数据
  121. ReadBuffer++;
  122. WriteBuffer++; //读写地址加1
  123. }
  124. spi_set_nss_high( ); //片选拉高
  125. }
  126. /** 软件SPI */

RF24L01的驱动函数,主要调用NRF24L01_Gpio_Init() RF24L01_Init() NRF24L01_check() RF24L01_Set_Mode() NRF24L01_TxPacket() 这几个函数就够用了。

  1. /**
  2. ******************************************************************************
  3. * @file dev_RF24L01.c
  4. * @author xxx
  5. * @version V1.0.0
  6. * @date 2020-1-03
  7. * @brief NRF24L01配置C文件
  8. ******************************************************************************
  9. */
  10. #include "common.h"
  11. const char *g_ErrorString = "RF24L01 is not find !...";
  12. /*
  13. * PTB2->SCK PTF0->CE
  14. * PTB3->MOSI PTE2->MISO
  15. * PTD2->CSN IRQ->PTA6
  16. *
  17. * PTE0->SCK PTG3->CE
  18. * PTE1->MOSI PTE2->MISO
  19. * PTE3->CSN IRQ->PTC7
  20. */
  21. void RF24L01_SET_CS_LOW()
  22. {
  23. GPIO_Set_IO_Value(PORT_E,GPIO_PIN_3,OUTPUT_LOW);
  24. }
  25. void RF24L01_SET_CS_HIGH()
  26. {
  27. GPIO_Set_IO_Value(PORT_E,GPIO_PIN_3,OUTPUT_HIGH);
  28. }
  29. void RF24L01_SET_CE_LOW()
  30. {
  31. GPIO_Set_IO_Value(PORT_G,GPIO_PIN_3,OUTPUT_LOW);
  32. }
  33. void RF24L01_SET_CE_HIGH()
  34. {
  35. GPIO_Set_IO_Value(PORT_G,GPIO_PIN_3,OUTPUT_HIGH);
  36. }
  37. unsigned char RF24L01_GET_IRQ_STATUS()
  38. {
  39. return GPIO_Get_IO_Value(PORT_C,GPIO_PIN_7);
  40. }
  41. /**
  42. * @brief :NRF24L01读寄存器
  43. * @param :
  44. @Addr:寄存器地址
  45. * @note :地址在设备中有效
  46. * @retval:读取的数据
  47. */
  48. uint8_t NRF24L01_Read_Reg( uint8_t RegAddr )
  49. {
  50. uint8_t btmp;
  51. RF24L01_SET_CS_LOW( ); //片选
  52. drv_spi_read_write_byte( NRF_READ_REG | RegAddr ); //读命令 地址
  53. btmp = drv_spi_read_write_byte( 0xFF ); //读数据
  54. RF24L01_SET_CS_HIGH( ); //取消片选
  55. return btmp;
  56. }
  57. /**
  58. * @brief :NRF24L01读指定长度的数据
  59. * @param :
  60. * @reg:地址
  61. * @pBuf:数据存放地址
  62. * @len:数据长度
  63. * @note :数据长度不超过255,地址在设备中有效
  64. * @retval:读取状态
  65. */
  66. void NRF24L01_Read_Buf( uint8_t RegAddr, uint8_t *pBuf, uint8_t len )
  67. {
  68. uint8_t btmp;
  69. RF24L01_SET_CS_LOW( ); //片选
  70. drv_spi_read_write_byte( NRF_READ_REG | RegAddr ); //读命令 地址
  71. for( btmp = 0; btmp < len; btmp ++ )
  72. {
  73. *( pBuf + btmp ) = drv_spi_read_write_byte( 0xFF ); //读数据
  74. }
  75. RF24L01_SET_CS_HIGH( ); //取消片选
  76. }
  77. /**
  78. * @brief :NRF24L01写寄存器
  79. * @param :无
  80. * @note :地址在设备中有效
  81. * @retval:读写状态
  82. */
  83. void NRF24L01_Write_Reg( uint8_t RegAddr, uint8_t Value )
  84. {
  85. RF24L01_SET_CS_LOW( ); //片选
  86. drv_spi_read_write_byte( NRF_WRITE_REG | RegAddr ); //写命令 地址
  87. drv_spi_read_write_byte( Value ); //写数据
  88. RF24L01_SET_CS_HIGH( ); //取消片选
  89. }
  90. /**
  91. * @brief :NRF24L01写指定长度的数据
  92. * @param :
  93. * @reg:地址
  94. * @pBuf:写入的数据地址
  95. * @len:数据长度
  96. * @note :数据长度不超过255,地址在设备中有效
  97. * @retval:写状态
  98. */
  99. void NRF24L01_Write_Buf( uint8_t RegAddr, uint8_t *pBuf, uint8_t len )
  100. {
  101. uint8_t i;
  102. RF24L01_SET_CS_LOW( ); //片选
  103. drv_spi_read_write_byte( NRF_WRITE_REG | RegAddr ); //写命令 地址
  104. for( i = 0; i < len; i ++ )
  105. {
  106. drv_spi_read_write_byte( *( pBuf + i ) ); //写数据
  107. }
  108. RF24L01_SET_CS_HIGH( ); //取消片选
  109. }
  110. /**
  111. * @brief :清空TX缓冲区
  112. * @param :无
  113. * @note :无
  114. * @retval:无
  115. */
  116. void NRF24L01_Flush_Tx_Fifo ( void )
  117. {
  118. RF24L01_SET_CS_LOW( ); //片选
  119. drv_spi_read_write_byte( FLUSH_TX ); //清TX FIFO命令
  120. RF24L01_SET_CS_HIGH( ); //取消片选
  121. }
  122. /**
  123. * @brief :清空RX缓冲区
  124. * @param :无
  125. * @note :无
  126. * @retval:无
  127. */
  128. void NRF24L01_Flush_Rx_Fifo( void )
  129. {
  130. RF24L01_SET_CS_LOW( ); //片选
  131. drv_spi_read_write_byte( FLUSH_RX ); //清RX FIFO命令
  132. RF24L01_SET_CS_HIGH( ); //取消片选
  133. }
  134. /**
  135. * @brief :重新使用上一包数据
  136. * @param :无
  137. * @note :无
  138. * @retval:无
  139. */
  140. void NRF24L01_Reuse_Tx_Payload( void )
  141. {
  142. RF24L01_SET_CS_LOW( ); //片选
  143. drv_spi_read_write_byte( REUSE_TX_PL ); //重新使用上一包命令
  144. RF24L01_SET_CS_HIGH( ); //取消片选
  145. }
  146. /**
  147. * @brief :NRF24L01空操作
  148. * @param :无
  149. * @note :无
  150. * @retval:无
  151. */
  152. void NRF24L01_Nop( void )
  153. {
  154. RF24L01_SET_CS_LOW( ); //片选
  155. drv_spi_read_write_byte( NOP ); //空操作命令
  156. RF24L01_SET_CS_HIGH( ); //取消片选
  157. }
  158. /**
  159. * @brief :NRF24L01读状态寄存器
  160. * @param :无
  161. * @note :无
  162. * @retval:RF24L01状态
  163. */
  164. uint8_t NRF24L01_Read_Status_Register( void )
  165. {
  166. uint8_t Status;
  167. RF24L01_SET_CS_LOW( ); //片选
  168. Status = drv_spi_read_write_byte( NRF_READ_REG + STATUS ); //读状态寄存器
  169. RF24L01_SET_CS_HIGH( ); //取消片选
  170. return Status;
  171. }
  172. /**
  173. * @brief :NRF24L01清中断
  174. * @param :
  175. @IRQ_Source:中断源
  176. * @note :无
  177. * @retval:清除后状态寄存器的值
  178. */
  179. uint8_t NRF24L01_Clear_IRQ_Flag( uint8_t IRQ_Source )
  180. {
  181. uint8_t btmp = 0;
  182. //IRQ_Source &= ( 1 << RX_DR ) | ( 1 << TX_DS ) | ( 1 << MAX_RT ); //中断标志处理
  183. btmp = NRF24L01_Read_Status_Register( ); //读状态寄存器
  184. RF24L01_SET_CS_LOW( ); //片选
  185. drv_spi_read_write_byte( NRF_WRITE_REG + STATUS ); //写状态寄存器命令
  186. drv_spi_read_write_byte( IRQ_Source | btmp ); //清相应中断标志
  187. RF24L01_SET_CS_HIGH( ); //取消片选
  188. return ( NRF24L01_Read_Status_Register( )); //返回状态寄存器状态
  189. }
  190. /**
  191. * @brief :读RF24L01中断状态
  192. * @param :无
  193. * @note :无
  194. * @retval:中断状态
  195. */
  196. uint8_t RF24L01_Read_IRQ_Status( void )
  197. {
  198. return ( NRF24L01_Read_Status_Register( ) & (( 1 << RX_DR ) | ( 1 << TX_DS ) | ( 1 << MAX_RT ))); //返回中断状态
  199. }
  200. /**
  201. * @brief :读FIFO中数据宽度
  202. * @param :无
  203. * @note :无
  204. * @retval:数据宽度
  205. */
  206. uint8_t NRF24L01_Read_Top_Fifo_Width( void )
  207. {
  208. uint8_t btmp;
  209. RF24L01_SET_CS_LOW( ); //片选
  210. drv_spi_read_write_byte( R_RX_PL_WID ); //读FIFO中数据宽度命令
  211. btmp = drv_spi_read_write_byte( 0xFF ); //读数据
  212. RF24L01_SET_CS_HIGH( ); //取消片选
  213. return btmp;
  214. }
  215. /**
  216. * @brief :读接收到的数据
  217. * @param :无
  218. * @note :无
  219. * @retval:
  220. @pRxBuf:数据存放地址首地址
  221. */
  222. uint8_t NRF24L01_Read_Rx_Payload( uint8_t *pRxBuf )
  223. {
  224. uint8_t Width, PipeNum;
  225. PipeNum = ( NRF24L01_Read_Reg( STATUS ) >> 1 ) & 0x07; //读接收状态
  226. Width = NRF24L01_Read_Top_Fifo_Width( ); //读接收数据个数
  227. RF24L01_SET_CS_LOW( ); //片选
  228. drv_spi_read_write_byte( RD_RX_PLOAD ); //读有效数据命令
  229. for( PipeNum = 0; PipeNum < Width; PipeNum ++ )
  230. {
  231. *( pRxBuf + PipeNum ) = drv_spi_read_write_byte( 0xFF ); //读数据
  232. }
  233. RF24L01_SET_CS_HIGH( ); //取消片选
  234. NRF24L01_Flush_Rx_Fifo( ); //清空RX FIFO
  235. return Width;
  236. }
  237. /**
  238. * @brief :发送数据(带应答)
  239. * @param :
  240. * @pTxBuf:发送数据地址
  241. * @len:长度
  242. * @note :一次不超过32个字节
  243. * @retval:无
  244. */
  245. void NRF24L01_Write_Tx_Payload_Ack( uint8_t *pTxBuf, uint8_t len )
  246. {
  247. uint8_t btmp;
  248. uint8_t length = ( len > 32 ) ? 32 : len; //数据长达大约32 则只发送32个
  249. NRF24L01_Flush_Tx_Fifo( ); //清TX FIFO
  250. RF24L01_SET_CS_LOW( ); //片选
  251. drv_spi_read_write_byte( WR_TX_PLOAD ); //发送命令
  252. for( btmp = 0; btmp < length; btmp ++ )
  253. {
  254. drv_spi_read_write_byte( *( pTxBuf + btmp ) ); //发送数据
  255. }
  256. RF24L01_SET_CS_HIGH( ); //取消片选
  257. }
  258. /**
  259. * @brief :发送数据(不带应答)
  260. * @param :
  261. * @pTxBuf:发送数据地址
  262. * @len:长度
  263. * @note :一次不超过32个字节
  264. * @retval:无
  265. */
  266. void NRF24L01_Write_Tx_Payload_NoAck( uint8_t *pTxBuf, uint8_t len )
  267. {
  268. if( len > 32 || len == 0 )
  269. {
  270. return ; //数据长度大于32 或者等于0 不执行
  271. }
  272. RF24L01_SET_CS_LOW( ); //片选
  273. drv_spi_read_write_byte( WR_TX_PLOAD_NACK ); //发送命令
  274. while( len-- )
  275. {
  276. drv_spi_read_write_byte( *pTxBuf ); //发送数据
  277. pTxBuf++;
  278. }
  279. RF24L01_SET_CS_HIGH( ); //取消片选
  280. }
  281. /**
  282. * @brief :在接收模式下向TX FIFO写数据(带ACK)
  283. * @param :
  284. * @pData:数据地址
  285. * @len:长度
  286. * @note :一次不超过32个字节
  287. * @retval:无
  288. */
  289. void NRF24L01_Write_Tx_Payload_InAck( uint8_t *pData, uint8_t len )
  290. {
  291. uint8_t btmp;
  292. len = ( len > 32 ) ? 32 : len; //数据长度大于32个则只写32个字节
  293. RF24L01_SET_CS_LOW( ); //片选
  294. drv_spi_read_write_byte( W_ACK_PLOAD ); //命令
  295. for( btmp = 0; btmp < len; btmp ++ )
  296. {
  297. drv_spi_read_write_byte( *( pData + btmp ) ); //写数据
  298. }
  299. RF24L01_SET_CS_HIGH( ); //取消片选
  300. }
  301. /**
  302. * @brief :设置发送地址
  303. * @param :
  304. * @pAddr:地址存放地址
  305. * @len:长度
  306. * @note :无
  307. * @retval:无
  308. */
  309. void NRF24L01_Set_TxAddr( uint8_t *pAddr, uint8_t len )
  310. {
  311. len = ( len > 5 ) ? 5 : len; //地址不能大于5个字节
  312. NRF24L01_Write_Buf( TX_ADDR, pAddr, len ); //写地址
  313. }
  314. /**
  315. * @brief :设置接收通道地址
  316. * @param :
  317. * @PipeNum:通道
  318. * @pAddr:地址存肥着地址
  319. * @Len:长度
  320. * @note :通道不大于5 地址长度不大于5个字节
  321. * @retval:无
  322. */
  323. void NRF24L01_Set_RxAddr( uint8_t PipeNum, uint8_t *pAddr, uint8_t Len )
  324. {
  325. Len = ( Len > 5 ) ? 5 : Len;
  326. PipeNum = ( PipeNum > 5 ) ? 5 : PipeNum; //通道不大于5 地址长度不大于5个字节
  327. NRF24L01_Write_Buf( RX_ADDR_P0 + PipeNum, pAddr, Len ); //写入地址
  328. }
  329. /**
  330. * @brief :设置通信速度
  331. * @param :
  332. * @Speed:速度
  333. * @note :无
  334. * @retval:无
  335. */
  336. void NRF24L01_Set_Speed( nRf24l01SpeedType Speed )
  337. {
  338. uint8_t btmp = 0;
  339. btmp = NRF24L01_Read_Reg( RF_SETUP );
  340. btmp &= ~( ( 1<<5 ) | ( 1<<3 ) );
  341. if( Speed == SPEED_250K ) //250K
  342. {
  343. btmp |= ( 1<<5 );
  344. }
  345. else if( Speed == SPEED_1M ) //1M
  346. {
  347. btmp &= ~( ( 1<<5 ) | ( 1<<3 ) );
  348. }
  349. else if( Speed == SPEED_2M ) //2M
  350. {
  351. btmp |= ( 1<<3 );
  352. }
  353. NRF24L01_Write_Reg( RF_SETUP, btmp );
  354. }
  355. /**
  356. * @brief :设置功率
  357. * @param :
  358. * @Speed:速度
  359. * @note :无
  360. * @retval:无
  361. */
  362. void NRF24L01_Set_Power( nRf24l01PowerType Power )
  363. {
  364. uint8_t btmp;
  365. btmp = NRF24L01_Read_Reg( RF_SETUP ) & ~0x07;
  366. switch( Power )
  367. {
  368. case POWER_F18DBM:
  369. btmp |= PWR_18DB;
  370. break;
  371. case POWER_F12DBM:
  372. btmp |= PWR_12DB;
  373. break;
  374. case POWER_F6DBM:
  375. btmp |= PWR_6DB;
  376. break;
  377. case POWER_0DBM:
  378. btmp |= PWR_0DB;
  379. break;
  380. default:
  381. break;
  382. }
  383. NRF24L01_Write_Reg( RF_SETUP, btmp );
  384. }
  385. /**
  386. * @brief :设置频率
  387. * @param :
  388. * @FreqPoint:频率设置参数
  389. * @note :值不大于127
  390. * @retval:无
  391. */
  392. void RF24LL01_Write_Hopping_Point( uint8_t FreqPoint )
  393. {
  394. NRF24L01_Write_Reg( RF_CH, FreqPoint & 0x7F );
  395. }
  396. /**
  397. * @brief :NRF24L01检测
  398. * @param :无
  399. * @note :无
  400. * @retval:无
  401. */
  402. void NRF24L01_check( void )
  403. {
  404. uint8_t i;
  405. uint8_t buf[5]={ 0XA5, 0XA5, 0XA5, 0XA5, 0XA5 };
  406. uint8_t read_buf[ 5 ] = { 0 };
  407. while( 1 )
  408. {
  409. NRF24L01_Write_Buf( TX_ADDR, buf, 5 ); //写入5个字节的地址
  410. NRF24L01_Read_Buf( TX_ADDR, read_buf, 5 ); //读出写入的地址
  411. for( i = 0; i < 5; i++ )
  412. {
  413. if( buf[ i ] != read_buf[ i ] )
  414. {
  415. break;
  416. }
  417. }
  418. if( 5 == i )
  419. {
  420. break;
  421. }
  422. else
  423. {
  424. //drv_uart_tx_bytes( (uint8_t *)g_ErrorString, 26 );
  425. }
  426. //Delay_1ms( 4 * 500 );
  427. Delay_1ms( 4 * 5 );
  428. }
  429. }
  430. /**
  431. * @brief :设置模式
  432. * @param :
  433. * @Mode:模式发送模式或接收模式
  434. * @note :无
  435. * @retval:无
  436. */
  437. void RF24L01_Set_Mode( nRf24l01ModeType Mode )
  438. {
  439. uint8_t controlreg = 0;
  440. RF24L01_SET_CE_LOW( );
  441. controlreg = NRF24L01_Read_Reg( CONFIG );
  442. if( Mode == MODE_TX )
  443. {
  444. controlreg &= ~( 1<< PRIM_RX );
  445. }
  446. else
  447. {
  448. if( Mode == MODE_RX )
  449. {
  450. uint8_t addr[5] = {INIT_ADDR};
  451. NRF24L01_Set_RxAddr( 0, &addr[0], 5 );
  452. controlreg |= ( 1<< PRIM_RX );
  453. controlreg &= ~( 1<< MASK_RX_DR );
  454. }
  455. }
  456. NRF24L01_Write_Reg( CONFIG, controlreg );
  457. RF24L01_SET_CE_HIGH( );
  458. Delay_1us(130);
  459. }
  460. /**
  461. * @brief :NRF24L01发送一次数据
  462. * @param :
  463. * @txbuf:待发送数据首地址
  464. * @Length:发送数据长度
  465. * @note :无
  466. * @retval:
  467. * MAX_TX:达到最大重发次数
  468. * TX_OK:发送完成
  469. * 0xFF:其他原因
  470. */
  471. uint8_t NRF24L01_TxPacket( uint8_t *txbuf, uint8_t Length )
  472. {
  473. uint8_t l_Status = 0;
  474. uint8_t addr[5] = {INIT_ADDR};
  475. RF24L01_SET_CE_LOW( );
  476. NRF24L01_Set_TxAddr( &addr[0], 5 ); //设置TX地址
  477. NRF24L01_Write_Buf( WR_TX_PLOAD, txbuf, Length ); //写数据到TX BUF 32字节 TX_PLOAD_WIDTH.
  478. RF24L01_SET_CE_HIGH( );
  479. Delay_1us(130);
  480. l_Status = NRF24L01_Read_Reg(STATUS); //读状态寄存器
  481. NRF24L01_Write_Reg( STATUS, l_Status ); //清除TX_DS或MAX_RT中断标志
  482. if( l_Status & MAX_TX ) //达到最大重发次数
  483. {
  484. NRF24L01_Write_Reg( FLUSH_TX,0xff ); //清除TX FIFO寄存器
  485. drv_spi_read_write_byte( FLUSH_TX );
  486. return MAX_TX;
  487. }
  488. if( l_Status & TX_OK ) //发送完成
  489. {
  490. return TX_OK;
  491. }
  492. return 0xFF; //其他原因发送失败
  493. }
  494. /**
  495. * @brief :NRF24L01接收数据
  496. * @param :
  497. * @rxbuf:接收数据存放地址
  498. * @note :无
  499. * @retval:接收的数据个数
  500. */
  501. uint8_t NRF24L01_RxPacket( uint8_t *rxbuf )
  502. {
  503. uint8_t l_Status = 0, l_RxLength = 0, l_100MsTimes = 0;
  504. l_Status = NRF24L01_Read_Reg( STATUS ); //读状态寄存器
  505. NRF24L01_Write_Reg( STATUS,l_Status ); //清中断标志
  506. /*RF24L01_SET_CS_LOW( ); //片选
  507. drv_spi_read_write_byte( FLUSH_RX );
  508. RF24L01_SET_CS_HIGH( );*/
  509. //while( 0 != RF24L01_GET_IRQ_STATUS( ))
  510. /*{
  511. Delay_1ms( 100 );
  512. if( 30 == l_100MsTimes++ ) //3s没接收过数据,重新初始化模块
  513. {
  514. NRF24L01_Gpio_Init( );
  515. RF24L01_Init( );
  516. RF24L01_Set_Mode( MODE_RX );
  517. //break;
  518. }
  519. }
  520. l_Status = NRF24L01_Read_Reg( STATUS ); //读状态寄存器
  521. NRF24L01_Write_Reg( STATUS,l_Status ); //清中断标志
  522. if( l_Status & RX_OK) //接收到数据
  523. {
  524. l_RxLength = NRF24L01_Read_Reg( R_RX_PL_WID ); //读取接收到的数据个数
  525. NRF24L01_Read_Buf( RD_RX_PLOAD,rxbuf,l_RxLength ); //接收到数据
  526. NRF24L01_Write_Reg( FLUSH_RX,0xff ); //清除RX FIFO
  527. return l_RxLength;
  528. }
  529. return 0; //没有收到数据 */
  530. }
  531. /**
  532. * @brief :RF24L01引脚初始化
  533. * PTB2->SCK PTF0->CE
  534. * PTB3->MOSI PTE2->MISO
  535. * PTD2->CSN IRQ->PTA6
  536. *
  537. * PTE0->SCK PTG3->CE
  538. * PTE1->MOSI PTE2->MISO
  539. * PTE3->CSN IRQ->PTC7
  540. * @param :无
  541. * @note :无
  542. * @retval:无
  543. */
  544. void NRF24L01_Gpio_Init( void )
  545. {
  546. GPIO_Init_IO(PORT_C,GPIO_PIN_7,INPUT);
  547. GPIO_Init_IO(PORT_G,GPIO_PIN_3,OUTPUT);
  548. KBI_Init(PORT_C,GPIO_PIN_7,FALLING);
  549. }
  550. /**
  551. * @brief :RF24L01模块初始化
  552. * @param :无
  553. * @note :无
  554. * @retval:无
  555. */
  556. void RF24L01_Init( void )
  557. {
  558. uint8_t addr[5] = {INIT_ADDR};
  559. RF24L01_SET_CE_LOW( );
  560. NRF24L01_Write_Reg( RX_PW_P0, 8 );
  561. NRF24L01_Write_Reg( CONFIG, 0x7e ); //接收中断
  562. NRF24L01_Write_Reg( EN_AA, ( 0 ) ); //禁止通道0自动应答
  563. NRF24L01_Write_Reg( EN_RXADDR, ( 1 ) ); //通道0接收
  564. NRF24L01_Write_Reg( SETUP_AW, AW_5BYTES ); //地址宽度 5个字节
  565. NRF24L01_Write_Reg( SETUP_RETR, 0x0a ); //重复等待时间 250us
  566. NRF24L01_Write_Reg( RF_CH, 40 ); //初始化通道
  567. NRF24L01_Write_Reg( RF_SETUP, 0x07 );
  568. NRF24L01_Set_TxAddr( &addr[0], 5 ); //设置TX地址
  569. NRF24L01_Set_RxAddr( 0, &addr[0], 5 ); //设置RX地址
  570. RF24L01_SET_CE_HIGH( );
  571. Delay_1ms(1);
  572. }

IRQ接收中断处理函数

  1. void KBI0_IRQHandler()
  2. {
  3. uint8_t l_Status = 0, l_RxLength = 0, l_100MsTimes = 0;
  4. unsigned char rxbuf[8];
  5. l_Status = NRF24L01_Read_Reg( STATUS ); //读状态寄存器
  6. NRF24L01_Write_Reg( STATUS,l_Status ); //清中断标志
  7. if( l_Status & RX_OK) //接收到数据
  8. {
  9. l_RxLength = NRF24L01_Read_Reg( R_RX_PL_WID ); //读取接收到的数据个数
  10. NRF24L01_Read_Buf( RD_RX_PLOAD,rxbuf,l_RxLength ); //接收到数据
  11. NRF24L01_Write_Reg( FLUSH_RX,0xff ); //清除RX FIFO
  12. GPIO_Toggle_IO_Value(PORT_C,GPIO_PIN_0);
  13. return l_RxLength;
  14. }
  15. KBI0_SC |= KBI_SC_KBACK_MASK; // clear interrupt flag
  16. }

调试备忘录-nRF24L01P的使用(教程 + 源码)的更多相关文章

  1. Eclipse开发环境debug模式调试断点从jar跳到源码

    Eclipse开发环境debug模式调试断点从jar跳到源码 说明:本案例使用jsch-0.1.54.jar和源码做test,项目分成两个,一个是jsch的源码,另一个是测试案例 一.下载JSch.的 ...

  2. 调试 .NET Framework 源代码、.DotNetCore源码

    调试 .NET Framework 源代码..DotNetCore源码 如何调试 .NET Framework 源代码 在 Visual Studio 调试器中指定符号 (.pdb) 和源文件 .NE ...

  3. 手把手教你调试SpringBoot启动 IoC容器初始化源码,spring如何解决循环依赖

    授人以鱼不如授人以渔,首先声明这篇文章并没有过多的总结和结论,主要内容是教大家如何一步一步自己手动debug调试源码,然后总结spring如何解决的循环依赖,最后,操作很简单,有手就行. 本次调试 是 ...

  4. 如何调试最新的asp.net mvc源码

    vs2013调试 一.源码当前为5.2.0.0,按下面改为5.0.0.1 二./web.config 版本为5.0.0.0 改为5.0.0.1 三.vs2013 x86 本机工具命令提示 sn.exe ...

  5. 实时滚动图表绘制方法: LightningChart教程 + 源码下载

    LightningChart图形控件彻底发挥了GPU加速和性能优化的最大效应,能够实时呈现超过10亿数据点的庞大数据,为大家提供先进与快速的图表库.这里的实时图实现的比较简单,大家先试一下这个效果,熟 ...

  6. unity3d俄罗斯方块源码教程+源码和程序下载

    小时候,大家都应玩过或听说过<俄罗斯方块>,它是红白机,掌机等一些电子设备中最常见的一款游戏.而随着时代的发展,信息的进步,游戏画面从简单的黑白方块到彩色方块,游戏的玩法机制从最简单的消方 ...

  7. Android 视频 教程 源码 电子书 网址

    资源名称 资源地址 下载量 好评率8天快速掌握Android视频教程67集(附源码)http://down.51cto.com/zt/2197 32157Android开发入门之实战技巧和源码 htt ...

  8. [参考资料] 80个Python经典资料(教程+源码+工具)汇总

    AD : 2018重磅地面课程<机器读心术之语音识别前沿实战特训营>,迈向人工智能新高度 [专题推荐]Python系列英文原版电子书 http://down.51cto.com/zt/10 ...

  9. 80个Python经典资料(教程+源码+工具)汇总——下载目录 ...

    原文转自:http://bbs.51cto.com/thread-935214-1.html 大家好,51CTO下载中心根据资料的热度和好评度收集了80个Python资料,分享给Python开发的同学 ...

随机推荐

  1. noi linux gedit 配置(c++环境)

    基本配置 方法一 查看所有命令: gsettings list-recursively | grep -i gedit 命令解释 gsettings set org.gnome.gedit.prefe ...

  2. 微信小程序反编译~2020年

    目录 摘要 介绍 安装反编译脚本 使用 获取wxapkg文件 反编译 结论 参考资料 摘要 安装wxappUnpacker小程序反编译工具并使用(2020.03) 关键词: 微信小程序反编译 wxss ...

  3. Windows电脑多个SSH Key管理.md

    笔者偏在阿里云,Github,开源中国上均存放一些私有项目代码,因此需要再Windows电脑上配置多个SSH Key 环境 操作系统:windows 7 Git 提示:Git 安装后就可以使用 Git ...

  4. 解决用vscode开发arduino时Serial未定义

    在工作目录编辑c_cpp_properties.json文件 添加defines字段 { "configurations": [ { "name": " ...

  5. commvalut oracle backup command

    run { allocate channel ch1 type 'sbt_tape'PARMS="SBT_LIBRARY=<software_installation_path> ...

  6. redis,rabbitmq,SqlAlchemy

    redis发布和订阅

  7. 关于android的监听器

    import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.os.Bu ...

  8. Python网络编程基础 PDF 完整超清版|网盘链接内附提取码下载|

    点此获取下载地址提取码:y9u5 Python网络编程最好新手入门书籍!175个详细案例,事实胜于雄辩,Sockets.DNS.Web Service.FTP.Email.SMTP.POP.IMAP. ...

  9. Python字符串内建函数_上

    Python字符串内建函数: 注:汉字属于字符(既是大写又是小写).数字可以是: Unicode 数字,全角数字(双字节),罗马数字,汉字数字. 1.capitalize( ): 将字符串第一个字母大 ...

  10. nonlocal 访问变量

    def counter(start = 0): def incr(): nonlocal start #分别保存每一个变量的临时值.类似yield start += 1 return start re ...