<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > stm32 NRF24L01+USART搞定有線(xiàn)和無(wú)線(xiàn)通信

stm32 NRF24L01+USART搞定有線(xiàn)和無(wú)線(xiàn)通信

作者: 時(shí)間:2016-11-19 來(lái)源:網(wǎng)絡(luò ) 收藏
前言

一般進(jìn)行遠程監控時(shí),2.4G無(wú)線(xiàn)通信是充當遠程數據傳輸的一種方法。這時(shí)就需要在現場(chǎng)部分具備無(wú)線(xiàn)數據發(fā)送裝置,而在上位機部分由于一般只有串口,所以將采集到的數據送到電腦里又要在上位機端設計一個(gè)數據接收的適配器。這里基于stm32分別設計了現場(chǎng)部分和適配器部分,這里只是基本通信功能實(shí)現的講解,一些復雜的技術(shù)比如加密、可靠等要根據具體的應用來(lái)設計~

本文引用地址:http://dyxdggzs.com/article/201611/318440.htm

總體說(shuō)明

這里采用stm32作為MCU,采用nRF24L01作為2.4G通信模塊。其中適配器中僅僅采用了USARTNRF24L01兩個(gè)主要部分,負責將下位機通過(guò)2.4G發(fā)送過(guò)來(lái)的數據通過(guò)串口發(fā)送給上位機,或者將上位機的通過(guò)串口傳來(lái)的數據通過(guò)2.4G發(fā)送給下位機來(lái)實(shí)現遠程監控(沒(méi)有采用uc-os操作系統,也沒(méi)有界面,要用串口和上位機相連);其中下位機比較復雜,因為一般下位機是一個(gè)集成的系統,包括從各種傳感器收集數據、向各種類(lèi)型的驅動(dòng)電路發(fā)送控制命令、將數據輸給打印機或顯示器、和無(wú)線(xiàn)通信或有線(xiàn)通信設備進(jìn)行互相通信來(lái)實(shí)現數據傳輸等,這里的下位機比較簡(jiǎn)單:采用uc-os實(shí)時(shí)操作系統+uc-gui負責界面顯示,外接7寸TFT液晶顯示屏,和適配器類(lèi)似也包括USART和NRF24L01通信部分,但是因為有了操作系統和可視化交互界面,所以也有點(diǎn)不同,接下來(lái)開(kāi)始介紹。

適配器部分

這里介紹的流程是以main函數為基準,廣度拓寬知識點(diǎn),最后main函數說(shuō)完,整個(gè)工程的細節也就大致能了解了~

1 int main(void){2   uint8_t a=0;//LED高低電壓控制3   /* System Clocks Configuration */4   RCC_Configuration();                                              //系統時(shí)鐘設置    5   /*嵌套向量中斷控制器 6       說(shuō)明了USART1搶占優(yōu)先級級別0(最多1位) ,和子優(yōu)先級級別0(最多7位) */ 7   NVIC_Configuration();                                              //中斷源配置8   /*對控制LED指示燈的IO口進(jìn)行了初始化,將端口配置為推挽上拉輸出,口線(xiàn)速度為50Mhz。PA9,PA10端口復用為串口1的TX,RX。9   在配置某個(gè)口線(xiàn)時(shí),首先應對它所在的端口的時(shí)鐘進(jìn)行使能。否則無(wú)法配置成功,由于用到了端口B, 因此要對這個(gè)端口的時(shí)鐘10   進(jìn)行使能,同時(shí)由于用到復用IO口功能用于配置串口。因此還要使能AFIO(復用功能IO)時(shí)鐘。*/11   GPIO_Configuration();                                              //端口初始化12   SPI2_NRF24L01_Init();                                           //SPI2及NRF24L01接口初始化  13   USART_Config(USART1);                                              //串口1初始化14   /*NRF24L01設置為接收模式*/15   RX_Mode(); 16 17    while (1)18   {19     if(usart_rec_flag==1) //判斷是否收到一幀有效數據20     {                                                  21         usart_rec_flag=0;22         NRF_Send_Data(TxBufferRF,sizeof(TxBufferRF));23         if(a==0){GPIO_SetBits(GPIOB, GPIO_Pin_5);a=1;}          //LED1  明暗閃爍                24         else{GPIO_ResetBits(GPIOB, GPIO_Pin_5);a=0;}25     }26     if(rf_rec_flag==1)27     {28           rf_rec_flag=0;29            for(i=0;i<32;i++)//發(fā)送字符串30         {31             USART_SendChar(USART1,TxBufferUSART[i]);32         //    Delay(0x0ff00);33         }34     }35   }36 }

第4行RCC初始化主要是系統時(shí)鐘和外設時(shí)鐘配置,這里注意要使能RCC_APB2Periph_USART1,當時(shí)忘了使能這個(gè)結果串口出現異常,我還以為是初始化和中斷向量什么的弄錯了呢,浪費了很長(cháng)時(shí)間。

1 /*--2 系統時(shí)鐘配置為72MHZ+外設時(shí)鐘配置*/ 3 void RCC_Configuration(void){4    SystemInit(); 5    RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1 RCC_APB2Periph_GPIOA  RCC_APB2Periph_GPIOB RCC_APB2Periph_AFIO  , ENABLE);  6 }

第7行中斷向量初始化設置,主要是設置串口接收中斷和NRF24L01中斷的,這樣設置好了之后當串口中斷被觸發(fā)時(shí)其對應的中斷子程序將被執行(這個(gè)科班的大概都知道這里就不多說(shuō)了),所以我們就要在stm32f10x_it.c里實(shí)現他們各自的中斷子程序了(這個(gè)一會(huì )再詳細介紹,咱們先把整個(gè)框架了解下)。另外說(shuō)一句,這里的的優(yōu)先級組將影響主優(yōu)先級和子優(yōu)先級數量具體請參考stm32f10X_的固件庫的NVIC.

1 void NVIC_Configuration(void){2  /*  結構聲明*/3   NVIC_InitTypeDef NVIC_InitStructure;4   EXTI_InitTypeDef EXTI_InitStructure;        5   6   /* 優(yōu)先級組 1  */    7   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);           8   9   /* Enable the USART1 Interrupt */10   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;                     //設置串口1中斷11   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;             //搶占優(yōu)先級 012   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;                //子優(yōu)先級為013   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                    //使能14   NVIC_Init(&NVIC_InitStructure);                                              15 16                                                                     17   NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;                    //NRF24L01 中斷響應18   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;            //搶占優(yōu)先級 019   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;                //子優(yōu)先級為120   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                    //使能21   NVIC_Init(&NVIC_InitStructure);                                                22 23   GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);       //NRF24L01 IRQ  PA024   25   EXTI_InitStructure.EXTI_Line = EXTI_Line0;                       //NRF24L01 IRQ PA026   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;               //EXTI中斷27   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;           //下降沿觸發(fā)28   EXTI_InitStructure.EXTI_LineCmd = ENABLE;                           //使能29   EXTI_Init(&EXTI_InitStructure);    30 }

第11行的GPIO初始化,主要是對通用IO口的屬性設置和初始化,這里一定要對串口所需的A9和A10配置好!

1 void GPIO_Configuration(void){2   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;                     //LED1控制--PB53   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;             //推挽輸出4   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;5   GPIO_Init(GPIOB, &GPIO_InitStructure);                     6 7   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;                      //USART1 TX8   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;             //復用推挽輸出9   GPIO_Init(GPIOA, &GPIO_InitStructure);                     //A端口 10 11   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;                  //USART1 RX12   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;        //復用開(kāi)漏輸入13   GPIO_Init(GPIOA, &GPIO_InitStructure);                      //A端口 14 }

第12行的SPI2_NRF24L01_Init();主要是驅動(dòng)NRF24L01的接口初始化,因為NRF24L01采用的是SPI通信,所以這里免不了SPI的設置和相關(guān)操作了,不過(guò)幸好都封裝好了~像以前在51上做SPI就得自己模擬SPI,沒(méi)有示波器調試起來(lái)甚是坑~此外這里我已經(jīng)把NRF24L01的整個(gè)驅動(dòng)都封裝在NRF24L01.c這個(gè)文件里了,當想用的時(shí)候只要在中斷向量里設置其中斷接收函數,并在it.c里實(shí)現其接收函數;一般主函數里用到的是其初始化函數SPI2_NRF24L01_Init();和RX_Mode();,當在過(guò)程中想利用NRF24L01向外發(fā)數據時(shí)只要調用函數void NRF_Send_Data(uint8_t* data_buffer, uint8_t Nb_bytes):

1 /****************************************************************************2 * 名    稱(chēng):NRF_Send_Data(uint8_t* data_buffer, uint8_t Nb_bytes)3 * 功    能:將保存在接收緩存區的32字節的數據通過(guò)NRF24L01+發(fā)送出去4 * 入口參數:data_buffer   待發(fā)送數據5             Nb_bytes      待發(fā)送數據長(cháng)度6 * 出口參數:無(wú)7 * 說(shuō)    明:數據小于32,把有效數據外的空間用0填滿(mǎn)8 * 調用方法:RX_Mode();9 ****************************************************************************/10 void NRF_Send_Data(uint8_t* data_buffer, uint8_t Nb_bytes)11 {  12     uchar i=0;  13     MODE_CE(0);                                 //NRF 模式控制     14 15     SPI_RW_Reg(WRITE_REG1+STATUS,0xff);         //設置狀態(tài)寄存器初始化16     SPI_RW_Reg(0xe1,0);                         //清除TX FIFO寄存器17     SPI_RW_Reg(0xe2,0);                         //清除RX FIFO寄存器18     TX_Mode();                                 //設置為發(fā)送模式19     delay_ms(1);20     if(Nb_bytes<32){                         //當接收到的USB虛擬串口數據小于32,把有效數據外的空間用0填滿(mǎn)21         for(i=Nb_bytes;i<32;i++) data_buffer[i]=0;22     }23     MODE_CE(0);24       SPI_Write_Buf(WR_TX_PLOAD, data_buffer, TX_PLOAD_WIDTH);        //發(fā)送32字節的緩存區數據到NRF24L0125     MODE_CE(1);                                                        //保持10us以上,將數據發(fā)送出去        26 }

第13行是USART初始化,包括波特率、數據位、停止位等~

1 void USART_Config(USART_TypeDef* USARTx){2   USART_InitStructure.USART_BaudRate = 9600;                        //速率9600bps3   USART_InitStructure.USART_WordLength = USART_WordLength_8b;        //數據位8位4   USART_InitStructure.USART_StopBits = USART_StopBits_1;            //停止位1位5   USART_InitStructure.USART_Parity = USART_Parity_No;                //無(wú)校驗位6   USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;   //無(wú)硬件流控7   USART_InitStructure.USART_Mode = USART_Mode_Rx  USART_Mode_Tx;                    //收發(fā)模式8 9   /* Configure USART1 */10   USART_Init(USARTx, &USART_InitStructure);                            //配置串口參數函數11  12   13   /* Enable USART1 Receive and Transmit interrupts */14   USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);                    //使能接收中斷15   USART_ITConfig(USART1, USART_IT_TXE, ENABLE);                        //使能發(fā)送緩沖空中斷   16 17   /* Enable the USART1 */18   USART_Cmd(USART1, ENABLE);    19 }

同樣的類(lèi)似于NRF24L01一旦初始化之后,其數據接收一般采用中斷方式、數據發(fā)送一般采用直接發(fā)送的方式。所以在中斷向量里也要設置,也要在it.c中實(shí)現其接收中斷子函數。其發(fā)送直接調用stm32f10的固件庫函數(這里我稍加封裝了下):其實(shí)就是發(fā)送一個(gè)data之后要監聽(tīng)是否發(fā)送完成才能進(jìn)行下次發(fā)送~

1 void USART_SendChar(USART_TypeDef* USARTx,uint8_t data){2     USART_SendData(USARTx,data);3     while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)==RESET);4 }

接下來(lái)進(jìn)入while循環(huán),不斷進(jìn)行監聽(tīng)看是否有串口接收標志位置1或者無(wú)線(xiàn)模塊接收標志位置1,如果有表明相應的有數據從該通道傳送過(guò)來(lái)。當是從串口傳來(lái)的數據表明數據是從上位機發(fā)送來(lái)的數據,并且想把該數據通過(guò)2.4G發(fā)送出去,所以這里調用:NRF_Send_Data(TxBufferRF,sizeof(TxBufferRF));將數據發(fā)送出去;當數據是從2.4G通道中傳過(guò)來(lái)的,表明數據是從下位機傳送過(guò)來(lái)的想給上位機,于是調用串口發(fā)送函數將數據發(fā)送給上位機:USART_SendChar(USART1,TxBufferUSART[i]);

看了上圖適配器端的數據交換過(guò)程就明白了串口中斷和無(wú)線(xiàn)中斷大致要干的事了,這里我就不多介紹,看看下面的代碼就明白了(在stm32f10x_it.c中),要再次提醒的是無(wú)論是串口還是無(wú)線(xiàn)其接收都是采用中斷,而發(fā)送采用循環(huán)直接發(fā)送,他們的中斷和中斷向量有關(guān)并要在stm32f10x_it.c里實(shí)現相應的中斷子程序~



1 /******************************************************************************/2 /*            STM32F10x Peripherals Interrupt Handlers                        */3 /******************************************************************************/4 5 /**6   * @brief  This function handles USART1 global interrupt request.7   * @param  None8   * @retval : None9   */10 void USART1_IRQHandler(void)      //串口1 中斷服務(wù)程序11 {12   unsigned int i;13   if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)       //判斷讀寄存器是否非空14   {    15     16     RxBufferUSART[RxCounter1++] = USART_ReceiveData(USART1);   //將讀寄存器的數據緩存到接收緩沖區里17     18     if(RxBufferUSART[RxCounter1-2]==0x0d&&RxBufferUSART[RxCounter1-1]==0x0a)     //判斷結束標志是否是0x0d 0x0a19     {20       for(i=0; i< RxCounter1; i++) TxBufferRF[i] = RxBufferUSART[i];          //將接收緩沖器的數據轉到發(fā)送緩沖區,準備轉發(fā)21       usart_rec_flag=1;                                                             //接收成功標志22       TxBufferRF[RxCounter1]=0;                                             //發(fā)送緩沖區結束符    23       TxCounter1=RxCounter1;24       RxCounter1=0;25     }26   }27   28   if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)                   //這段是為了避免STM32 USART 第一個(gè)字節發(fā)不出去的BUG 29   { 30      USART_ITConfig(USART1, USART_IT_TXE, DISABLE);                         //禁止發(fā)緩沖器空中斷, 31   }    32 }  33 /*******************************************************************************34 * Function Name  : EXTI0 中斷函數35 * Description    : NRF24L01中斷服務(wù)程序36 * Input          : None37 * Output         : None38 * Return         : None39 *******************************************************************************/40 void EXTI0_IRQHandler(void){41     u8 i=0;42      u8 status;    43     if(EXTI_GetITStatus(EXTI_Line0) != RESET)            //判斷是否產(chǎn)生了EXTI0中斷44       {45         if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==0){ //判斷是否是PA0線(xiàn)變低            46             status=SPI_Read(READ_REG1+STATUS);            // 讀取狀態(tài)寄存其來(lái)判斷數據接收狀況    47             if(status & 0x40)                            // 判斷是否接收到數據                   48             {            49                 //GPIO_ResetBits(GPIOB, GPIO_Pin_5);   50                  SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);  //從接收緩沖區里讀出數據51                 for(i=0; i<32; i++)TxBufferUSART[i] = rx_buf[i];  //向USB 端點(diǎn)1的緩沖區里放置數據      52                 rf_rec_flag=1;53             }54             else if((status &0x10)>0){                     //發(fā)射達到最大復發(fā)次數                55                 SPI_RW_Reg(0xe1,0);                          //清除發(fā)送緩沖區                  56                 RX_Mode();                                 //進(jìn)入接收模式                   57             }58             else if((status &0x20)>0){                     //發(fā)射后收到應答 59                 GPIO_SetBits(GPIOB, GPIO_Pin_5);   60                 SPI_RW_Reg(0xe1,0);                         //清除發(fā)送緩沖區              61                 RX_Mode();                                 //進(jìn)入接收模式                   62             }63             SPI_RW_Reg(WRITE_REG1+STATUS, status);         //清除07寄存器標志64         }        65         EXTI_ClearITPendingBit(EXTI_Line0);             //清除EXTI0上的中斷標志              66     } 67 }
串口和無(wú)線(xiàn)接收中斷子程序

下位機部分

上面說(shuō)過(guò)一般具有遠程通信能力的嵌入式系統其下位機部分往往要干很多事,這里我們采用stm32作為MCU并搭載uc-OS實(shí)時(shí)操作系統負責任務(wù)調度,同時(shí)采用7寸TFT彩屏和uc-GUI設計可視化人機交互界面。其中任務(wù)包括主任務(wù)、界面任務(wù)和觸摸任務(wù),主任務(wù)負責建立其他任務(wù),界面任務(wù)中將包含整個(gè)人機交互界面的界面刷新邏輯,觸摸任務(wù)負責獲取觸摸位置數據獲取~

這里我們還是得從main函數先說(shuō)起:首先在main函數中進(jìn)行相關(guān)初始化,然后建立主任務(wù)并啟動(dòng)uc-OS內核;接著(zhù)在主任務(wù)中調用App_TaskCreate();分別建立界面任務(wù)和觸摸任務(wù)(如下每個(gè)任務(wù)的建立類(lèi)似,要給出指向任務(wù)代碼的指針、任務(wù)執行時(shí)傳遞給任務(wù)的參數的指針,分配給這個(gè)任務(wù)的棧信息,任務(wù)優(yōu)先級等)。這樣當任務(wù)建立好之后,其執行權就由操作系統調度了~

1 static  void App_TaskCreate(void)2 {3    /*  建立用戶(hù)界面任務(wù) */4    OSTaskCreateExt(AppTaskUserIF,                                               //指向任務(wù)代碼的指針5                        (void *)0,                                                   //任務(wù)開(kāi)始執行時(shí),傳遞給任務(wù)的參數的指針6                        (OS_STK *)&AppTaskUserIFStk[APP_TASK_USER_IF_STK_SIZE-1],  //分配給任務(wù)的堆棧的棧頂指針   從頂向下遞減7                     APP_TASK_USER_IF_PRIO,                                       //分配給任務(wù)的優(yōu)先級8                     APP_TASK_USER_IF_PRIO,                                       //預備給以后版本的特殊標識符,在現行版本同任務(wù)優(yōu)先級9                     (OS_STK *)&AppTaskUserIFStk[0],                               //指向任務(wù)堆棧棧底的指針,用于堆棧的檢驗10                     APP_TASK_USER_IF_STK_SIZE,                                    //指定堆棧的容量,用于堆棧的檢驗11                     (void *)0,                                                    //指向用戶(hù)附加的數據域的指針,用來(lái)擴展任務(wù)的任務(wù)控制塊12                     OS_TASK_OPT_STK_CHKOS_TASK_OPT_STK_CLR);                    //選項,指定是否允許堆棧檢驗,是否將堆棧清0,任務(wù)是否要13                                                                                 //進(jìn)行浮點(diǎn)運算等等。14                     15    /* 建立觸摸驅動(dòng)任務(wù) */16    OSTaskCreateExt(AppTaskKbd,17                        (void *)0,18                     (OS_STK *)&AppTaskKbdStk[APP_TASK_KBD_STK_SIZE-1],19                     APP_TASK_KBD_PRIO,20                     APP_TASK_KBD_PRIO,21                     (OS_STK *)&AppTaskKbdStk[0],22                     APP_TASK_KBD_STK_SIZE,23                     (void *)0,24                     OS_TASK_OPT_STK_CHKOS_TASK_OPT_STK_CLR);   25 26 }

這里以界面任務(wù)為例:因為我們在建立界面任務(wù)時(shí)已經(jīng)指定其任務(wù)代碼指針AppTaskUserIF,所以這里來(lái)寫(xiě)其對應的函數(也就是說(shuō)這里是界面任務(wù)的入口)。從下面的代碼可以看出進(jìn)入界面任務(wù)時(shí)首先對uc-GUI進(jìn)行初始化,然后進(jìn)入死循環(huán)不斷執行Fun()函數(有人會(huì )疑惑:這里while死循環(huán)不就只能死在這里嗎?怎么執行其他任務(wù)呢?,這就是具有操作系統和不具有操作系統的不同啦~雖然這里是while死循環(huán),但是當OS要把CPU占有權分給其他任務(wù)時(shí)就會(huì )把當前執行的任務(wù)的信息壓入其對應的??臻g,當再次要把CPU分配給該任務(wù)時(shí),則把棧里保存的上次執行的情況拿出來(lái)繼續執行,從而實(shí)現搶占與多任務(wù)的效果?。?/p>

1 static  void  AppTaskUserIF (void *p_arg)2 {                                               3  (void)p_arg;                                    4   GUI_Init();                    //ucgui初始化 5   while(1) 6   {    7      Fun();                     //界面主程序8   }9 }

所以接下來(lái)我們主要看Fun.c里的Fun函數:雖然代碼有點(diǎn)長(cháng),但是很好理解,其核心思路就是建立整個(gè)界面并對界面中的每個(gè)控件進(jìn)行相關(guān)設置同時(shí)獲得其句柄,在最后又進(jìn)入了while死循環(huán),在循環(huán)中不斷檢測2.4G是否接受到數據(和適配器端類(lèi)似也是中斷子程序中收數據然后置接收標志為1的),然后根據從2.4G收到的數據來(lái)刷新文本顯示區;下面一個(gè)if判斷speed_change_flag是否有效來(lái)向串口發(fā)送相應的數據。那么我們的問(wèn)題又來(lái)了:這個(gè)speed_change_flag是在哪里被改變的呢?這個(gè)我們就要參看窗口回調函數了!這里的窗口回調函數是窗口動(dòng)作響應函數(就像安卓開(kāi)發(fā)里的按鈕監聽(tīng)或MFC里的按鈕點(diǎn)擊事件等),一旦窗口里的控件有相應的觸發(fā)動(dòng)作就會(huì )調用該函數,并把事件類(lèi)型封裝在WM_MESSAGE里傳過(guò)來(lái),在該函數里對該消息進(jìn)行解析并作出相應的動(dòng)作即可(非常像Win32!!!我懷疑做這個(gè)uc-GUI的人有copy微軟的嫌疑,?(^∇^*)隨便猜測,如有雷同,純屬巧合)。這樣我們就很容易找到send按鈕的監聽(tīng)用于將數據通過(guò)NRF24L01發(fā)送出去的相關(guān)操作,也就明白了滑動(dòng)條監聽(tīng)用來(lái)改變speed1~5.上面說(shuō)了這么多,少了介紹整個(gè)界面是怎么建立的了~其實(shí)整個(gè)窗體的布局都要放在一個(gè)結構體里,然后在fun()函數里調用hWin = GUI_CreateDialogBox(aDialogCreate, GUI_COUNTOF(aDialogCreate), _cbCallback, 0, 0, 0);根據定義的窗口資源和回調函數進(jìn)行窗體的建立~這樣我們就圓滿(mǎn)地理解了stm32基于uc-OS并搭載uc-GUI的運行邏輯啦!



1 void Fun(void) {   2   GUI_CURSOR_Show();                                        //打開(kāi)鼠標圖形顯示  3   4   /* 建立對話(huà)框時(shí),包含了資源列表,資源數目, 并且指定了用于動(dòng)作響應的回調函數  */5   hWin = GUI_CreateDialogBox(aDialogCreate, GUI_COUNTOF(aDialogCreate), _cbCallback, 0, 0, 0);6 7   FRAMEWIN_SetFont(hWin, &GUI_FontComic18B_1);                  //對話(huà)框字體設置 8   FRAMEWIN_SetClientColor(hWin, GUI_BLACK);                      //對話(huà)框的窗體顏色是黑色9   memcpy(tx_buf, "1234567890abcdefghij!@#$%^&*()-=", 32);   //將長(cháng)度為32字節的發(fā)送字符串拷貝到發(fā)送緩沖區,10   memcpy(rx_buf, "", 32);                                    //將接收緩存區清空11  12   /* 獲得文本框句柄 */        13   text1 = WM_GetDialogItem(hWin, GUI_ID_TEXT0);                //獲得對話(huà)框里GUI_ID_TEXT0項目(文本框Send Text Area)的句柄14   text2 = WM_GetDialogItem(hWin, GUI_ID_TEXT1);                //獲得對話(huà)框里GUI_ID_TEXT1項目(文本框Receive Text Area)的句柄15   text3 = WM_GetDialogItem(hWin, GUI_ID_TEXT2);                //獲得對話(huà)框里GUI_ID_TEXT2項目(文本框2M BPS)的句柄16   text4 = WM_GetDialogItem(hWin, GUI_ID_TEXT3);                //獲得對話(huà)框里GUI_ID_TEXT3項目(文本框1M BPS)的句柄17   text6 = WM_GetDialogItem(hWin, GUI_ID_TEXT5);                //獲得對話(huà)框里GUI_ID_TEXT5項目(文本框250K BPS)的句柄18   text5 = WM_GetDialogItem(hWin, GUI_ID_TEXT4);                //獲得對話(huà)框里GUI_ID_TEXT4項目(狀態(tài)字符文本框)的句柄  19   /* 設置文本框字體 */20   TEXT_SetFont(text1,pFont);                                //設置對話(huà)框里文本框Send Text Area的字體21   TEXT_SetFont(text2,pFont);                                //設置對話(huà)框里文本框Receive Text Area的字體22   TEXT_SetFont(text3,pFont18);                                //設置對話(huà)框里文本框2M BPS的字體23   TEXT_SetFont(text4,pFont18);                                //設置對話(huà)框里文本框1M BPS的字體24   TEXT_SetFont(text6,pFont18);                                //設置對話(huà)框里文本框250K BPS的字體25   TEXT_SetFont(text5,pFont);                                //設置對話(huà)框里狀態(tài)字符文本框的字體26   /* 設置文本框顏色 */27   TEXT_SetTextColor(text1,GUI_GREEN);                        //設置對話(huà)框里文本框Send Text Area的字體顏色28   TEXT_SetTextColor(text2,GUI_GREEN );                        //設置對話(huà)框里文本框Receive Text Area的字體顏色29   TEXT_SetTextColor(text3,GUI_YELLOW);                        //設置對話(huà)框里文本框2M BPS的字體顏色30   TEXT_SetTextColor(text4,GUI_YELLOW);                        //設置對話(huà)框里文本框1M BPS的字體顏色31   TEXT_SetTextColor(text6,GUI_YELLOW);                       //設置對話(huà)框里文本框250K BPS的字體顏色32   TEXT_SetTextColor(text5,GUI_YELLOW);                        //設置對話(huà)框里狀態(tài)字符文本框的字體顏色33   TEXT_SetBkColor(text5,GUI_BLUE);                            //設置對話(huà)框里狀態(tài)字符文本框的背景顏色34 35   /* 編輯框相關(guān) */36   edit1 = WM_GetDialogItem(hWin, GUI_ID_EDIT1);                //獲得對話(huà)框里GUI_ID_EDIT1項目(編輯框 發(fā)送字符串顯示區)的句柄37   EDIT_SetFont(edit1,pFont18);                                //設置對話(huà)框里編輯框 發(fā)送字符串顯示區的字體38   EDIT_SetText(edit1,(const char *)tx_buf);                    //設置對話(huà)框里編輯框 發(fā)送字符串顯示區的字符串39   edit2 = WM_GetDialogItem(hWin, GUI_ID_EDIT2);                //獲得對話(huà)框里GUI_ID_EDIT2項目(編輯框 接收字符串顯示區)的句柄40   EDIT_SetFont(edit2,pFont18);                                //設置對話(huà)框里編輯框 接收字符串顯示區的字體41   EDIT_SetText(edit2,(const char *)rx_buf);                    //設置對話(huà)框里編輯框 接收字符串顯示區的字符串42 43   /* 按鈕相關(guān) */44   bt[0]=WM_GetDialogItem(hWin,GUI_ID_BUTTON0);                //獲得對話(huà)框里GUI_ID_BUTTON0項目(按鍵SEND)的句柄45   bt[1]=WM_GetDialogItem(hWin, GUI_ID_BUTTON2);                //獲得對話(huà)框里GUI_ID_BUTTON2項目(按鍵CLEAR)的句柄46   BUTTON_SetFont(bt[0],pFont);                                //設置對話(huà)框里按鍵SEND的字體47   BUTTON_SetFont(bt[1],pFont);                                //設置對話(huà)框里按鍵CLEAR的字體48   BUTTON_SetTextColor(bt[0],0,GUI_WHITE);                     //設置對話(huà)框里按鍵SEND未被按下的字體顏色49   BUTTON_SetTextColor(bt[1],0,GUI_WHITE);                    //設置對話(huà)框里按鍵CLEAR未被按下的字體顏色50 51   /* List相關(guān) */            52   nrf_Pipe=0;                                                //NRF24L01初始發(fā)射通道設置為053   list1 = WM_GetDialogItem(hWin, GUI_ID_LISTBOX0);            //獲得對話(huà)框里GUI_ID_LISTBOX0項目(列表框-通道選擇)的句柄     54   LISTBOX_SetText(list1, _apListBox);                        //設置對話(huà)框里列表框-通道選擇里的條目55   LISTBOX_SetFont(list1,pFont18);                            //設置對話(huà)框里列表框-通道選擇的字體56   LISTBOX_SetSel(list1,nrf_Pipe);                            //設置對話(huà)框里列表框-通道選擇的焦點(diǎn)選擇57   SCROLLBAR_CreateAttached(list1, SCROLLBAR_CF_VERTICAL);    //設置對話(huà)框里列表框-通道選擇的卷動(dòng)方向為下拉        58 59   /* Radio按鈕相關(guān) */        60   rd0 = WM_GetDialogItem(hWin, GUI_ID_RADIO0);                //獲得對話(huà)框里GUI_ID_RADIO0項目(點(diǎn)選框-速率選擇)的句柄61   nrf_baud=0;                                                //NRF24L01速率 初始為2MPS62   RADIO_SetValue(rd0,0);                                    //設置對話(huà)框里點(diǎn)選框-速率選擇的焦點(diǎn)選擇63   RX_Mode();                                                //NRF24L01進(jìn)入接收模式 64  65   /* 獲得slider部件的句柄 */    66   slider1 = WM_GetDialogItem(hWin, GUI_ID_SLIDER1);67   slider2 = WM_GetDialogItem(hWin, GUI_ID_SLIDER2);68   slider3 = WM_GetDialogItem(hWin, GUI_ID_SLIDER3);69   slider4 = WM_GetDialogItem(hWin, GUI_ID_SLIDER4);70   slider5 = WM_GetDialogItem(hWin, GUI_ID_SLIDER5);71   /* 設置slider部件的取值范圍-8-8*/  72   SLIDER_SetRange(slider1,-8,8);    73   SLIDER_SetRange(slider2,-8,8);74   SLIDER_SetRange(slider3,-8,8);75   SLIDER_SetRange(slider4,-8,8);76   SLIDER_SetRange(slider5,-8,8);77   /* 設置slider部件的值*/      78   SLIDER_SetValue(slider1,0);  79   SLIDER_SetValue(slider2,0);    80   SLIDER_SetValue(slider3,0);  81   SLIDER_SetValue(slider4,0);  82   SLIDER_SetValue(slider5,0);  83   /* 獲取文本框句柄 */84   text_speed1 = WM_GetDialogItem(hWin, GUI_ID_TEXT_SPEED1);    85   text_speed2 = WM_GetDialogItem(hWin, GUI_ID_TEXT_SPEED2);    86   text_speed3 = WM_GetDialogItem(hWin, GUI_ID_TEXT_SPEED3);    87   text_speed4 = WM_GetDialogItem(hWin, GUI_ID_TEXT_SPEED4);    88   text_speed5 = WM_GetDialogItem(hWin, GUI_ID_TEXT_SPEED5);    89   /* 設置文本框字體 */90   TEXT_SetFont(text_speed1,pFont18);91   TEXT_SetFont(text_speed2,pFont18);92   TEXT_SetFont(text_speed3,pFont18);93   TEXT_SetFont(text_speed4,pFont18);94   TEXT_SetFont(text_speed5,pFont18);                                    95   /* 設置文本框顏色 */96   TEXT_SetTextColor(text_speed1,GUI_YELLOW);        97   TEXT_SetTextColor(text_speed2,GUI_YELLOW);        98   TEXT_SetTextColor(text_speed3,GUI_YELLOW);        99   TEXT_SetTextColor(text_speed4,GUI_YELLOW);        100   TEXT_SetTextColor(text_speed5,GUI_YELLOW);        101 102   speed_change_flag=0;103 104   while (1)105   {               106     if(Rx_Succ==1){                                            //當NRF24L01接收到有效數據107         EDIT_SetText(edit2,(const char *)rx_buf);            //將接收緩沖區的字符寫(xiě)入到接收字符編輯框內108         TEXT_SetText(text5,(const char *)status_buf);        //將狀態(tài)文本緩沖區的字符寫(xiě)入到狀態(tài)文本框內109         Rx_Succ=0; 110 //        for(i=0;i
Fun()


1 /****************************************************************************2 * 名    稱(chēng):static void _cbCallback(WM_MESSAGE * pMsg)3 * 功    能:ucgui回調函數,是作為對話(huà)框動(dòng)作響應的函數4 * 入口參數:無(wú)5 * 出口參數:無(wú)6 * 說(shuō)    明:7 * 調用方法:8 ****************************************************************************/  9 static void _cbCallback(WM_MESSAGE * pMsg) {10   int NCode, Id;11   switch (pMsg->MsgId) {12     case WM_NOTIFY_PARENT:                          //通知父窗口有事件在窗口部件上發(fā)生13       Id    = WM_GetId(pMsg->hWinSrc);            //獲得對話(huà)框窗口里發(fā)生事件的部件的ID14       NCode = pMsg->Data.v;                       //通知代碼15       switch (NCode) {16         case WM_NOTIFICATION_RELEASED:            //窗體部件動(dòng)作被釋放             17           if (Id == GUI_ID_BUTTON2) {             //按鍵CLEAR被松開(kāi)18             memcpy(status_buf, "", 20);              //清空狀態(tài)文本緩沖區 19             memcpy(rx_buf, "", 32);                  //清空接收文本緩沖區         20             TEXT_SetText(text5,(const char *)status_buf);           //清空狀態(tài)文本框    21             EDIT_SetText(edit2,(const char *)rx_buf);            //清空接收字符編輯框22             memcpy(tx_buf, "", 32);                //清空發(fā)送文本緩沖區23             NRF24L01_TXBUF(tx_buf,32);            //將發(fā)送字符緩沖區的字符通過(guò)NRF24L01發(fā)送出去        24           }          25           else if (Id == GUI_ID_BUTTON0) {      //按鍵SEND 被松開(kāi)26               memcpy(tx_buf, "1234567890abcdefghij!@#$%^&*()-=", 32);      //將32字節的文本拷貝到發(fā)送文本緩沖區27             memcpy(rx_buf, "", 32);                //清空接收文本緩沖區     28             memcpy(status_buf, "", 20);            //清空狀態(tài)文本緩沖區 29             EDIT_SetText(edit2,(const char *)rx_buf);            //清空接收字符編輯框    30             NRF24L01_TXBUF(tx_buf,32);            //將發(fā)送字符緩沖區的字符通過(guò)NRF24L01發(fā)送出去31             memcpy(tx_buf, "", 32);                //清空發(fā)送文本緩沖區32             TEXT_SetText(text5,(const char *)status_buf);        //清空狀態(tài)文本框               33           }34           else if (Id == GUI_ID_RADIO0) {       //NRF24L01無(wú)線(xiàn)速率點(diǎn)選框點(diǎn)選動(dòng)作完成35               nrf_baud= RADIO_GetValue(rd0);        //獲得速率表示值36             RX_Mode();                            //進(jìn)入接收模式            37           }38           else if (Id == GUI_ID_LISTBOX0){      //NRF24L01無(wú)線(xiàn)通道選擇動(dòng)作39             nrf_Pipe= LISTBOX_GetSel(list1);    //獲得NRF24LL01無(wú)線(xiàn)通道表示值             40             RX_Mode();                           //進(jìn)入接收模式     41           }else if(Id == GUI_ID_SLIDER1){       //slider1 的值被改變42             speed1=SLIDER_GetValue(slider1);//獲得slider1的值43             if(speed1>0){44                speed_show[0]=+;45                speed_show[1]=0+speed1;46                control_data=8+speed1;47             }else if(speed1<0){48                speed_show[0]=-;49                speed_show[1]=0-speed1;50                control_data=16-speed1;51             }else{52                speed_show[0]= ;53                speed_show[1]=0;54                control_data=0;55             }56 //            USART_SendChar(USART1,control_data);57             TEXT_SetText(text_speed1,speed_show);58             speed_change_flag=1;                     59           }else if(Id == GUI_ID_SLIDER2){       //slider2 的值被改變60             speed2=SLIDER_GetValue(slider2);//獲得slider2的值61             if(speed2>0){62                speed_show[0]=+;63                speed_show[1]=0+speed2;64                control_data=32+8+speed2;65             }else if(speed2<0){66                speed_show[0]=-;67                speed_show[1]=0-speed2;68                control_data=32+16-speed2;69             }else{70                speed_show[0]= ;71                speed_show[1]=0;72                control_data=0;73             }74             TEXT_SetText(text_speed2,speed_show);75             speed_change_flag=1;            76           }else if(Id == GUI_ID_SLIDER3){       //slider3 的值被改變77             speed3=SLIDER_GetValue(slider3);//獲得slider3的值78             if(speed3>0){79                speed_show[0]=+;80                speed_show[1]=0+speed3;81                control_data=64+8+speed3;82             }else if(speed3<0){83                speed_show[0]=-;84                speed_show[1]=0-speed3;85                control_data=64+16-speed3;86             }else{87                speed_show[0]= ;88                speed_show[1]=0;89                control_data=0;90             }91             TEXT_SetText(text_speed3,speed_show);92             speed_change_flag=1;      93           }else if(Id == GUI_ID_SLIDER4){       //slider4 的值被改變94             speed4=SLIDER_GetValue(slider4);//獲得slider4的值95             if(speed4>0){96                speed_show[0]=+;97                speed_show[1]=0+speed4;98                control_data=96+8+speed4;99             }else if(speed4<0){100                speed_show[0]=-;      101                speed_show[1]=0-speed4;102                control_data=96+16-speed4;103             }else{104                speed_show[0]= ;105                speed_show[1]=0;106                control_data=0;107             }108             TEXT_SetText(text_speed4,speed_show);109             speed_change_flag=1;      110           }else if(Id == GUI_ID_SLIDER5){       //slider5 的值被改變speed5=SLIDER_GetValue(slider5);//獲得slider5的值112             if(speed5>0){113                speed_show[0]=+;114                speed_show[1]=0+speed5;115                control_data=128+8+speed5;116             }else if(speed5<0){117                speed_show[0]=-;118                speed_show[1]=0-speed5;119                control_data=128+16-speed5;120             }else{121                speed_show[0]= ;122                speed_show[1]=0;123                control_data=0;124             }125             TEXT_SetText(text_speed5,speed_show);126             speed_change_flag=1;      127           }128          break;129          default: break;130       }        131     default:132       WM_DefaultProc(pMsg);                        //默認程序來(lái)處理消息133       break;134   }135 }
窗口回調函數
1 /* 定義了對話(huà)框資源列表 */2 static const GUI_WIDGET_CREATE_INFO aDialogCreate[] = {3   //建立窗體, 大小是800X480  原點(diǎn)在0,04   { FRAMEWIN_CreateIndirect, "http://beautifulzzzz", 0,0,0, 800, 480, FRAMEWIN_CF_ACTIVE },5   { BUTTON_CreateIndirect,   "SEND",    GUI_ID_BUTTON0,       0,    395,  200,  55 },6  7   { BUTTON_CreateIndirect,   "CLEAR", GUI_ID_BUTTON2,   200,    395, 200,  55 },8   { EDIT_CreateIndirect,     "",       GUI_ID_EDIT1,    0,   190, 400,  65, EDIT_CF_LEFT, 50 },9   { EDIT_CreateIndirect,     "",       GUI_ID_EDIT2,    0,   290, 400,  65, EDIT_CF_LEFT, 50 },10   11   //建立TEXT控件,起點(diǎn)是窗體的X,X,大小XXY  文字左對齊12   { TEXT_CreateIndirect,     "Send Text Area",  GUI_ID_TEXT0,   1,   160,  400,  25, TEXT_CF_LEFT },13   { TEXT_CreateIndirect,     "Receive Text Area ",  GUI_ID_TEXT1,     1,   263,  400, 25, TEXT_CF_LEFT },14  15   { TEXT_CreateIndirect,     "2M bps",  GUI_ID_TEXT2,   23,   22,  140,  25, TEXT_CF_LEFT },16   { TEXT_CreateIndirect,     "1M bps",  GUI_ID_TEXT3,     23,   42,  140,  25, TEXT_CF_LEFT },17   { TEXT_CreateIndirect,     "250K bps",  GUI_ID_TEXT5,     23,   62,  140,  25, TEXT_CF_LEFT },18   19   { TEXT_CreateIndirect,     "",  GUI_ID_TEXT4,     0,   120,  400,  25, TEXT_CF_LEFT },20 21   { RADIO_CreateIndirect,     "Receive Mode",  GUI_ID_RADIO0,     3,   33,  40,  52, RADIO_TEXTPOS_LEFT,3},22 23   { LISTBOX_CreateIndirect,  "",       GUI_ID_LISTBOX0,  134,    13,  130,  90, 0, 0 },24 25    //建立滑塊26   { SLIDER_CreateIndirect,   NULL,     GUI_ID_SLIDER1,  440,  60, 320, 25, 0, 0 },27   { SLIDER_CreateIndirect,   NULL,     GUI_ID_SLIDER2,  440,  120, 320, 25, 0, 0 },28   { SLIDER_CreateIndirect,   NULL,     GUI_ID_SLIDER3,  440,  180, 320, 25, 0, 0 },29   { SLIDER_CreateIndirect,   NULL,     GUI_ID_SLIDER4,  440,  240, 320, 25, 0, 0 },30   { SLIDER_CreateIndirect,   NULL,     GUI_ID_SLIDER5,  440,  300, 320, 25, 0, 0 },31   //建立滑塊對應的text32   { TEXT_CreateIndirect,     "0",  GUI_ID_TEXT_SPEED1,   770,   60,   25,  25, TEXT_CF_LEFT },33   { TEXT_CreateIndirect,     "0",  GUI_ID_TEXT_SPEED2,   770,   120,  25,  25, TEXT_CF_LEFT },34   { TEXT_CreateIndirect,     "0",  GUI_ID_TEXT_SPEED3,   770,   180,  25,  25, TEXT_CF_LEFT },35   { TEXT_CreateIndirect,     "0",  GUI_ID_TEXT_SPEED4,   770,   240,  25,  25, TEXT_CF_LEFT },36   { TEXT_CreateIndirect,     "0",  GUI_ID_TEXT_SPEED5,   770,   300,  25,  25, TEXT_CF_LEFT },37 };

還要回過(guò)頭說(shuō)說(shuō)我們的USART和NRF24L01,他們的初始化要看main函數中的BSP_Init();函數,該函數負相關(guān)硬件的初始化設置(中文意思是板級支持包初始化函數,因為uc-OS可以并不只限于stm32單片機,所以這里要根據不同平臺進(jìn)行相應的設置)。該函數位于bsp.c函數中,其作用相當于將以前我們在main函數中進(jìn)行的相關(guān)硬件初始化單獨拿出來(lái)封裝成一個(gè)函數而已~但是,串口和無(wú)線(xiàn)對應的中斷接收程序卻有點(diǎn)不一樣,因為這里是操作系統,所以在每個(gè)中斷子程序前要調用OS_ENTER_CRITICAL();保存當前的全局中斷標志,然后OSIntNesting++;中斷嵌套深度加1,最后調用OS_EXIT_CRITICAL();恢復全局中斷標志進(jìn)入正常的中斷處理,此外在中斷響應函數最后要調用OSIntExit(); 檢測如果有更高優(yōu)先級的任務(wù)就緒了,則執行一次任務(wù)切換。



1 /*******************************************************************************2 * Function Name  : USART1_IRQHandler3 * Description    : This function handles USART1 global interrupt request.4 * Input          : None5 * Output         : None6 * Return         : None7 *******************************************************************************/8 void USART1_IRQHandler(void)9 { 10     unsigned int i;11     OS_CPU_SR  cpu_sr;12     OS_ENTER_CRITICAL();  //保存全局中斷標志,關(guān)總中斷 Tell uC/OS-II that we are starting an ISR13     OSIntNesting++;14     OS_EXIT_CRITICAL();      //恢復全局中斷曛?        15 16     if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)       //判斷讀寄存器是否非空17     {    18         RxBufferUSART[RxCounter1++] = USART_ReceiveData(USART1);   //將讀寄存器的數據緩存到接收緩沖區里19         if(RxBufferUSART[RxCounter1-2]==0x0d&&RxBufferUSART[RxCounter1-1]==0x0a)     //判斷結束標志是否是0x0d 0x0a20         {21             for(i=0; i< RxCounter1; i++) TxBufferRF[i] = RxBufferUSART[i];          //將接收緩沖器的數據轉到發(fā)送緩沖區,準備轉發(fā)22             usart_rec_flag=1;                                                             //接收成功標志23             TxBufferRF[RxCounter1]=0;                                             //發(fā)送緩沖區結束符    24             TxCounter1=RxCounter1;25             RxCounter1=0;26         }27     }28     if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)                   //這段是為了避免STM32 USART 第一個(gè)字節發(fā)不出去的BUG 29     { 30         USART_ITConfig(USART1, USART_IT_TXE, DISABLE);                         //禁止發(fā)緩沖器空中斷, 31     }    32     OSIntExit();           //在os_core.c文件里定義,如果有更高優(yōu)先級的任務(wù)就緒了,則執行一次任務(wù)切換    33 }34 /////////////////////////////35 void EXTI0_IRQHandler(void)36 { 37   unsigned char status,i;38   OS_CPU_SR  cpu_sr;39   OS_ENTER_CRITICAL();  //保存全局中斷標志,關(guān)總中斷 Tell uC/OS-II that we are starting an ISR40   OSIntNesting++;41   OS_EXIT_CRITICAL();      //恢復全局中斷標志             42   43   if(EXTI_GetITStatus(EXTI_Line0) != RESET)            //判斷是否產(chǎn)生了EXTI0中斷44   {45       if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==0){ //判斷是否是PA0線(xiàn)變低            46         status=SPI_Read(READ_REG1+STATUS);            // 讀取狀態(tài)寄存其來(lái)判斷數據接收狀況    47         if(status & 0x40)                            // 判斷是否接收到數據                   48         {                                                         49              SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);  //從接收緩沖區里讀出數據 50             for(i=0; i<32; i++){                              //向USB 端點(diǎn)1的緩沖區里放置數據51                 TxBufferUSART[i] = rx_buf[i];     52             }53             rf_rec_flag=1;          54             if((status&0x0e)<=0x0a){                           55                nrf_Pipe_r=(status&0x0e)>>1;                      //讀出是在哪個(gè)通道接收的56             }57             else nrf_Pipe_r=0;                     58             Rx_Succ=1;            //讀取數據完成標志59             /* 根據讀出的接收通道號,將相應信息寫(xiě)入狀態(tài)文本緩沖區 */60             if(nrf_Pipe_r==0) memcpy(status_buf, "Pipe 0 Recive OK!   ", 20);           61             else if(nrf_Pipe_r==1) memcpy(status_buf, "Pipe 1 Recive OK!   ", 20);62             else if(nrf_Pipe_r==2) memcpy(status_buf, "Pipe 2 Recive OK!   ", 20);63             else if(nrf_Pipe_r==3) memcpy(status_buf, "Pipe 3 Recive OK!   ", 20);64             else if(nrf_Pipe_r==4) memcpy(status_buf, "Pipe 4 Recive OK!   ", 20);65             else if(nrf_Pipe_r==5) memcpy(status_buf, "Pipe 5 Recive OK!   ", 20);66         }67         else if((status &0x10)>0){                     //發(fā)射達到最大復發(fā)次數                68             SPI_RW_Reg(0xe1,0);                          //清除發(fā)送緩沖區                  69             RX_Mode();                                 //進(jìn)入接收模式                                 70             Rx_Succ=1;                                                                                    71             /* 根據發(fā)送通道,將相應信息寫(xiě)入狀態(tài)文本緩沖區 */72             if(nrf_Pipe==0) memcpy(status_buf, "Pipe 0 NO ACK!      ", 20);73             else if(nrf_Pipe==1) memcpy(status_buf, "Pipe 1 NO ACK!      ", 20);74             else if(nrf_Pipe==2) memcpy(status_buf, "Pipe 2 NO ACK!      ", 20);75             else if(nrf_Pipe==3) memcpy(status_buf, "Pipe 3 NO ACK!      ", 20);  76             else if(nrf_Pipe==4) memcpy(status_buf, "Pipe 4 NO ACK!      ", 20);77             else if(nrf_Pipe==5) memcpy(status_buf, "Pipe 5 NO ACK!      ", 20);            78         }79         else if((status &0x20)>0){                     //發(fā)射后收到應答             80             SPI_RW_Reg(0xe1,0);                         //清除發(fā)送緩沖區              81             RX_Mode();                                 //進(jìn)入接收模式82             Rx_Succ=1;83             /* 根據發(fā)送通道,將相應信息寫(xiě)入狀態(tài)文本緩沖區 */84             if(nrf_Pipe==0) memcpy(status_buf, "Pipe 0 Send OK!     ", 20);85             else if(nrf_Pipe==1) memcpy(status_buf, "Pipe 1 Send OK!     ", 20);86             else if(nrf_Pipe==2) memcpy(status_buf, "Pipe 2 Send OK!     ", 20);87             else if(nrf_Pipe==3) memcpy(status_buf, "Pipe 3 Send OK!     ", 20);88             else if(nrf_Pipe==4) memcpy(status_buf, "Pipe 4 Send OK!     ", 20);89             else if(nrf_Pipe==5) memcpy(status_buf, "Pipe 5 Send OK!     ", 20);               90         }91         92         SPI_RW_Reg(WRITE_REG1+STATUS, status);         //清除07寄存器標志              93       }        94       EXTI_ClearITPendingBit(EXTI_Line0);             //清除EXTI0上的中斷標志              95   }   96   OSIntExit();           //在os_core.c文件里定義,如果有更高優(yōu)先級的任務(wù)就緒了,則執行一次任務(wù)切換     97 }
串口和無(wú)線(xiàn)中斷子程序

最后說(shuō)明

對于純玩軟件的小伙伴,這里涉及的東西有點(diǎn)多,不必細究,看看了解即可。但是對于初學(xué)stm32,尤其是還在為stm32控制NRF24L01不通的同學(xué),這個(gè)還是挺有用



評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>