[原创] STM32F746模拟SPI驱动NRF24L01进行数据交流程序

天天好心情亲   2016-1-4 09:57 楼主
忙活了好几天终于将STM32F746模拟SPI驱动NRF24L01进行数据交流的驱动写好了 ,不过有待调整,,先奉上以供大家参考!!!!!!
  1. /*****SPI驱动函数*******************/
  2. #include "stm32f7xx_hal_conf.h"

  3. SPI_HandleTypeDef hspi2;

  4. uint8_t status;
  5. //uint8_t txbuf[4]={0,1,2,3};         //发送缓冲
  6. uint8_t rxbuf[4];                         //接收缓冲
  7. int i=0;
  8. uint8_t RX_BUF[RX_PLOAD_WIDTH];                //接收数据缓存
  9. uint8_t TX_BUF[TX_PLOAD_WIDTH];                //发射数据缓存                                                                                                                                                                                                                                    
  10. uint8_t TX_ADDRESS[TX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};  // 定义一个静态发送地址
  11. uint8_t RX_ADDRESS[RX_ADR_WIDTH] = {0x34,0x43,0x10,0x10,0x01};


  12. uint8_t aTxBuffer[] = "****SPI - Two Boards communication based on Polling **** SPI Message ******** SPI Message ******** SPI Message ****";

  13. uint16_t Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)
  14. {
  15.   while (BufferLength--)
  16.   {
  17.     if((*pBuffer1) != *pBuffer2)
  18.     {
  19.       return BufferLength;
  20.     }
  21.     pBuffer1++;
  22.     pBuffer2++;
  23.   }

  24.   return 0;
  25. }
  26. /* Buffer used for reception */
  27. uint8_t aRxBuffer[BUFFERSIZE];
  28. void Error_Handler(void);
  29. void spi_config(void)
  30. {
  31.        
  32.        
  33.         GPIO_InitTypeDef  GPIO_InitStruct;
  34.        
  35.     /*##-1- Enable peripherals and GPIO Clocks #################################*/
  36.     /* Enable GPIO TX/RX clock */
  37.   __GPIOI_CLK_ENABLE();
  38.   __GPIOB_CLK_ENABLE();
  39.         __GPIOH_CLK_ENABLE();
  40.         __GPIOA_CLK_ENABLE();
  41.     /* Enable SPI clock */
  42.     SPIx_CLK_ENABLE();
  43.          /*Configure GPIO pin : PF10 */
  44.   GPIO_InitStruct.Pin = GPIO_PIN_8;
  45.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  46.   GPIO_InitStruct.Pull = GPIO_PULLUP;
  47.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  48.   /*Configure GPIO pins : PF9 PF8 */
  49.   GPIO_InitStruct.Pin = GPIO_PIN_3;
  50.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  51.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  52.   GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
  53.   HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
  54.        
  55.         GPIO_InitStruct.Pin = GPIO_PIN_6;
  56.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  57.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  58.   GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
  59.   HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
  60.    
  61.    
  62.    /**SPI2 GPIO Configuration   
  63.     PI1     ------> SPI2_SCK
  64.     PB14     ------> SPI2_MISO
  65.     PB15     ------> SPI2_MOSI
  66.     */
  67.     GPIO_InitStruct.Pin = GPIO_PIN_1;
  68.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  69.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  70.     GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
  71.     GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
  72.     HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);

  73.     GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_15;
  74.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  75.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  76.     GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
  77.     GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
  78.     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  79.           hspi2.Instance = SPI2;
  80.                 hspi2.Init.Mode = SPI_MODE_MASTER;
  81.                 hspi2.Init.Direction = SPI_DIRECTION_2LINES;
  82.                 hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
  83.                 hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
  84.                 hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
  85.                 hspi2.Init.NSS = SPI_NSS_SOFT;
  86.                 hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  87.                 hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  88.                 hspi2.Init.TIMode = SPI_TIMODE_DISABLED;
  89.                 hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
  90.                 hspi2.Init.CRCPolynomial = 7;
  91.                 hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  92.                 hspi2.Init.NSSPMode = SPI_NSS_PULSE_ENABLED;
  93.                 HAL_SPI_Init(&hspi2);
  94.                                
  95. }


  96. uint8_t SPI_ExchangeByte(uint8_t input)
  97. {
  98.   uint8_t output;
  99.   while(HAL_SPI_TransmitReceive(&hspi2,&input,&output,1,1000)!=HAL_OK);
  100.    return output;
  101. }
  102. void cmd(uint8_t *cmd,uint8_t *cmdsize)
  103. {
  104.         while( cmdsize -- )
  105.     {
  106.         SPI_ExchangeByte( *cmd++ );
  107.     }
  108. }
  109. uint8_t SPI_NRF_WriteBuf(uint8_t reg ,uint8_t *pBuf,uint8_t bytes)
  110. {
  111.           uint8_t status;
  112.          NRF_CE_LOW();
  113.             /*置低CSN,使能SPI传输*/
  114.          NRF_CSN_LOW();                       

  115.          /*发送寄存器号*/       
  116.            status = SPI_ExchangeByte( reg );
  117.        
  118.             /*向缓冲区写入数据*/
  119.          while( bytes -- )   
  120.                         {
  121.                                 SPI_ExchangeByte( *pBuf++ );
  122.                         }
  123.                     
  124.         /*CSN拉高,完成*/
  125.         NRF_CSN_HIGH();                       
  126.   
  127.           return (status);        //返回NRF24L01的状态                        
  128. }


  129. uint8_t SPI_NRF_ReadBuf(uint8_t reg, uint8_t *buffer, uint8_t size )
  130. {
  131.          uint8_t status;
  132.   NRF_CE_LOW();
  133.         /*置低CSN,使能SPI传输*/
  134.         NRF_CSN_LOW();
  135.         status =SPI_ExchangeByte( reg );
  136.         while( size -- )
  137.     {
  138.         *buffer++ = SPI_ExchangeByte( 0xFF );
  139.     }
  140.    
  141.    NRF_CSN_HIGH();       
  142.                 return (status);        //返回NRF24L01的状态                
  143. }



  144. uint8_t check2401(void)
  145. {
  146.         uint8_t buf[5]={0xC2,0xC2,0xC2,0xC2,0xC2};
  147.         uint8_t buf1[5];
  148.   uint8_t i;

  149.         /*写入5个字节的地址.  */  
  150.         SPI_NRF_WriteBuf(NRF_WRITE_REG+TX_ADDR,buf,5);

  151.         /*读出写入的地址 */
  152.         SPI_NRF_ReadBuf(TX_ADDR,buf1,5);

  153.         /*比较*/               
  154.         for(i=0;i<5;i++)
  155.         {
  156.                 if(buf1[i]!=0xC2)
  157.                 break;
  158.         }
  159.                
  160.         if(i==5)
  161.                 {
  162.                         printf("初始化NRF24L01成功...\r\n");
  163.                
  164.                   return SUCCESS ;
  165.                 }
  166.                        //MCU与NRF成功连接
  167.         else
  168.                 {
  169.                                
  170.                         printf("初始化NRF24L01失败...\r\n");
  171.                   return ERROR ;
  172.                 }
  173.                        //MCU与NRF不正常连接
  174. }

  175. /**
  176.   * [url=home.php?mod=space&uid=159083]@brief[/url]   用于向NRF特定的寄存器写入数据
  177.   * @param   
  178.   *                @arg reg:NRF的命令+寄存器地址
  179.   *                @arg dat:将要向寄存器写入的数据
  180.   * @retval  NRF的status寄存器的状态
  181.   */
  182. uint8_t SPI_NRF_WriteReg(uint8_t reg,uint8_t dat)
  183. {
  184.         uint8_t status;
  185.          NRF_CE_LOW();
  186.         /*置低CSN,使能SPI传输*/
  187.     NRF_CSN_LOW();
  188.                                
  189.         /*发送命令及寄存器号 */
  190.         status = SPI_ExchangeByte( reg );
  191.                  
  192.          /*向寄存器写入数据*/
  193.     SPI_ExchangeByte(dat);
  194.                   
  195.         /*CSN拉高,完成*/          
  196.           NRF_CSN_HIGH();       
  197.                
  198.         /*返回状态寄存器的值*/
  199.            return(status);
  200. }
  201. /**
  202.   * @brief   用于从NRF特定的寄存器读出数据
  203.   * @param   
  204.   *                @arg reg:NRF的命令+寄存器地址
  205.   * @retval  寄存器中的数据
  206.   */
  207. uint8_t SPI_NRF_ReadReg(uint8_t reg)
  208. {
  209. uint8_t reg_val;

  210.         NRF_CE_LOW();
  211.         /*置低CSN,使能SPI传输*/
  212.         NRF_CSN_LOW();
  213.                                
  214.            /*发送寄存器号*/
  215.         SPI_ExchangeByte(reg);

  216.          /*读取寄存器的值 */
  217.         reg_val = SPI_ExchangeByte(NOP);
  218.                    
  219.            /*CSN拉高,完成*/
  220.         NRF_CSN_HIGH();               
  221.           
  222.         return reg_val;
  223. }       
  224. void NRF_RX_Mode(void)

  225. {
  226.         NRF_CE_LOW();       

  227.    SPI_NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址

  228.    SPI_NRF_WriteReg(NRF_WRITE_REG+EN_AA,0x01);    //使能通道0的自动应答   

  229.    SPI_NRF_WriteReg(NRF_WRITE_REG+EN_RXADDR,0x01);//使能通道0的接收地址   

  230.    SPI_NRF_WriteReg(NRF_WRITE_REG+RF_CH,CHANAL);      //设置RF通信频率   

  231.    SPI_NRF_WriteReg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度      

  232.    SPI_NRF_WriteReg(NRF_WRITE_REG+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启   

  233.    SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG, 0x0f);  //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式

  234. /*CE拉高,进入接收模式*/       
  235.   NRF_CE_HIGH();

  236. }   

  237. /**
  238.   * @brief  配置发送模式
  239.   * @param  无
  240.   * @retval 无
  241.   */
  242. void NRF_TX_Mode(void)
  243. {  
  244.         NRF_CE_LOW();               

  245.    SPI_NRF_WriteBuf(NRF_WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH);    //写TX节点地址

  246.    SPI_NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK   

  247.    SPI_NRF_WriteReg(NRF_WRITE_REG+EN_AA,0x01);     //使能通道0的自动应答   

  248.    SPI_NRF_WriteReg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址  

  249.    SPI_NRF_WriteReg(NRF_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次

  250.    SPI_NRF_WriteReg(NRF_WRITE_REG+RF_CH,CHANAL);       //设置RF通道为CHANAL

  251.    SPI_NRF_WriteReg(NRF_WRITE_REG+RF_SETUP,0x0f);  //设置TX发射参数,0db增益,2Mbps,低噪声增益开启   
  252.        
  253.    SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG,0x0e);    //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,发射模式,开启所有中断

  254. /*CE拉高,进入发送模式*/       
  255.   NRF_CE_HIGH();
  256.   HAL_Delay(5);//CE要拉高一段时间才进入发送模式
  257.                
  258. }

  259. /**
  260.   * @brief   用于向NRF的发送缓冲区中写入数据
  261.   * @param   
  262.   *                @arg txBuf:存储了将要发送的数据的数组,外部定义       
  263.   * @retval  发送结果,成功返回TXDS,失败返回MAXRT或ERROR
  264.   */
  265. uint8_t NRF_Tx_Dat(uint8_t *txbuf)
  266. {
  267.         uint8_t state;  

  268.          /*ce为低,进入待机模式1*/
  269.         NRF_CE_LOW();

  270.         /*写数据到TX BUF 最大 32个字节*/                                               
  271.    SPI_NRF_WriteBuf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);

  272.       /*CE为高,txbuf非空,发送数据包 */   
  273.          NRF_CE_HIGH();
  274.                  
  275.           /*等待发送完成中断 */                           
  276.         while(NRF_Read_IRQ()!=0);        
  277.        
  278.         /*读取状态寄存器的值 */                              
  279.         state = SPI_NRF_ReadReg(STATUS);

  280.          /*清除TX_DS或MAX_RT中断标志*/                  
  281.         SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS,state);        

  282.         SPI_NRF_WriteReg(FLUSH_TX,NOP);    //清除TX FIFO寄存器

  283.          /*判断中断类型*/   
  284.         if(state&MAX_RT)                     //达到最大重发次数
  285.                          return MAX_RT;

  286.         else if(state&TX_DS)                  //发送完成
  287.                          return TX_DS;
  288.          else                                                  
  289.                         return ERROR;                 //其他原因发送失败
  290. }


  291. /**
  292.   * @brief   用于从NRF的接收缓冲区中读出数据
  293.   * @param   
  294.   *                @arg rxBuf :用于接收该数据的数组,外部定义       
  295.   * @retval
  296.   *                @arg 接收结果
  297.   */
  298. uint8_t NRF_Rx_Dat(uint8_t *rxbuf)
  299. {
  300.         uint8_t state;
  301.         NRF_CE_HIGH();         //进入接收状态
  302.          /*等待接收中断*/
  303.         while(NRF_Read_IRQ()!=0);
  304.        
  305.         NRF_CE_LOW();           //进入待机状态
  306.         /*读取status寄存器的值  */               
  307.         state=SPI_NRF_ReadReg(STATUS);
  308.          
  309.         /* 清除中断标志*/      
  310.         SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS,state);

  311.         /*判断是否接收到数据*/
  312.         if(state&RX_DR)                                 //接收到数据
  313.         {
  314.           SPI_NRF_ReadBuf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据
  315.              SPI_NRF_WriteReg(FLUSH_RX,NOP);          //清除RX FIFO寄存器
  316.           return RX_DR;
  317.         }
  318.         else   
  319.                 return ERROR;                    //没收到任何数据
  320. }

  321. void nrf_check(void)
  322. {
  323.            status = check2401();
  324.          if(status == SUCCESS)          
  325.                     printf("\r\n NRF与MCU连接成功!\r\n");  
  326.    else          
  327.                 printf("\r\n NRF与MCU连接失败,请重新检查接线。\r\n");
  328. }
  329. void nrf_send(uint8_t *txbuf)
  330. {
  331.                  printf("\r\n 主机端 进入自应答发送模式\r\n");
  332.         HAL_Delay(10);//CE要拉高一段时间才进入发送模式
  333.                  NRF_TX_Mode();
  334.                
  335.                         /*开始发送数据*/       
  336.         status = NRF_Tx_Dat(txbuf);          
  337.                   printf("\r\n 电子协会\r\n");
  338.                   /*判断发送状态*/
  339.                   switch(status)
  340.                           {
  341.                             case MAX_RT:
  342.                                           printf("\r\n 主机端 没接收到应答信号,发送次数超过限定值,发送失败。 \r\n");
  343.                                  break;
  344.        
  345.                           case ERROR:
  346.                                            printf("\r\n 未知原因导致发送失败。 \r\n");
  347.                                  break;
  348.        
  349.                           case TX_DS:
  350.                                           printf("\r\n 主机端 接收到 从机端 的应答信号,发送成功! \r\n");                        
  351.                                  break;                                                                 
  352.                           }                                  
  353.        
  354. //                 printf("\r\n 主机端 进入接收模式。 \r\n");       
  355. //                NRF_RX_Mode();
  356. //       
  357. //                        /*等待接收数据*/
  358. //                status = NRF_Rx_Dat(rxbuf);
  359. //       
  360. //                        /*判断接收状态*/
  361. //                        switch(status)
  362. //                        {
  363. //                         case RX_DR:
  364. //                                 for(i=0;i<4;i++)
  365. //                                {                                       
  366. //                                        printf("\r\n 主机端 接收到 从机端 发送的数据为:%d \r\n",rxbuf[i]);
  367. //                                        txbuf[i] =rxbuf[i];
  368. //                                }
  369. //                                  break;
  370. //       
  371. //                         case ERROR:
  372. //                                          printf("\r\n 主机端 接收出错。   \r\n");
  373. //                                  break;                 
  374. //                        }
  375. }

  376. /*************************/


回复评论 (9)

楼主辛苦了。
点赞  2016-1-4 16:19
楼主写这个的目的何在
点赞  2016-1-4 17:25
好像没说明,怎么交流的。楼主就贴了一端程序就走了啊。哈哈哈
点赞  2016-1-5 16:59
引用: huaiqiao 发表于 2016-1-5 16:59
好像没说明,怎么交流的。楼主就贴了一端程序就走了啊。哈哈哈

你是指的是SPI通信还是指?
点赞  2016-1-6 12:34
引用: zhoulei88 发表于 2016-1-4 17:25
楼主写这个的目的何在

方便用F7的人可以很好地调用和理解SPI驱动NRF24L01
点赞  2016-1-6 12:34
半双工,真spi,dma
点赞  2016-1-6 12:40
引用: 天天好心情亲 发表于 2016-1-6 12:34
你是指的是SPI通信还是指?

对对,SPI,能分享下您模拟的过程更好了
点赞  2016-1-6 16:47
引用: 天天好心情亲 发表于 2016-1-6 12:34
方便用F7的人可以很好地调用和理解SPI驱动NRF24L01

我偏向于用硬件SPI
点赞  2016-1-6 17:41
spi真的很不错,这个不错呀,多谢分享,我也来学习学习,看来MBED越来越强大了,我要加强学习,不然就落后了
点赞  2016-1-7 22:07
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复