[应用相关] [stm32] NRF24L01+USART搞定有线和无线通信

[复制链接]
1423|23
 楼主| features 发表于 2020-1-1 17:45 | 显示全部楼层
还要回过头说说我们的USART和NRF24L01,他们的初始化要看main函数中的BSP_Init();函数,该函数负相关硬件的初始化设置(中文意思是板级支持包初始化函数,因为uc-OS可以并不只限于stm32单片机,所以这里要根据不同平台进行相应的设置)。该函数位于bsp.c函数中,其作用相当于将以前我们在main函数中进行的相关硬件初始化单独拿出来封装成一个函数而已~但是,串口和无线对应的中断接收程序却有点不一样,因为这里是操作系统,所以在每个中断子程序前要调用OS_ENTER_CRITICAL();保存当前的全局中断标志,然后OSIntNesting++;中断嵌套深度加1,最后调用OS_EXIT_CRITICAL();恢复全局中断标志进入正常的中断处理,此外在中断响应函数最后要调用OSIntExit(); 检测如果有更高优先级的任务就绪了,则执行一次任务切换。
 楼主| features 发表于 2020-1-1 17:45 | 显示全部楼层
串口和无线中断子程序
  1. /*******************************************************************************
  2. * Function Name  : USART1_IRQHandler
  3. * Description    : This function handles USART1 global interrupt request.
  4. * Input          : None
  5. * Output         : None
  6. * Return         : None
  7. *******************************************************************************/
  8. void USART1_IRQHandler(void)
  9. {
  10.     unsigned int i;
  11.     OS_CPU_SR  cpu_sr;
  12.     OS_ENTER_CRITICAL();  //保存全局中断标志,关总中断 Tell uC/OS-II that we are starting an ISR
  13.     OSIntNesting++;
  14.     OS_EXIT_CRITICAL();      //恢复全局中断曛?        

  15.     if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)       //判断读寄存器是否非空
  16.     {   
  17.         RxBufferUSART[RxCounter1++] = USART_ReceiveData(USART1);   //将读寄存器的数据缓存到接收缓冲区里
  18.         if(RxBufferUSART[RxCounter1-2]==0x0d&&RxBufferUSART[RxCounter1-1]==0x0a)     //判断结束标志是否是0x0d 0x0a
  19.         {
  20.             for(i=0; i< RxCounter1; i++) TxBufferRF[i] = RxBufferUSART[i];          //将接收缓冲器的数据转到发送缓冲区,准备转发
  21.             usart_rec_flag=1;                                                             //接收成功标志
  22.             TxBufferRF[RxCounter1]=0;                                             //发送缓冲区结束符   
  23.             TxCounter1=RxCounter1;
  24.             RxCounter1=0;
  25.         }
  26.     }
  27.     if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)                   //这段是为了避免STM32 USART 第一个字节发不出去的BUG
  28.     {
  29.         USART_ITConfig(USART1, USART_IT_TXE, DISABLE);                         //禁止发缓冲器空中断,
  30.     }   
  31.     OSIntExit();           //在os_core.c文件里定义,如果有更高优先级的任务就绪了,则执行一次任务切换   
  32. }
  33. /////////////////////////////
  34. void EXTI0_IRQHandler(void)
  35. {
  36.   unsigned char status,i;
  37.   OS_CPU_SR  cpu_sr;
  38.   OS_ENTER_CRITICAL();  //保存全局中断标志,关总中断 Tell uC/OS-II that we are starting an ISR
  39.   OSIntNesting++;
  40.   OS_EXIT_CRITICAL();      //恢复全局中断标志            
  41.   
  42.   if(EXTI_GetITStatus(EXTI_Line0) != RESET)            //判断是否产生了EXTI0中断
  43.   {
  44.       if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==0){ //判断是否是PA0线变低            
  45.         status=SPI_Read(READ_REG1+STATUS);            // 读取状态寄存其来判断数据接收状况   
  46.         if(status & 0x40)                            // 判断是否接收到数据                  
  47.         {                                                         
  48.              SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);  //从接收缓冲区里读出数据
  49.             for(i=0; i<32; i++){                              //向USB 端点1的缓冲区里放置数据
  50.                 TxBufferUSART[i] = rx_buf[i];     
  51.             }
  52.             rf_rec_flag=1;         
  53.             if((status&0x0e)<=0x0a){                           
  54.                nrf_Pipe_r=(status&0x0e)>>1;                      //读出是在哪个通道接收的
  55.             }
  56.             else nrf_Pipe_r=0;                     
  57.             Rx_Succ=1;            //读取数据完成标志
  58.             /* 根据读出的接收通道号,将相应信息写入状态文本缓冲区 */
  59.             if(nrf_Pipe_r==0) memcpy(status_buf, "Pipe 0 Recive OK!   ", 20);           
  60.             else if(nrf_Pipe_r==1) memcpy(status_buf, "Pipe 1 Recive OK!   ", 20);
  61.             else if(nrf_Pipe_r==2) memcpy(status_buf, "Pipe 2 Recive OK!   ", 20);
  62.             else if(nrf_Pipe_r==3) memcpy(status_buf, "Pipe 3 Recive OK!   ", 20);
  63.             else if(nrf_Pipe_r==4) memcpy(status_buf, "Pipe 4 Recive OK!   ", 20);
  64.             else if(nrf_Pipe_r==5) memcpy(status_buf, "Pipe 5 Recive OK!   ", 20);
  65.         }
  66.         else if((status &0x10)>0){                     //发射达到最大复发次数               
  67.             SPI_RW_Reg(0xe1,0);                          //清除发送缓冲区                  
  68.             RX_Mode();                                 //进入接收模式                                 
  69.             Rx_Succ=1;                                                                                    
  70.             /* 根据发送通道,将相应信息写入状态文本缓冲区 */
  71.             if(nrf_Pipe==0) memcpy(status_buf, "Pipe 0 NO ACK!      ", 20);
  72.             else if(nrf_Pipe==1) memcpy(status_buf, "Pipe 1 NO ACK!      ", 20);
  73.             else if(nrf_Pipe==2) memcpy(status_buf, "Pipe 2 NO ACK!      ", 20);
  74.             else if(nrf_Pipe==3) memcpy(status_buf, "Pipe 3 NO ACK!      ", 20);  
  75.             else if(nrf_Pipe==4) memcpy(status_buf, "Pipe 4 NO ACK!      ", 20);
  76.             else if(nrf_Pipe==5) memcpy(status_buf, "Pipe 5 NO ACK!      ", 20);            
  77.         }
  78.         else if((status &0x20)>0){                     //发射后收到应答            
  79.             SPI_RW_Reg(0xe1,0);                         //清除发送缓冲区              
  80.             RX_Mode();                                 //进入接收模式
  81.             Rx_Succ=1;
  82.             /* 根据发送通道,将相应信息写入状态文本缓冲区 */
  83.             if(nrf_Pipe==0) memcpy(status_buf, "Pipe 0 Send OK!     ", 20);
  84.             else if(nrf_Pipe==1) memcpy(status_buf, "Pipe 1 Send OK!     ", 20);
  85.             else if(nrf_Pipe==2) memcpy(status_buf, "Pipe 2 Send OK!     ", 20);
  86.             else if(nrf_Pipe==3) memcpy(status_buf, "Pipe 3 Send OK!     ", 20);
  87.             else if(nrf_Pipe==4) memcpy(status_buf, "Pipe 4 Send OK!     ", 20);
  88.             else if(nrf_Pipe==5) memcpy(status_buf, "Pipe 5 Send OK!     ", 20);               
  89.         }
  90.         
  91.         SPI_RW_Reg(WRITE_REG1+STATUS, status);         //清除07寄存器标志              
  92.       }        
  93.       EXTI_ClearITPendingBit(EXTI_Line0);             //清除EXTI0上的中断标志              
  94.   }   
  95.   OSIntExit();           //在os_core.c文件里定义,如果有更高优先级的任务就绪了,则执行一次任务切换     
  96. }
 楼主| features 发表于 2020-1-1 17:46 | 显示全部楼层
最后说明

对于纯玩软件的小伙伴,这里涉及的东西有点多,不必细究,看看了解即可。但是对于初学stm32,尤其是还在为stm32控制NRF24L01不通的同学,这个还是挺有用滴~下面有工程的链接,里面有些注释不规范,一切以我博客里说的为准哦~
 楼主| features 发表于 2020-1-1 17:47 | 显示全部楼层
链接

上述工程keil代码:http://pan.baidu.com/s/1mgqowQ0

本文链接:http://www.cnblogs.com/zjutlitao/p/4242734.html

上述工程GitHub链接:https://github.com/beautifulzzzz/stm32/tree/master/stm32_USART%2BNRF24L01

可能有用1:[stm32][ucos] 1、基于ucos操作系统的LED闪烁、串口通信简单例程  https://bbs.21ic.com/icview-2893452-1-1.html

可能有用2:[stm32][ucos][ucgui] 2、LED闪烁、串口、滑块、文本编辑框简单例程  https://bbs.21ic.com/icview-2893454-1-1.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部