日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

UART0串口编程(六):串口(UART0)之UC/OS(二)UC/OS下的串口接收任务编程

發(fā)布時間:2025/6/15 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 UART0串口编程(六):串口(UART0)之UC/OS(二)UC/OS下的串口接收任务编程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

串口(UART0)之UC/OS(二)

一.串口接收數(shù)據(jù)在UC/OS設(shè)計中應(yīng)注意的問題

1. ???串口通信的數(shù)據(jù)接收過程:

1> ?UART 接收FIFO接收到預(yù)定字節(jié)后觸發(fā)中斷

2> ?ISR讀取接收到的內(nèi)容并保存

3> ?經(jīng)過一次或若干次ISR完成一個通信幀的接收(拼裝通信幀)

4> ?處理和解釋通信內(nèi)容

5> ?根據(jù)處理結(jié)果觸發(fā)其他任務(wù)

2. ???串口數(shù)據(jù)接收程序設(shè)計時,應(yīng)該考慮的問題:

1>即使以上的操作過程很簡單,也最好不要把它全部安排在ISR中完成,如果放在一起的話,就會給UART0通信帶來危機(jī)(此處具體請看前面的文章)。

2>所以要安排一個與ISR關(guān)聯(lián)的“串口接收”任務(wù)來完成后面的工作。再創(chuàng)建一個幀緩沖區(qū)。在接收的過程中,將接收到的內(nèi)容寫入幀緩沖區(qū)。接收完一幀后,處理和解釋過程需要讀幀緩沖區(qū)的內(nèi)容。

3>將寫幀緩沖區(qū)的操作安排在ISR中完成,讀幀緩沖去的操作安排在串口接收任務(wù)中完成。

4>由于ISR和串口接收任務(wù)是并發(fā)程序單元,存在資源同步問題,故需要對幀緩沖區(qū)進(jìn)行互斥訪問。

二.設(shè)計ISR與串口接收任務(wù)之間的通信方法:

1. ISR的主要功能是響應(yīng)異步事件,該異步事件將觸發(fā)一系列操作。ISR設(shè)計的基本原則是:盡可能簡短。

2.ISR與關(guān)聯(lián)任務(wù)的通信方式有兩種類型:信號型和數(shù)據(jù)型。

1>當(dāng)使用信號量進(jìn)行通信時,ISR只完成發(fā)送信號量的工作,表示事件已經(jīng)發(fā)生,通過信號量的同步功能觸發(fā)關(guān)聯(lián)任務(wù)。

2>當(dāng)使用數(shù)據(jù)進(jìn)行通信時,ISR需要完成對異步事件的信息進(jìn)行采集工作,然后使用消息郵箱(或消息隊(duì)列)將數(shù)據(jù)發(fā)送給關(guān)聯(lián)任務(wù),由關(guān)聯(lián)任務(wù)完成后續(xù)數(shù)據(jù)處理工作。

3>做項(xiàng)目時常見的三種情況:

? ?觸發(fā)ISR的事件不包含數(shù)據(jù):不需要對事件進(jìn)行信息采集。此時,ISR使用信號量與關(guān)聯(lián)任務(wù)進(jìn)行通信。

? ?觸發(fā)ISR的事件是包含數(shù)據(jù)的低頻事件:將數(shù)據(jù)采集的工作放在關(guān)聯(lián)任務(wù)中完成,(產(chǎn)生的時刻延遲與采樣周期相比可以忽略不計,對采集數(shù)據(jù)的質(zhì)量沒有影響。此時,ISR使用信號量與關(guān)聯(lián)任務(wù)進(jìn)行通信,從而簡化了ISR。

? ?觸發(fā)ISR的事件是包含數(shù)據(jù)的中高頻事件:數(shù)據(jù)采集的工作放在關(guān)聯(lián)任務(wù)中完成時,產(chǎn)生的時延與采樣周期相比不能忽略不計時,對采樣數(shù)據(jù)的質(zhì)量有影響。此時,關(guān)聯(lián)任務(wù)從消息郵箱中得到消息的數(shù)據(jù),并完成后續(xù)處理工作。

? ?觸發(fā)ISR的事件是包含數(shù)據(jù)的非周期高頻率事件:對于非周期高頻事件,其最短事件間隔可能小于一個事件數(shù)據(jù)處理的耗時,如果使用消息郵箱進(jìn)行通信,就可能會出現(xiàn)數(shù)據(jù)丟失現(xiàn)象。此時,數(shù)據(jù)采集的工作應(yīng)該在ISR中完成,由ISR使用具有數(shù)據(jù)緩沖功能的消息隊(duì)列與關(guān)聯(lián)任務(wù)進(jìn)行通信。關(guān)聯(lián)任務(wù)從消息隊(duì)列中得到消息的數(shù)據(jù),并完成后續(xù)處理工作。

注意:具體采用那一種方式來實(shí)現(xiàn)ISR與串口接收任務(wù)之間的通信要視具體情況而定。

以下用信號量和消息隊(duì)列兩種方式來實(shí)現(xiàn)串口接收編程

三. ??UC/OS串口接收數(shù)據(jù)編程

通過一個程序來分析UC/OS串口接收數(shù)據(jù)設(shè)計和實(shí)現(xiàn)

程序設(shè)計目標(biāo):

用串口中斷接收上位機(jī)發(fā)送的8字節(jié)數(shù)據(jù),再把它們傳送給上位機(jī)。

u 用信號量的方式

1.系統(tǒng)有那些任務(wù)組成

1> ?啟動任務(wù)

2> ?接收任務(wù)

3> ?接收中斷服務(wù)例程

4> ?發(fā)送任務(wù)

2.各任務(wù)之間的關(guān)系

?

3.啟動任務(wù)流程:

l ?定義各種通信工具(例如:信號量)

l ?系統(tǒng)硬件初始化

l ?初始化UART0

l ?創(chuàng)建各個任務(wù)

l ?創(chuàng)建各種通信工具

l ?刪除自己

?

程序:

?

/********************************************************************** Task0(啟動任務(wù))********************************************************************/void Task0 (void *pdata){pdata = pdata; TargetInit(); //硬件初始化 UART0_Init(115200); //初始化串口Sem_SendFlag = OSSemCreate(0); //創(chuàng)建發(fā)送信號量Sem_StartFlag = OSSemCreate(1); //創(chuàng)建開始信號量OSTaskCreate(Task1,(void *)0, &TaskStk1[TaskStkLengh - 1],4); //創(chuàng)建接收任務(wù)OSTaskCreate(Task2,(void *)0, &TaskStk2[TaskStkLengh - 1],5); //創(chuàng)建發(fā)送任務(wù)OSTaskDel(OS_PRIO_SELF); //刪除自己 }

?

?

4.接收任務(wù)流程

?

?

l ?等待開始信號量

l ?處理和解釋通信內(nèi)容(本程序較簡單,不涉及)

程序:

?

/********************************************************************Task1(接收任務(wù))********************************************************************/void Task1 (void *pdata){uint8 err;pdata = pdata;while(1){OSSemPend(Sem_StartFlag,0,&err); //等帶開始信號量//以下可以根據(jù)具體業(yè)務(wù)來編寫處理和解釋通信內(nèi)容}}

?

?

5.串口中斷接收流程:

?

?

l ?關(guān)中斷

l ?清除串口中斷標(biāo)志位

l ?清除中斷控制寄存器

l ?接收數(shù)據(jù)放入緩沖區(qū)

l ?開中斷

l ?發(fā)送發(fā)送信號量

?

程序:

?

/*********************************************************** 名 稱: UART0_Exception* 功 能: 串口接收中斷* 入口參數(shù): 無* 出口參數(shù): 無**********************************************************/void UART0_Exception(void){uint8 i;uint32 data;OS_ENTER_CRITICAL();data = U0IIR; //清除中斷表示寄存器標(biāo)志VICVectAddr = 0; //清除中斷for(i=0; i<8; i++){rcv_buf[i] = U0RBR; // 讀取FIFO的數(shù)據(jù)}OS_EXIT_CRITICAL();OSSemPost(Sem_SendFlag); //發(fā)送發(fā)送信號量}

?

?

6.發(fā)送任務(wù)流程

?

?

l ?等待發(fā)送信號量

l ?發(fā)送數(shù)據(jù)

l ?發(fā)送開始信號量

?

程序:

?

/************************************************************ Task2(發(fā)送任務(wù))**********************************************************/void Task2 (void *pdata){uint8 i,err;pdata = pdata;while(1){OSSemPend(Sem_SendFlag,0,&err); //等待發(fā)送信號量for(i = 0;i < 8; i++)UART0_SendByte(rcv_buf[i]); //通過輪訓(xùn)方式來發(fā)送串口數(shù)據(jù)OSSemPost(Sem_StartFlag); //發(fā)送開始信號量} }

?

?

發(fā)送數(shù)據(jù)函數(shù):

?

?

?

/*********************************************************** 名 稱: UART0_SendByte* 功 能: 向串口發(fā)送字節(jié)數(shù)據(jù),并等待發(fā)送完畢。* 入口參數(shù): data 要發(fā)送的數(shù)據(jù)* 出口參數(shù): 無**********************************************************/void UART0_SendByte(uint8 data){U0THR = data; while(0 == (U0LSR & 0x40));}

?

u 用消息隊(duì)列接收數(shù)據(jù)的方式

?

1. ???系統(tǒng)有那些任務(wù)組成

1>啟動任務(wù)

2>接收任務(wù)(中調(diào)用一個接受處理函數(shù))

3>接收中斷服務(wù)例程

4>發(fā)送任務(wù)

2. ???各任務(wù)之間的關(guān)系

?

?

3.啟動任務(wù)流程:

l ?定義各種通信工具(例如:信號量)

l ?系統(tǒng)硬件初始化

l ?初始化UART0

l ?創(chuàng)建各個任務(wù)

l ?創(chuàng)建各種通信工具

l ?刪除自己

?

程序:

?

/********************************************************************Task0(啟動任務(wù))********************************************************************/void Task0 (void *pdata){pdata = pdata; TargetInit(); //硬件初始化 UART0_Init(115200); //初始化串口Sem_SendFlag = OSSemCreate(0); //創(chuàng)建發(fā)送信號量Sem_StartFlag = OSSemCreate(1); //創(chuàng)建開始信號量ReMsg_Qeue = OSQCreate(&MsgGrp_Buf[0],10); //創(chuàng)建消息隊(duì)列OSTaskCreate(Task1,(void *)0, &TaskStk1[TaskStkLengh - 1],4); //創(chuàng)建接收任務(wù)OSTaskCreate(Task2,(void *)0, &TaskStk2[TaskStkLengh - 1],5); //創(chuàng)建發(fā)送任務(wù)OSTaskDel(OS_PRIO_SELF); //刪除自己}

?

?

4.接收任務(wù)流程

?

?

l ?等待開始信號量

l ?處理接收數(shù)據(jù)

l ?發(fā)送發(fā)送信號量

?

程序:

?

/********************************************************************** Task1(接收任務(wù))********************************************************************/void Task1 (void *pdata){uint8 err;pdata = pdata;while(1){OSSemPend(Sem_StartFlag,0,&err); //等待開始信號量UART0_RcvData(rcv_buf,2); //接收數(shù)據(jù)OSSemPost(Sem_SendFlag); //發(fā)送發(fā)送信號量}}

?

?

處理接收數(shù)據(jù)函數(shù):

?

?

?

/********************************************************************* 名 稱: Rcv_Data* 功 能: rcv_buf:接收中斷返回后的數(shù)據(jù) count :控制中斷次數(shù)* 入口參數(shù): 無* 出口參數(shù): 無********************************************************************/void UART0_RcvData(uint8 *rcv_buf,uint8 count){uint8 i;uint8 j;uint32 rcv_data;uint8 err;for(j = 0;j < count;j++){//等待消息隊(duì)列rcv_data = (uint32)(uint32 *)OSQPend(ReMsg_Qeue,0,&err);if(0x11223344 == rcv_data) {rcv_data = 0x12345678;} //將每條消息分解為4字節(jié),存入幀緩沖區(qū)for(i = 0;i < 4;i++){rcv_buf[4*j+3-i] = (uint8)(rcv_data&0xff);rcv_data >>= 8;}}}

?

?

5.串口中斷接收流程:

?

?

l ?關(guān)中斷

l ?清除串口中斷標(biāo)志位

l ?清除中斷控制寄存器

l ?接收4字節(jié)數(shù)據(jù)拼裝成32為地址

l ?發(fā)送消息郵箱

l ?開中斷

?

程序:

?

/********************************************************************* 名 稱: UART0_Exception* 功 能: 串口接收中斷* 入口參數(shù): 無* 出口參數(shù): 無********************************************************************/void UART0_Exception(void){uint8 i;uint32 data;OS_ENTER_CRITICAL();data = U0IIR; //清除中斷表示寄存器標(biāo)志VICVectAddr = 0; //清除中斷for(i = 0;i < 4;i++){data = (data << 8) | U0RBR; //將接受四字節(jié)數(shù)據(jù)拼裝成32位地址}if(0x00000000 == data){data = 0x11223344; //防止00000000地址不能發(fā)送}OSQPost(ReMsg_Qeue,(void *)data); //發(fā)送該地址到消息郵箱OS_EXIT_CRITICAL();}

?

?

6.發(fā)送任務(wù)流程

?

?

l ?等待發(fā)送信號量

l ?發(fā)送數(shù)據(jù)

l ?發(fā)送開始信號量

?

?

程序:

?

/************************************************************ Task2(發(fā)送任務(wù))**********************************************************/void Task2 (void *pdata){uint8 i,err;pdata = pdata;while(1){OSSemPend(Sem_SendFlag,0,&err); //等待發(fā)送信號量for(i = 0;i < 8; i++)UART0_SendByte(rcv_buf[i]); //通過輪訓(xùn)方式來發(fā)送串口數(shù)據(jù)OSSemPost(Sem_StartFlag); //發(fā)送開始信號量} }

?

?

發(fā)送數(shù)據(jù)函數(shù):

?

?

?

/*********************************************************** 名 稱: UART0_SendByte* 功 能: 向串口發(fā)送字節(jié)數(shù)據(jù),并等待發(fā)送完畢。* 入口參數(shù): data 要發(fā)送的數(shù)據(jù)* 出口參數(shù): 無**********************************************************/void UART0_SendByte(uint8 data){U0THR = data; while(0 == (U0LSR & 0x40));}

?

?

?

總結(jié)

以上是生活随笔為你收集整理的UART0串口编程(六):串口(UART0)之UC/OS(二)UC/OS下的串口接收任务编程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。