微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 第079例:SPI-NRF24L01无线模块(一对多通信)

第079例:SPI-NRF24L01无线模块(一对多通信)

时间:10-02 整理:3721RD 点击:
【HAL库每天一例】系列例程从今天开始持续更新。
我们将坚持每天至少发布一个基于YS-F1Pro开发板的HAL库例程,
该系列例程将带领大家从零开始使用HAL库,后面会持续添加模块应用例程。
同样的,我们还程序发布基于HAL库的指导文档和视频教程,欢迎持续关注,并提出改进意见。
例程下载:
资料包括程序、相关说明资料以及软件使用截图
百度云链接:http://pan.baidu.com/s/1i574oPv
密码:r3s3

(硬石YS-F1Pro开发板HAL库例程持续更新\2. 软件设计之高级裸机例程(HAL库版本)\YSF1_HAL-113. SPI-NRF24L01无线模块(一对多通信))
/**
  ******************************************************************************
  *                           硬石YS-F1Pro开发板例程功能说明
  *
  *  例程名称: 终端
  *   
  ******************************************************************************
  * 说明:
  * 本例程配套硬石stm32开发板YS-F1Pro使用。
  *
  * 淘宝:
  * 论坛:http://www.ing10bbs.com
  * 版权归硬石嵌入式开发团队所有,请勿商用。
  ******************************************************************************
  */
/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/







终端
bsp_NRF24L01.c文件内容

  1. /**
  2.   ******************************************************************************
  3.   * 文件名程: bsp_NRF24L01.c
  4.   * 作    者: 硬石嵌入式开发团队
  5.   * 版    本: V1.0
  6.   * 编写日期: 2015-10-04
  7.   * 功    能: NRF24L01无线模块底层驱动实现
  8.   ******************************************************************************
  9.   * 说明:
  10.   * 本例程配套硬石stm32开发板YS-F1Pro使用。
  11.   *
  12.   * 淘宝:
  13.   * 论坛:http://www.ing10bbs.com
  14.   * 版权归硬石嵌入式开发团队所有,请勿商用。
  15.   ******************************************************************************
  16.   */

  17. /* 包含头文件 ----------------------------------------------------------------*/
  18. #include "NRF24L01/bsp_NRF24L01.h"

  19. /* 私有类型定义 --------------------------------------------------------------*/
  20. /* 私有宏定义 ----------------------------------------------------------------*/                              
  21. /* 私有变量 ------------------------------------------------------------------*/
  22. SPI_HandleTypeDef hspi_NRF24L01;
  23. uint8_t TX_ADDRESS[TX_ADR_WIDTH]= {0xb0,0x43,0x10,0x10,0x01}; //发送地址
  24. uint8_t RX_ADDRESS0[RX_ADR_WIDTH]={0xb0,0x43,0x10,0x10,0x01};        //接收地址
  25. uint8_t RX_ADDRESS1[RX_ADR_WIDTH]={0xb1,0x43,0x10,0x10,0x01};        //接收地址1
  26. uint8_t RX_ADDRESS2[RX_ADR_WIDTH]= {0xb2,0x43,0x10,0x10,0x01};        //接收地址2
  27. uint8_t RX_ADDRESS3[RX_ADR_WIDTH]= {0xb3,0x43,0x10,0x10,0x01};        //接收地址3
  28. uint8_t RX_ADDRESS4[RX_ADR_WIDTH]= {0xb4,0x43,0x10,0x10,0x01};        //接收地址4
  29. uint8_t RX_ADDRESS5[RX_ADR_WIDTH]= {0xb5,0x43,0x10,0x10,0x01};        //接收地址5

  30. /* 扩展变量 ------------------------------------------------------------------*/
  31. /* 私有函数原形 --------------------------------------------------------------*/
  32. /* 函数体 --------------------------------------------------------------------*/

  33. /**
  34.   * 函数功能: 串行FLASH初始化
  35.   * 输入参数: huart:串口句柄类型指针
  36.   * 返 回 值: 无
  37.   * 说    明: 该函数被HAL库内部调用
  38. */
  39. void NRF24L01_SPI_Init(void)
  40. {
  41.   hspi_NRF24L01.Instance = NRF24L01_SPIx;
  42.   hspi_NRF24L01.Init.Mode = SPI_MODE_MASTER;
  43.   hspi_NRF24L01.Init.Direction = SPI_DIRECTION_2LINES;
  44.   hspi_NRF24L01.Init.DataSize = SPI_DATASIZE_8BIT;
  45.   hspi_NRF24L01.Init.CLKPolarity = SPI_POLARITY_LOW;
  46.   hspi_NRF24L01.Init.CLKPhase = SPI_PHASE_1EDGE;
  47.   hspi_NRF24L01.Init.NSS = SPI_NSS_SOFT;
  48.   hspi_NRF24L01.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  49.   hspi_NRF24L01.Init.FirstBit = SPI_FIRSTBIT_MSB;
  50.   hspi_NRF24L01.Init.TIMode = SPI_TIMODE_DISABLE;
  51.   hspi_NRF24L01.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  52.   hspi_NRF24L01.Init.CRCPolynomial = 10;
  53.   HAL_SPI_Init(&hspi_NRF24L01);
  54.   
  55.   __HAL_SPI_ENABLE(&hspi_NRF24L01);
  56. }

  57. /**
  58.   * 函数功能: SPI外设系统级初始化
  59.   * 输入参数: hspi:SPI句柄类型指针
  60.   * 返 回 值: 无
  61.   * 说    明: 该函数被HAL库内部调用
  62.   */
  63. void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
  64. {
  65.   GPIO_InitTypeDef GPIO_InitStruct;
  66.   if(hspi->Instance==NRF24L01_SPIx)
  67.   {
  68.     /* SPI外设时钟使能 */
  69.     NRF24L01_SPIx_RCC_CLK_ENABLE();
  70.     /* GPIO外设时钟使能 */
  71.     NRF24L01_SPI_GPIO_ClK_ENABLE();
  72.     NRF24L01_SPI_CS_CLK_ENABLE();
  73.     NRF24L01_CE_CLK_ENABLE();
  74.     NRF24L01_IRQ_CLK_ENABLE();
  75.    
  76.     /* Disable the Serial Wire Jtag Debug Port SWJ-DP */
  77.     __HAL_AFIO_REMAP_SWJ_DISABLE();
  78.    
  79.     /**SPI3 GPIO Configuration   
  80.     PF11     ------> SPI3_NSS
  81.     PB3      ------> SPI3_SCK
  82.     PB4      ------> SPI3_MISO
  83.     PB5      ------> SPI3_MOSI
  84.     */
  85.     GPIO_InitStruct.Pin = NRF24L01_SPI_SCK_PIN|NRF24L01_SPI_MOSI_PIN;
  86.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  87.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  88.     HAL_GPIO_Init(NRF24L01_SPI_GPIO_PORT, &GPIO_InitStruct);

  89.     GPIO_InitStruct.Pin = NRF24L01_SPI_MISO_PIN;
  90.     GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  91.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  92.     HAL_GPIO_Init(NRF24L01_SPI_GPIO_PORT, &GPIO_InitStruct);
  93.    
  94.     HAL_GPIO_WritePin(NRF24L01_SPI_CS_PORT, NRF24L01_SPI_CS_PIN, GPIO_PIN_SET);
  95.     GPIO_InitStruct.Pin = NRF24L01_SPI_CS_PIN;
  96.     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  97.     HAL_GPIO_Init(NRF24L01_SPI_CS_PORT, &GPIO_InitStruct);
  98.    
  99.     HAL_GPIO_WritePin(NRF24L01_CE_PORT, NRF24L01_CE_PIN, GPIO_PIN_RESET);
  100.     GPIO_InitStruct.Pin = NRF24L01_CE_PIN;
  101.     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  102.     HAL_GPIO_Init(NRF24L01_CE_PORT, &GPIO_InitStruct);
  103.    
  104.     GPIO_InitStruct.Pin = NRF24L01_IRQ_PIN;
  105.     GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  106.     GPIO_InitStruct.Pull = GPIO_PULLUP;
  107.     HAL_GPIO_Init(NRF24L01_IRQ_PORT, &GPIO_InitStruct);
  108.   }
  109. }

  110. /**
  111.   * 函数功能: SPI外设系统级反初始化
  112.   * 输入参数: hspi:SPI句柄类型指针
  113.   * 返 回 值: 无
  114.   * 说    明: 该函数被HAL库内部调用
  115.   */
  116. void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi)
  117. {

  118.   if(hspi->Instance==NRF24L01_SPIx)
  119.   {
  120.     /* SPI外设时钟禁用 */
  121.     NRF24L01_SPIx_RCC_CLK_DISABLE();
  122.   
  123.     /**SPI3 GPIO Configuration   
  124.     PF11     ------> SPI3_NSS
  125.     PB3      ------> SPI3_SCK
  126.     PB4      ------> SPI3_MISO
  127.     PB5      ------> SPI3_MOSI
  128.     */
  129.     HAL_GPIO_DeInit(NRF24L01_SPI_GPIO_PORT, NRF24L01_SPI_SCK_PIN|NRF24L01_SPI_MISO_PIN|NRF24L01_SPI_MOSI_PIN);
  130.     HAL_GPIO_DeInit(NRF24L01_SPI_CS_PORT, NRF24L01_SPI_CS_PIN);
  131.     HAL_GPIO_DeInit(NRF24L01_CE_PORT, NRF24L01_CE_PIN);
  132.     HAL_GPIO_DeInit(NRF24L01_IRQ_PORT, NRF24L01_IRQ_PIN);
  133.   }
  134. }


  135. /**
  136.   * 函数功能: 往串行Flash读取写入一个字节数据并接收一个字节数据
  137.   * 输入参数: byte:待发送数据
  138.   * 返 回 值: uint8_t:接收到的数据
  139.   * 说    明:无
  140.   */
  141. uint8_t SPIx_ReadWriteByte(SPI_HandleTypeDef* hspi,uint8_t byte)
  142. {
  143.   uint8_t d_read,d_send=byte;
  144.   if(HAL_SPI_TransmitReceive(hspi,&d_send,&d_read,1,0xFF)!=HAL_OK)
  145.   {
  146.     d_read=0xFF;
  147.   }
  148.   return d_read;
  149. }

  150. /**
  151.   * 函数功能: 检测24L01是否存在
  152.   * 输入参数: 无
  153.   * 返 回 值: 0,成功;1,失败
  154.   * 说    明:无         
  155.   */
  156. uint8_t NRF24L01_Check(void)
  157. {
  158.         uint8_t buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
  159.         uint8_t i;
  160.         NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,buf,5);//写入5个字节的地址.       
  161.         NRF24L01_Read_Buf(TX_ADDR,buf,5); //读出写入的地址  
  162.         for(i=0;i<5;i++)if(buf[i]!=0XA5)break;                                                                   
  163.         if(i!=5)return 1;//检测24L01错误       
  164.         return 0;                 //检测到24L01
  165. }                  

  166. /**
  167.   * 函数功能: SPI写寄存器
  168.   * 输入参数: 无
  169.   * 返 回 值: 无
  170.   * 说    明:reg:指定寄存器地址
  171.   *           
  172.   */
  173. uint8_t NRF24L01_Write_Reg(uint8_t reg,uint8_t value)
  174. {
  175.         uint8_t status;       
  176.   NRF24L01_SPI_CS_ENABLE();                 //使能SPI传输
  177.   status =SPIx_ReadWriteByte(&hspi_NRF24L01,reg);//发送寄存器号
  178.   SPIx_ReadWriteByte(&hspi_NRF24L01,value);      //写入寄存器的值
  179.   NRF24L01_SPI_CS_DISABLE();                 //禁止SPI传输          
  180.   return(status);                               //返回状态值
  181. }

  182. /**
  183.   * 函数功能: 读取SPI寄存器值
  184.   * 输入参数: 无
  185.   * 返 回 值: 无
  186.   * 说    明:reg:要读的寄存器
  187.   *           
  188.   */
  189. uint8_t NRF24L01_Read_Reg(uint8_t reg)
  190. {
  191.         uint8_t reg_val;            
  192.         NRF24L01_SPI_CS_ENABLE();          //使能SPI传输               
  193.   SPIx_ReadWriteByte(&hspi_NRF24L01,reg);   //发送寄存器号
  194.   reg_val=SPIx_ReadWriteByte(&hspi_NRF24L01,0XFF);//读取寄存器内容
  195.   NRF24L01_SPI_CS_DISABLE();          //禁止SPI传输                    
  196.   return(reg_val);           //返回状态值
  197. }       

  198. /**
  199.   * 函数功能: 在指定位置读出指定长度的数据
  200.   * 输入参数: 无
  201.   * 返 回 值: 此次读到的状态寄存器值
  202.   * 说    明:无
  203.   *           
  204.   */
  205. uint8_t NRF24L01_Read_Buf(uint8_t reg,uint8_t *pBuf,uint8_t len)
  206. {
  207.         uint8_t status,uint8_t_ctr;          
  208.   
  209.   NRF24L01_SPI_CS_ENABLE();           //使能SPI传输
  210.   status=SPIx_ReadWriteByte(&hspi_NRF24L01,reg);//发送寄存器值(位置),并读取状态值             
  211.         for(uint8_t_ctr=0;uint8_t_ctr<len;uint8_t_ctr++)
  212.   {
  213.     pBuf[uint8_t_ctr]=SPIx_ReadWriteByte(&hspi_NRF24L01,0XFF);//读出数据
  214.   }
  215.   NRF24L01_SPI_CS_DISABLE();       //关闭SPI传输
  216.   return status;        //返回读到的状态值
  217. }

  218. /**
  219.   * 函数功能: 在指定位置写指定长度的数据
  220.   * 输入参数: 无
  221.   * 返 回 值: 无
  222.   * 说    明:reg:寄存器(位置)  *pBuf:数据指针  len:数据长度
  223.   *           
  224.   */
  225. uint8_t NRF24L01_Write_Buf(uint8_t reg, uint8_t *pBuf, uint8_t len)
  226. {
  227.         uint8_t status,uint8_t_ctr;            
  228.         NRF24L01_SPI_CS_ENABLE();          //使能SPI传输
  229.   status = SPIx_ReadWriteByte(&hspi_NRF24L01,reg);//发送寄存器值(位置),并读取状态值
  230.   for(uint8_t_ctr=0; uint8_t_ctr<len; uint8_t_ctr++)
  231.   {
  232.     SPIx_ReadWriteByte(&hspi_NRF24L01,*pBuf++); //写入数据         
  233.   }
  234.   NRF24L01_SPI_CS_DISABLE();       //关闭SPI传输
  235.   return status;          //返回读到的状态值
  236. }                                  

  237. /**
  238.   * 函数功能: 启动NRF24L01发送一次数据
  239.   * 输入参数: 无
  240.   * 返 回 值: 发送完成状况
  241.   * 说    明:txbuf:待发送数据首地址
  242.   *           
  243.   */
  244. uint8_t NRF24L01_TxPacket(uint8_t *txbuf)
  245. {
  246.         uint8_t sta;
  247.         NRF24L01_CE_LOW();
  248.   NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//写数据到TX BUF  32个字节
  249.         NRF24L01_CE_HIGH();//启动发送         
  250.   
  251.         while(NRF24L01_IRQ_PIN_READ()!=0);//等待发送完成
  252.   
  253.         sta=NRF24L01_Read_Reg(STATUS);  //读取状态寄存器的值          
  254.         NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志
  255.         if(sta&MAX_TX)//达到最大重发次数
  256.         {
  257.                 NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器
  258.                 return MAX_TX;
  259.         }
  260.         if(sta&TX_OK)//发送完成
  261.         {
  262.                 return TX_OK;
  263.         }
  264.         return 0xff;//其他原因发送失败
  265. }

  266. /**
  267.   * 函数功能:启动NRF24L01接收一次数据
  268.   * 输入参数: 无
  269.   * 返 回 值: 无
  270.   * 说    明:无
  271.   *           
  272.   */
  273. uint8_t NRF24L01_RxPacket(uint8_t *rxbuf)
  274. {
  275.         uint8_t sta;                                                                              
  276.         sta=NRF24L01_Read_Reg(STATUS);  //读取状态寄存器的值             
  277.         NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志
  278.         if(sta&RX_OK)//接收到数据
  279.         {
  280.                 NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据
  281.                 NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
  282.                 return 0;
  283.         }          
  284.         return 1;//没收到任何数据
  285. }                                            

  286. /**
  287.   * 函数功能: 该函数初始化NRF24L01到RX模式
  288.   * 输入参数: 无
  289.   * 返 回 值: 无
  290.   * 说    明:无
  291.   *           
  292.   */
  293. void NRF24L01_RX_Mode(void)
  294. {
  295.         NRF24L01_CE_LOW();          
  296.   NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0F);//配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC
  297.   NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x3f);    //使能通道0的自动应答   
  298.   NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x3f);//使能通道0的接收地址           
  299.   NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);             //设置RF通信频率                  
  300.   NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);//设置TX发射参数,0db增益,2Mbps,低噪声增益开启   
  301.   
  302.   NRF24L01_Write_Reg(NRF_WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节
  303.   NRF24L01_Write_Reg(NRF_WRITE_REG + RX_PW_P1, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节
  304.   NRF24L01_Write_Reg(NRF_WRITE_REG + RX_PW_P2, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节
  305.   NRF24L01_Write_Reg(NRF_WRITE_REG + RX_PW_P3, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节
  306.   NRF24L01_Write_Reg(NRF_WRITE_REG + RX_PW_P4, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节
  307.   NRF24L01_Write_Reg(NRF_WRITE_REG + RX_PW_P5, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节
  308.   
  309.   NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(uint8_t*)RX_ADDRESS0,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK          
  310.   NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P1,(uint8_t*)RX_ADDRESS1,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK
  311.   NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P2,(uint8_t*)RX_ADDRESS2,1); //设置TX节点地址,主要为了使能ACK
  312.   NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P3,(uint8_t*)RX_ADDRESS3,1); //设置TX节点地址,主要为了使能ACK
  313.   NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P4,(uint8_t*)RX_ADDRESS4,1); //设置TX节点地址,主要为了使能ACK
  314.   NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P5,(uint8_t*)RX_ADDRESS5,1); //设置TX节点地址,主要为了使能ACK
  315.   NRF24L01_CE_HIGH(); //CE为高,进入接收模式
  316.   HAL_Delay(1);
  317. }                                                 

  318. /**
  319.   * 函数功能: 该函数初始化NRF24L01到TX模式
  320.   * 输入参数: 无
  321.   * 返 回 值: 无
  322.   * 说    明:无
  323.   *           
  324.   */
  325. void NRF24L01_TX_Mode(uint8_t *address)
  326. {                                                                                                                 
  327.         NRF24L01_CE_LOW();            
  328.   NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(uint8_t *)address,TX_ADR_WIDTH);//写TX节点地址
  329.   NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(uint8_t *)address,TX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK          

  330.   NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);     //使能通道0的自动应答   
  331.   NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址  
  332.   NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x01);//设置自动重发间隔时间:4000us + 86us;最大自动重发次数:15次
  333.   NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);       //设置RF通道为40
  334.   NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);  //设置TX发射参数,0db增益,2Mbps,低噪声增益开启   
  335.   NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e);    //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
  336.         NRF24L01_CE_HIGH();//CE为高,10us后启动发送
  337.   HAL_Delay(1);
  338. }

  339. /******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/

复制代码



客户端1:


客户端2:


客户端3:


客户端4:


客户端5:


客户端6:



好资料,谢谢小编的分享!

很好的资料,收藏了。

检测2401的函数里  这里的  0xA5  不用改么   看你上面的 发送接收地址不是这个   for(i=0;i<5;i++)if(buf[i]!=0XA5)break;

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top