社区导航

 
查看: 1215|回复: 5

[原创] STM32F769I-DISCO评测【12】--基于NRF24L01无线照明

[复制链接]

1054

TA的帖子

1

TA的资源

版主

Rank: 6Rank: 6

发表于 2017-1-2 19:55:15 | 显示全部楼层 |阅读模式
本帖最后由 qwerghf 于 2017-1-2 23:17 编辑

本节我们主要是基于NRF24L01实现一个无线照明终端。由于收发需要一对,所以正好使用STM32F769和STM32F746一个做接收设备控制台灯的亮灭,一个作为遥控发射装置。对于NRF24L01来说大家都不陌生,和MCU之间通过SPI接口通信,正好我们的STM32F769和STM32F746都有ardunio接口,上面有一个SPI2,方便我们接入NRF24L01。本次用的SPI2,如下红色圈出 1.png
电路原理图如下: 原理图.png
实际硬件图:
IMG_0021.JPG
IMG_0022.JPG

实际的驱动程序如下:
  1. //NRF24L01寄存器操作命令
  2. #define NRF_READ_REG    0x00  //读配置寄存器,低5位为寄存器地址
  3. #define NRF_WRITE_REG   0x20  //写配置寄存器,低5位为寄存器地址
  4. #define RD_RX_PLOAD     0x61  //读RX有效数据,1~32字节
  5. #define WR_TX_PLOAD     0xA0  //写TX有效数据,1~32字节
  6. #define FLUSH_TX        0xE1  //清除TX FIFO寄存器.发射模式下用
  7. #define FLUSH_RX        0xE2  //清除RX FIFO寄存器.接收模式下用
  8. #define REUSE_TX_PL     0xE3  //重新使用上一包数据,CE为高,数据包被不断发送.
  9. #define NOP             0xFF  //空操作,可以用来读状态寄存器         
  10. //SPI(NRF24L01)寄存器地址
  11. #define CONFIG          0x00  //配置寄存器地址;bit0:1接收模式,0发射模式;bit1:电选择;bit2:CRC模式;bit3:CRC使能;
  12.                               //bit4:中断MAX_RT(达到最大重发次数中断)使能;bit5:中断TX_DS使能;bit6:中断RX_DR使能
  13. #define EN_AA           0x01  //使能自动应答功能  bit0~5,对应通道0~5
  14. #define EN_RXADDR       0x02  //接收地址允许,bit0~5,对应通道0~5
  15. #define SETUP_AW        0x03  //设置地址宽度(所有数据通道):bit1,0:00,3字节;01,4字节;02,5字节;
  16. #define SETUP_RETR      0x04  //建立自动重发;bit3:0,自动重发计数器;bit7:4,自动重发延时 250*x+86us
  17. #define RF_CH           0x05  //RF通道,bit6:0,工作通道频率;
  18. #define RF_SETUP        0x06  //RF寄存器;bit3:传输速率(0:1Mbps,1:2Mbps);bit2:1,发射功率;bit0:低噪声放大器增益
  19. #define STATUS          0x07  //状态寄存器;bit0:TX FIFO满标志;bit3:1,接收数据通道号(最大:6);bit4,达到最多次重发
  20.                               //bit5:数据发送完成中断;bit6:接收数据中断;
  21. #define MAX_TX                  0x10  //达到最大发送次数中断
  22. #define TX_OK                   0x20  //TX发送完成中断
  23. #define RX_OK                   0x40  //接收到数据中断

  24. #define OBSERVE_TX      0x08  //发送检测寄存器,bit7:4,数据包丢失计数器;bit3:0,重发计数器
  25. #define CD              0x09  //载波检测寄存器,bit0,载波检测;
  26. #define RX_ADDR_P0      0x0A  //数据通道0接收地址,最大长度5个字节,低字节在前
  27. #define RX_ADDR_P1      0x0B  //数据通道1接收地址,最大长度5个字节,低字节在前
  28. #define RX_ADDR_P2      0x0C  //数据通道2接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;
  29. #define RX_ADDR_P3      0x0D  //数据通道3接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;
  30. #define RX_ADDR_P4      0x0E  //数据通道4接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;
  31. #define RX_ADDR_P5      0x0F  //数据通道5接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等;
  32. #define TX_ADDR         0x10  //发送地址(低字节在前),ShockBurstTM模式下,RX_ADDR_P0与此地址相等
  33. #define RX_PW_P0        0x11  //接收数据通道0有效数据宽度(1~32字节),设置为0则非法
  34. #define RX_PW_P1        0x12  //接收数据通道1有效数据宽度(1~32字节),设置为0则非法
  35. #define RX_PW_P2        0x13  //接收数据通道2有效数据宽度(1~32字节),设置为0则非法
  36. #define RX_PW_P3        0x14  //接收数据通道3有效数据宽度(1~32字节),设置为0则非法
  37. #define RX_PW_P4        0x15  //接收数据通道4有效数据宽度(1~32字节),设置为0则非法
  38. #define RX_PW_P5        0x16  //接收数据通道5有效数据宽度(1~32字节),设置为0则非法
  39. #define NRF_FIFO_STATUS 0x17  //FIFO状态寄存器;bit0,RX FIFO寄存器空标志;bit1,RX FIFO满标志;bit2,3,保留
  40.                               //bit4,TX FIFO空标志;bit5,TX FIFO满标志;bit6,1,循环发送上一数据包.0,不循环;
  41. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  42. //24L01操作线
  43. #define NRF24L01_CE(n)   (n?HAL_GPIO_WritePin(GPIOJ,GPIO_PIN_1,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOJ,GPIO_PIN_1,GPIO_PIN_RESET))//24L01片选信号
  44. #define NRF24L01_CSN(n)  (n?HAL_GPIO_WritePin(GPIOJ,GPIO_PIN_0,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOJ,GPIO_PIN_0,GPIO_PIN_RESET))//SPI片选信号           
  45. #define NRF24L01_IRQ     HAL_GPIO_ReadPin(GPIOG,GPIO_PIN_3)//IRQ主机数据输入
  46. //24L01发送接收数据宽度定义
  47. #define TX_ADR_WIDTH    5           //5字节的地址宽度
  48. #define RX_ADR_WIDTH    5           //5字节的地址宽度
  49. #define TX_PLOAD_WIDTH  32          //32字节的用户数据宽度
  50. #define RX_PLOAD_WIDTH  32          //32字节的用户数据宽度
  51.                                                                                       

  52. void NRF24L01_Init(void);//初始化
  53. void NRF24L01_RX_Mode(void);//配置为接收模式
  54. void NRF24L01_TX_Mode(void);//配置为发送模式
  55. u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 u8s);//写数据区
  56. u8 NRF24L01_Read_Buf(u8 reg, u8 *pBuf, u8 u8s);//读数据区                  
  57. u8 NRF24L01_Read_Reg(u8 reg);                        //读寄存器
  58. u8 NRF24L01_Write_Reg(u8 reg, u8 value);//写寄存器
  59. u8 NRF24L01_Check(void);//检查24L01是否存在
  60. u8 NRF24L01_TxPacket(u8 *txbuf);//发送一个包的数据
  61. u8 NRF24L01_RxPacket(u8 *rxbuf);//接收一个包的数据

  62. const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //发送地址
  63. const u8 RX_ADDRESS[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //发送地址

  64. //针对NRF24L01修改SPI2驱动
  65. void NRF24L01_SPI_Init(void)
  66. {
  67.     __HAL_SPI_DISABLE(&SPI2_Handler);               //先关闭SPI2
  68.     SPI2_Handler.Init.CLKPolarity=SPI_POLARITY_LOW; //串行同步时钟的空闲状态为低电平
  69.     SPI2_Handler.Init.CLKPhase=SPI_PHASE_1EDGE;     //串行同步时钟的第1个跳变沿(上升或下降)数据被采样
  70.     HAL_SPI_Init(&SPI2_Handler);
  71.     __HAL_SPI_ENABLE(&SPI2_Handler);                //使能SPI2
  72. }

  73. //初始化24L01的IO口
  74. void NRF24L01_Init(void)
  75. {
  76.     GPIO_InitTypeDef GPIO_Initure;
  77.     __HAL_RCC_GPIOJ_CLK_ENABLE();                        //开启GPIOJ时钟
  78.    
  79.     GPIO_Initure.Pin=GPIO_PIN_0|GPIO_PIN_1; //PJ0,1
  80.     GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  //推挽输出
  81.     GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
  82.     GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
  83.     HAL_GPIO_Init(GPIOJ,&GPIO_Initure);     //初始化
  84.      
  85.     GPIO_Initure.Pin=GPIO_PIN_3;           //PI11
  86.     GPIO_Initure.Mode=GPIO_MODE_INPUT;      //输入
  87.     HAL_GPIO_Init(GPIOJ,&GPIO_Initure);     //初始化
  88.    
  89.     SPI2_Init();                                    //初始化SPI2  
  90.     NRF24L01_SPI_Init();                    //针对NRF的特点修改SPI的设置
  91.         NRF24L01_CE(0);                                     //使能24L01
  92.         NRF24L01_CSN(1);                                    //SPI片选取消                                   
  93. }

  94. //检测24L01是否存在
  95. //返回值:0,成功;1,失败        
  96. u8 NRF24L01_Check(void)
  97. {
  98.         u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
  99.         u8 i;
  100.         SPI2_SetSpeed(SPI_BAUDRATEPRESCALER_8); //spi速度为6.75Mhz(24L01的最大SPI时钟为10Mhz)            
  101.         NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,buf,5);//写入5个字节的地址.        
  102.         NRF24L01_Read_Buf(TX_ADDR,buf,5); //读出写入的地址  
  103.         for(i=0;i<5;i++)if(buf[i]!=0XA5)break;                                                                    
  104.         if(i!=5)return 1;//检测24L01错误        
  105.         return 0;                 //检测到24L01
  106. }        

  107. //SPI写寄存器
  108. //reg:指定寄存器地址
  109. //value:写入的值
  110. u8 NRF24L01_Write_Reg(u8 reg,u8 value)
  111. {
  112.         u8 status;        
  113.            NRF24L01_CSN(0);                //使能SPI传输
  114.           status =SPI2_ReadWriteByte(reg);//发送寄存器号
  115.           SPI2_ReadWriteByte(value);      //写入寄存器的值
  116.           NRF24L01_CSN(1);                //禁止SPI传输           
  117.           return(status);                               //返回状态值
  118. }

  119. //读取SPI寄存器值
  120. //reg:要读的寄存器
  121. u8 NRF24L01_Read_Reg(u8 reg)
  122. {
  123.         u8 reg_val;            
  124.          NRF24L01_CSN(0);            //使能SPI传输               
  125.           SPI2_ReadWriteByte(reg);    //发送寄存器号
  126.           reg_val=SPI2_ReadWriteByte(0XFF);//读取寄存器内容
  127.           NRF24L01_CSN(1);            //禁止SPI传输                    
  128.           return(reg_val);            //返回状态值
  129. }        

  130. //在指定位置读出指定长度的数据
  131. //reg:寄存器(位置)
  132. //*pBuf:数据指针
  133. //len:数据长度
  134. //返回值,此次读到的状态寄存器值
  135. u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len)
  136. {
  137.         u8 status,u8_ctr;               
  138.           NRF24L01_CSN(0);            //使能SPI传输
  139.           status=SPI2_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值              
  140.          for(u8_ctr=0;u8_ctr<len;u8_ctr++)pBuf[u8_ctr]=SPI2_ReadWriteByte(0XFF);//读出数据
  141.           NRF24L01_CSN(1);            //关闭SPI传输
  142.           return status;              //返回读到的状态值
  143. }

  144. //在指定位置写指定长度的数据
  145. //reg:寄存器(位置)
  146. //*pBuf:数据指针
  147. //len:数据长度
  148. //返回值,此次读到的状态寄存器值
  149. u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len)
  150. {
  151.         u8 status,u8_ctr;            
  152.          NRF24L01_CSN(0);            //使能SPI传输
  153.           status = SPI2_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值
  154.           for(u8_ctr=0; u8_ctr<len; u8_ctr++)SPI2_ReadWriteByte(*pBuf++); //写入数据         
  155.           NRF24L01_CSN(1);            //关闭SPI传输
  156.           return status;              //返回读到的状态值
  157. }        

  158. //启动NRF24L01发送一次数据
  159. //txbuf:待发送数据首地址
  160. //返回值:发送完成状况
  161. u8 NRF24L01_TxPacket(u8 *txbuf)
  162. {
  163.         u8 sta;
  164.          SPI2_SetSpeed(SPI_BAUDRATEPRESCALER_8); //spi速度为6.75Mhz(24L01的最大SPI时钟为10Mhz)   
  165.         NRF24L01_CE(0);
  166.           NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//写数据到TX BUF  32个字节
  167.          NRF24L01_CE(1);                         //启动发送           
  168.         while(NRF24L01_IRQ!=0);                 //等待发送完成
  169.         sta=NRF24L01_Read_Reg(STATUS);          //读取状态寄存器的值           
  170.         NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志
  171.         if(sta&MAX_TX)                          //达到最大重发次数
  172.         {
  173.                 NRF24L01_Write_Reg(FLUSH_TX,0xff);  //清除TX FIFO寄存器
  174.                 return MAX_TX;
  175.         }
  176.         if(sta&TX_OK)                           //发送完成
  177.         {
  178.                 return TX_OK;
  179.         }
  180.         return 0xff;//其他原因发送失败
  181. }

  182. //启动NRF24L01发送一次数据
  183. //txbuf:待发送数据首地址
  184. //返回值:0,接收完成;其他,错误代码
  185. u8 NRF24L01_RxPacket(u8 *rxbuf)
  186. {
  187.         u8 sta;                                                                              
  188.         SPI2_SetSpeed(SPI_BAUDRATEPRESCALER_8); //spi速度为6.75Mhz(24L01的最大SPI时钟为10Mhz)   
  189.         sta=NRF24L01_Read_Reg(STATUS);          //读取状态寄存器的值            
  190.         NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志
  191.         if(sta&RX_OK)//接收到数据
  192.         {
  193.                 NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据
  194.                 NRF24L01_Write_Reg(FLUSH_RX,0xff);  //清除RX FIFO寄存器
  195.                 return 0;
  196.         }           
  197.         return 1;//没收到任何数据
  198. }               

  199. //该函数初始化NRF24L01到RX模式
  200. //设置RX地址,写RX数据宽度,选择RF频道,波特率和LNA HCURR
  201. //当CE变高后,即进入RX模式,并可以接收数据了                  
  202. void NRF24L01_RX_Mode(void)
  203. {
  204.         NRF24L01_CE(0);         
  205.           NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址
  206.          
  207.           NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);       //使能通道0的自动应答   
  208.           NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);   //使能通道0的接收地址           
  209.           NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);                //设置RF通信频率                  
  210.           NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度            
  211.           NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);    //设置TX发射参数,0db增益,2Mbps,低噪声增益开启   
  212.           NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);     //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式
  213.           NRF24L01_CE(1); //CE为高,进入接收模式
  214. }               

  215. //该函数初始化NRF24L01到TX模式
  216. //设置TX地址,写TX数据宽度,设置RX自动应答的地址,填充TX发送数据,选择RF频道,波特率和LNA HCURR
  217. //PWR_UP,CRC使能
  218. //当CE变高后,即进入RX模式,并可以接收数据了                  
  219. //CE为高大于10us,则启动发送.         
  220. void NRF24L01_TX_Mode(void)
  221. {                                                                                                                 
  222.         NRF24L01_CE(0);            
  223.           NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址
  224.           NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK         

  225.           NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);     //使能通道0的自动应答   
  226.           NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址  
  227.           NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次
  228.           NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);       //设置RF通道为40
  229.           NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);  //设置TX发射参数,0db增益,2Mbps,低噪声增益开启   
  230.           NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e);    //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
  231.         NRF24L01_CE(1);//CE为高,10us后启动发送
  232. }


  233. SPI_HandleTypeDef SPI2_Handler;  //SPI2句柄

  234. void SPI2_Init(void)
  235. {
  236.     SPI2_Handler.Instance=SPI2;                      //SP2
  237.     SPI2_Handler.Init.Mode=SPI_MODE_MASTER;          //设置SPI工作模式,设置为主模式
  238.     SPI2_Handler.Init.Direction=SPI_DIRECTION_2LINES;//设置SPI单向或者双向的数据模式:SPI设置为双线模式
  239.     SPI2_Handler.Init.DataSize=SPI_DATASIZE_8BIT;    //设置SPI的数据大小:SPI发送接收8位帧结构
  240.     SPI2_Handler.Init.CLKPolarity=SPI_POLARITY_HIGH; //串行同步时钟的空闲状态为高电平
  241.     SPI2_Handler.Init.CLKPhase=SPI_PHASE_2EDGE;      //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
  242.     SPI2_Handler.Init.NSS=SPI_NSS_SOFT;              //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
  243.     SPI2_Handler.Init.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_256;//定义波特率预分频的值:波特率预分频值为256
  244.     SPI2_Handler.Init.FirstBit=SPI_FIRSTBIT_MSB;     //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
  245.     SPI2_Handler.Init.TIMode=SPI_TIMODE_DISABLE;     //关闭TI模式
  246.     SPI2_Handler.Init.CRCCalculation=SPI_CRCCALCULATION_DISABLE;//关闭硬件CRC校验
  247.     SPI2_Handler.Init.CRCPolynomial=7;               //CRC值计算的多项式
  248.     HAL_SPI_Init(&SPI2_Handler);
  249.    
  250.     __HAL_SPI_ENABLE(&SPI2_Handler);                 //使能SPI2
  251.     SPI2_ReadWriteByte(0Xff);                        //启动传输
  252. }

  253. void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
  254. {
  255.     GPIO_InitTypeDef GPIO_Initure;
  256.    
  257.           __HAL_RCC_GPIOA_CLK_ENABLE();                   //使能GPIOA时钟
  258.     __HAL_RCC_GPIOB_CLK_ENABLE();                   //使能GPIOB时钟
  259.     __HAL_RCC_SPI2_CLK_ENABLE();                    //使能SPI2时钟
  260.    
  261.     GPIO_Initure.Pin=GPIO_PIN_12;
  262.     GPIO_Initure.Mode=GPIO_MODE_AF_PP;              //复用推挽输出
  263.     GPIO_Initure.Pull=GPIO_PULLUP;                  //上拉
  264.     GPIO_Initure.Speed=GPIO_SPEED_FAST;             //快速   
  265.     GPIO_Initure.Alternate=GPIO_AF5_SPI2;           //复用为SPI2
  266.     HAL_GPIO_Init(GPIOA,&GPIO_Initure);             //初始化
  267.         
  268.           GPIO_Initure.Pin=GPIO_PIN_14|GPIO_PIN_15;
  269.           HAL_GPIO_Init(GPIOB,&GPIO_Initure);             //初始化
  270.         
  271. }

  272. void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler)
  273. {
  274.     assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));//判断有效性
  275.     __HAL_SPI_DISABLE(&SPI2_Handler);            //关闭SPI
  276.     SPI2_Handler.Instance->CR1&=0XFFC7;          //位3-5清零,用来设置波特率
  277.     SPI2_Handler.Instance->CR1|=SPI_BaudRatePrescaler;//设置SPI速度
  278.     __HAL_SPI_ENABLE(&SPI2_Handler);             //使能SPI
  279.    
  280. }

  281. u8 SPI2_ReadWriteByte(u8 TxData)
  282. {
  283.     u8 Rxdata;
  284.     HAL_SPI_TransmitReceive(&SPI2_Handler,&TxData,&Rxdata,1, 1000);      
  285.          return Rxdata;                              //返回收到的数据               
  286. }

复制代码
  1. <blockquote>//NRF24L01寄存器操作命令
复制代码


点击此处,查看STM32F769I开发板官方资源。
此帖出自stm32/stm8论坛

评分

1

查看全部评分



回复

使用道具 举报

584

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2017-1-2 21:47:12 | 显示全部楼层


回复

使用道具 举报

2692

TA的帖子

8

TA的资源

版主

Rank: 6Rank: 6

发表于 2017-1-2 22:26:04 | 显示全部楼层
贴代码用代码框更好哟!


回复

使用道具 举报

2692

TA的帖子

8

TA的资源

版主

Rank: 6Rank: 6

发表于 2017-1-2 22:26:31 | 显示全部楼层
  1. SPI_HandleTypeDef SPI2_Handler;

  2. void SPI2_Init(void)
  3. {
  4.     SPI2_Handler.Instance=SPI2;                      //SP2
  5.     SPI2_Handler.Init.Mode=SPI_MODE_MASTER;          //设置SPI工作模式,设置为主模式
  6.     SPI2_Handler.Init.Direction=SPI_DIRECTION_2LINES;//设置SPI单向或者双向的数据模式:SPI设置为双线模式
  7.     SPI2_Handler.Init.DataSize=SPI_DATASIZE_8BIT;    //设置SPI的数据大小:SPI发送接收8位帧结构
  8.     SPI2_Handler.Init.CLKPolarity=SPI_POLARITY_HIGH; //串行同步时钟的空闲状态为高电平
  9.     SPI2_Handler.Init.CLKPhase=SPI_PHASE_2EDGE;      //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
  10.     SPI2_Handler.Init.NSS=SPI_NSS_SOFT;              //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
  11.     SPI2_Handler.Init.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_256;//定义波特率预分频的值:波特率预分频值为256
  12.     SPI2_Handler.Init.FirstBit=SPI_FIRSTBIT_MSB;     //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
  13.     SPI2_Handler.Init.TIMode=SPI_TIMODE_DISABLE;     //关闭TI模式
  14.     SPI2_Handler.Init.CRCCalculation=SPI_CRCCALCULATION_DISABLE;//关闭硬件CRC校验
  15.     SPI2_Handler.Init.CRCPolynomial=7;               //CRC值计算的多项式
  16.     HAL_SPI_Init(&SPI2_Handler);

  17.     __HAL_SPI_ENABLE(&SPI2_Handler);                 //使能SPI2
  18.     SPI2_ReadWriteByte(0Xff);                        //启动传输
  19. }


  20. void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
  21. {
  22.     GPIO_InitTypeDef GPIO_Initure;

  23.     __HAL_RCC_GPIOB_CLK_ENABLE();                   //使能GPIOF时钟
  24.     __HAL_RCC_SPI2_CLK_ENABLE();                    //使能SPI2时钟

  25.     //PB13,14,15
  26.     GPIO_Initure.Pin=GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
  27.     GPIO_Initure.Mode=GPIO_MODE_AF_PP;              //复用推挽输出
  28.     GPIO_Initure.Pull=GPIO_PULLUP;                  //上拉
  29.     GPIO_Initure.Speed=GPIO_SPEED_FAST;             //快速   
  30.     GPIO_Initure.Alternate=GPIO_AF5_SPI2;           //复用为SPI2
  31.     HAL_GPIO_Init(GPIOB,&GPIO_Initure);             //初始化
  32. }


  33. void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler)
  34. {
  35.     assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));//判断有效性
  36.     __HAL_SPI_DISABLE(&SPI2_Handler);            //关闭SPI
  37.     SPI2_Handler.Instance->CR1&=0XFFC7;          //位3-5清零,用来设置波特率
  38.     SPI2_Handler.Instance->CR1|=SPI_BaudRatePrescaler;//设置SPI速度
  39.     __HAL_SPI_ENABLE(&SPI2_Handler);             //使能SPI
  40. }


  41. u8 SPI2_ReadWriteByte(u8 TxData)
  42. {
  43.     u8 Rxdata;
  44.     HAL_SPI_TransmitReceive(&SPI2_Handler,&TxData,&Rxdata,1, 1000);      
  45.          return Rxdata;                              //返回收到的数据               
  46. }


  47. const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //发送地址
  48. const u8 RX_ADDRESS[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //发送地址

  49. //针对NRF24L01修改SPI2驱动
  50. void NRF24L01_SPI_Init(void)
  51. {
  52.     __HAL_SPI_DISABLE(&SPI2_Handler);               //先关闭SPI2
  53.     SPI2_Handler.Init.CLKPolarity=SPI_POLARITY_LOW; //串行同步时钟的空闲状态为低电平
  54.     SPI2_Handler.Init.CLKPhase=SPI_PHASE_1EDGE;     //串行同步时钟的第1个跳变沿(上升或下降)数据被采样
  55.     HAL_SPI_Init(&SPI2_Handler);
  56.     __HAL_SPI_ENABLE(&SPI2_Handler);                //使能SPI2
  57. }

  58. //初始化24L01的IO口
  59. void NRF24L01_Init(void)
  60. {
  61.     GPIO_InitTypeDef GPIO_Initure;
  62.     __HAL_RCC_GPIOG_CLK_ENABLE();                        //开启GPIOG时钟
  63.     __HAL_RCC_GPIOI_CLK_ENABLE();                        //开启GPIOI时钟

  64.     GPIO_Initure.Pin=GPIO_PIN_10|GPIO_PIN_12; //PG10,12
  65.     GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  //推挽输出
  66.     GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
  67.     GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
  68.     HAL_GPIO_Init(GPIOG,&GPIO_Initure);     //初始化

  69.     GPIO_Initure.Pin=GPIO_PIN_11;           //PI11
  70.     GPIO_Initure.Mode=GPIO_MODE_INPUT;      //输入
  71.     HAL_GPIO_Init(GPIOI,&GPIO_Initure);     //初始化

  72.     SPI2_Init();                                    //初始化SPI2  
  73.     NRF24L01_SPI_Init();                    //针对NRF的特点修改SPI的设置
  74.         NRF24L01_CE(0);                                     //使能24L01
  75.         NRF24L01_CSN(1);                                    //SPI片选取消                                   
  76. }

  77. //检测24L01是否存在
  78. //返回值:0,成功;1,失败        
  79. u8 NRF24L01_Check(void)
  80. {
  81.         u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
  82.         u8 i;
  83.         SPI2_SetSpeed(SPI_BAUDRATEPRESCALER_8); //spi速度为6.75Mhz(24L01的最大SPI时钟为10Mhz)            
  84.         NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,buf,5);//写入5个字节的地址.        
  85.         NRF24L01_Read_Buf(TX_ADDR,buf,5); //读出写入的地址  
  86.         for(i=0;i<5;i++)if(buf!=0XA5)break;                                                                    
  87.         if(i!=5)return 1;//检测24L01错误        
  88.         return 0;                 //检测到24L01
  89. }        
  90.          
  91. //SPI写寄存器
  92. //reg:指定寄存器地址
  93. //value:写入的值
  94. u8 NRF24L01_Write_Reg(u8 reg,u8 value)
  95. {
  96.         u8 status;        
  97.            NRF24L01_CSN(0);                //使能SPI传输
  98.           status =SPI2_ReadWriteByte(reg);//发送寄存器号
  99.           SPI2_ReadWriteByte(value);      //写入寄存器的值
  100.           NRF24L01_CSN(1);                //禁止SPI传输           
  101.           return(status);                               //返回状态值
  102. }
  103. //读取SPI寄存器值
  104. //reg:要读的寄存器
  105. u8 NRF24L01_Read_Reg(u8 reg)
  106. {
  107.         u8 reg_val;            
  108.          NRF24L01_CSN(0);            //使能SPI传输               
  109.           SPI2_ReadWriteByte(reg);    //发送寄存器号
  110.           reg_val=SPI2_ReadWriteByte(0XFF);//读取寄存器内容
  111.           NRF24L01_CSN(1);            //禁止SPI传输                    
  112.           return(reg_val);            //返回状态值
  113. }        

  114. //在指定位置读出指定长度的数据
  115. //reg:寄存器(位置)
  116. //*pBuf:数据指针
  117. //len:数据长度
  118. //返回值,此次读到的状态寄存器值
  119. u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len)
  120. {
  121.         u8 status,u8_ctr;               
  122.           NRF24L01_CSN(0);            //使能SPI传输
  123.           status=SPI2_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值              
  124.          for(u8_ctr=0;u8_ctr<len;u8_ctr++)pBuf[u8_ctr]=SPI2_ReadWriteByte(0XFF);//读出数据
  125.           NRF24L01_CSN(1);            //关闭SPI传输
  126.           return status;              //返回读到的状态值
  127. }
  128. //在指定位置写指定长度的数据
  129. //reg:寄存器(位置)
  130. //*pBuf:数据指针
  131. //len:数据长度
  132. //返回值,此次读到的状态寄存器值
  133. u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 len)
  134. {
  135.         u8 status,u8_ctr;            
  136.          NRF24L01_CSN(0);            //使能SPI传输
  137.           status = SPI2_ReadWriteByte(reg);//发送寄存器值(位置),并读取状态值
  138.           for(u8_ctr=0; u8_ctr<len; u8_ctr++)SPI2_ReadWriteByte(*pBuf++); //写入数据         
  139.           NRF24L01_CSN(1);            //关闭SPI传输
  140.           return status;              //返回读到的状态值
  141. }        
  142.                            
  143. //启动NRF24L01发送一次数据
  144. //txbuf:待发送数据首地址
  145. //返回值:发送完成状况
  146. u8 NRF24L01_TxPacket(u8 *txbuf)
  147. {
  148.         u8 sta;
  149.          SPI2_SetSpeed(SPI_BAUDRATEPRESCALER_8); //spi速度为6.75Mhz(24L01的最大SPI时钟为10Mhz)   
  150.         NRF24L01_CE(0);
  151.           NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//写数据到TX BUF  32个字节
  152.          NRF24L01_CE(1);                         //启动发送           
  153.         while(NRF24L01_IRQ!=0);                 //等待发送完成
  154.         sta=NRF24L01_Read_Reg(STATUS);          //读取状态寄存器的值           
  155.         NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志
  156.         if(sta&MAX_TX)                          //达到最大重发次数
  157.         {
  158.                 NRF24L01_Write_Reg(FLUSH_TX,0xff);  //清除TX FIFO寄存器
  159.                 return MAX_TX;
  160.         }
  161.         if(sta&TX_OK)                           //发送完成
  162.         {
  163.                 return TX_OK;
  164.         }
  165.         return 0xff;//其他原因发送失败
  166. }

  167. //启动NRF24L01发送一次数据
  168. //txbuf:待发送数据首地址
  169. //返回值:0,接收完成;其他,错误代码
  170. u8 NRF24L01_RxPacket(u8 *rxbuf)
  171. {
  172.         u8 sta;                                                                              
  173.         SPI2_SetSpeed(SPI_BAUDRATEPRESCALER_8); //spi速度为6.75Mhz(24L01的最大SPI时钟为10Mhz)   
  174.         sta=NRF24L01_Read_Reg(STATUS);          //读取状态寄存器的值            
  175.         NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志
  176.         if(sta&RX_OK)//接收到数据
  177.         {
  178.                 NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据
  179.                 NRF24L01_Write_Reg(FLUSH_RX,0xff);  //清除RX FIFO寄存器
  180.                 return 0;
  181.         }           
  182.         return 1;//没收到任何数据
  183. }        
  184.                                     
  185. //该函数初始化NRF24L01到RX模式
  186. //设置RX地址,写RX数据宽度,选择RF频道,波特率和LNA HCURR
  187. //当CE变高后,即进入RX模式,并可以接收数据了                  
  188. void NRF24L01_RX_Mode(void)
  189. {
  190.         NRF24L01_CE(0);         
  191.           NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址
  192.          
  193.           NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);       //使能通道0的自动应答   
  194.           NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);   //使能通道0的接收地址           
  195.           NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);                //设置RF通信频率                  
  196.           NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度            
  197.           NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);    //设置TX发射参数,0db增益,2Mbps,低噪声增益开启   
  198.           NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);     //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式
  199.           NRF24L01_CE(1); //CE为高,进入接收模式
  200. }
  201.                                                 
  202. //该函数初始化NRF24L01到TX模式
  203. //设置TX地址,写TX数据宽度,设置RX自动应答的地址,填充TX发送数据,选择RF频道,波特率和LNA HCURR
  204. //PWR_UP,CRC使能
  205. //当CE变高后,即进入RX模式,并可以接收数据了                  
  206. //CE为高大于10us,则启动发送.         
  207. void NRF24L01_TX_Mode(void)
  208. {                                                                                                                 
  209.         NRF24L01_CE(0);            
  210.           NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址
  211.           NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK         

  212.           NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);     //使能通道0的自动应答   
  213.           NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址  
  214.           NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次
  215.           NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);       //设置RF通道为40
  216.           NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);  //设置TX发射参数,0db增益,2Mbps,低噪声增益开启   
  217.           NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e);    //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
  218.         NRF24L01_CE(1);//CE为高,10us后启动发送
  219. }
复制代码

点评

好的,多谢,之前不会  详情 回复 发表于 2017-1-2 22:31


回复

使用道具 举报

1054

TA的帖子

1

TA的资源

版主

Rank: 6Rank: 6

 楼主| 发表于 2017-1-2 22:31:35 | 显示全部楼层

好的,多谢,之前不会


回复

使用道具 举报

14

TA的帖子

2

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2017-3-18 15:21:36 | 显示全部楼层
用手机APP控制就更好了,我有这需求,359711208@qq.com


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

Archiver|手机版|小黑屋|电子工程世界 ( 京ICP证 060456 )

GMT+8, 2018-12-15 14:32 , Processed in 0.242314 second(s), 20 queries , Gzip On, MemCache On.

快速回复 返回顶部 返回列表