有一次做乙個東西,為了盡量不占用cpu的處理資料時間,所以就使用dma接收串列埠的資料,但是呢問題來了.,,,,,怎麼樣才能確定接收到了一條完整的資料了,,我們都知道只要開啟dma
那傢伙就不停的把接收的資料放到我們指定的地方.
只要接收到一條完整的資料我就該去處理了
關於空閒中斷,,,就是說每接收到一條完整的資料就會置位空閒標誌位,我們只需要判斷空閒標誌位是否置一,,就能知道是不是接收到了一條完整的資料
用空閒中斷的好處就是,,對於以前我寫程式通訊都會在資料的後面加上尾,,然後另乙個接收的微控制器通過判斷資料的尾來確定是不是一條完整的資料,,,有了空閒中斷就不需要在給資料加上尾了,,,,,
直接程式吧
u8 usart1_rx_cop[1024]=; //串列埠2備用接收緩衝,最大 1024 個位元組.
u8 usart1_rx_buf[1024]=; //
串列埠1接收緩衝,最大 1024 個位元組.
u16 usart1_rec_cnt = 0; //
串列埠1接收的資料個數
u16 usart1_current_cnt = 0; //
串列埠1當前接收的資料個數
u16 usart1_current_cnt = 0; //
串列埠1當前接收的資料個數
u8 usart1_at_flage = 0; //
串列埠1接收完成標誌位
u8 usart2_rx_cop[
1024]=; //
串列埠2備用接收緩衝,最大 1024 個位元組.
u8 usart2_rx_buf[1024]=; //
串列埠2接收緩衝,最大 1024 個位元組.
u16 usart2_rec_cnt = 0; //
串列埠2接收的資料個數
u16 usart2_current_cnt = 0; //
串列埠2當前接收的資料個數
u16 usart2_current_cnt = 0; //
串列埠2當前接收的資料個數
u8 usart2_at_flage = 0; //
串列埠2接收完成標誌位
u8 usart3_rx_buf[
1024]=; //
串列埠3接收緩衝,最大 1024 個位元組.
u16 usart3_rec_cnt = 0; //
串列埠3接收的資料個數
u8 usart3_at_flage = 0; //
串列埠3接收完成標誌位
u8 free_read_rst = 0;//
讀dr清除空閒中斷
voidusart123_init(uint32_t bound_1,uint32_t bound_2,uint32_t bound_3)
/*主函式迴圈裡只需要......*******************串列埠 1 中斷服務程式*********************
*/void usart1_irqhandler(void)
else
if(usart_getitstatus(usart1,usart_it_idle) ==set)//傳輸完一條完整的資料就會進入這個
}
先說一點:微控制器的串列埠可以接收任意波特率的資料,你所寫的9600意思是以這個波特率傳送....
其實昨天才發現這傢伙真的太準確了,,準確到如果碰見通訊中速率如果不是設定的波特率,就是說通訊的速率慢了不是(我上面設定的波特率是9600)1/9600(s)發過來一位資料了,低於了這個值假設是2400吧!接受到一位資料後如果1/9600(s)後沒有接收到資料,那麼這傢伙也會進空閒中斷.......因為你是設定的9600,,,,那麼在1/9600(s)後理應接收到下一位資料....而其實是在1/2400(s)後才會接收到另一位資料.....如果能把空閒中斷的檢測時間降到滿足的要求就好了....
所以嘛,,,,,自己寫個別這麼苛刻的,昨天寫好了,不過呢今天主要是把自己遇到的問題說一下
其實思路都知道
串列埠接收的時候開啟乙個定時器,並且只要接收到資料就清零乙個變數,這個變數是在定時器裡面執行自加一操作,,
如果串列埠一段時間(空閒中斷的檢測時間)不接收資料了這個變數就能自加到我們設定的數,然後關掉定時器,置位接收完成標誌位,...
直接上程式
/********************串列埠 1 中斷服務程式*********************
*/void usart1_irqhandler(void
)}
void timer_config(void)
void tim2_irqhandler(void然後昨天又寫了乙個兩個串列埠的,因為用了兩個串列埠做資料轉換(用的串列埠1和串列埠3),,,,其實其中乙個也可以用空閒中斷,,但是擔心資料傳輸過程中萬一速率有所變化,,,,,,,,完蛋啦)
if(time2_cnt>3
)//空閒時間大於約3毫秒
}
uint8_t usart1_timeflage = 0;//串列埠1空閒變數允許累加標誌
uint16_t usart1_idealtime = 0;//
串列埠1空閒累加變數
uint8_t usart3_timeflage = 0;//
串列埠3空閒變數允許累加標誌
uint16_t usart3_idealtime = 0;//
串列埠3空閒累加變數
u8 usart1_rx_cop[1024]=; //
串列埠2備用接收緩衝,最大 1024 個位元組.
u8 usart1_rx_buf[1024]=; //
串列埠1接收緩衝,最大 1024 個位元組.
u16 usart1_rec_cnt = 0; //
串列埠1接收的資料個數
u16 usart1_current_cnt = 0; //
串列埠2當前接收的資料個數
u16 usart1_current_cnt = 0; //
串列埠2當前接收的資料個數
u8 usart1_at_flage = 0; //
串列埠1接收完成標誌位
u8 usart2_rx_cop[
1024]=; //
串列埠2備用接收緩衝,最大 1024 個位元組.
u8 usart2_rx_buf[1024]=; //
串列埠2接收緩衝,最大 1024 個位元組.
u16 usart2_rec_cnt = 0; //
串列埠2接收的資料個數
u16 usart2_current_cnt = 0; //
串列埠2當前接收的資料個數
u16 usart2_current_cnt = 0; //
串列埠2當前接收的資料個數
u8 usart2_at_flage = 0; //
串列埠2接收完成標誌位
u8 usart3_rx_cop[
1024]=; //
串列埠2備用接收緩衝,最大 1024 個位元組.
u8 usart3_rx_buf[1024]=; //
串列埠2接收緩衝,最大 1024 個位元組.
u16 usart3_rec_cnt = 0; //
串列埠2接收的資料個數
u16 usart3_current_cnt = 0; //
串列埠2當前接收的資料個數
u16 usart3_current_cnt = 0; //
串列埠2當前接收的資料個數
u8 usart3_at_flage = 0; //
串列埠2接收完成標誌位
調節這個值以適應不同的接收速率
if(usart3_timeflage == 1)//
開始累加空閒變數
}if(usart3_idealtime>=100)//
調節這個值以適應不停的接收速率}}
那麼主迴圈裡---具體的處理函式,改為自己的就行
原始碼,,這個是用的板子的空閒中斷,,,,板子的其餘檔案刪掉便可,,,,
關於STM32串列埠空閒中斷的問題
1.空閒中斷是接受資料後出現乙個byte的高電平 空閒 狀態,就會觸發空閒中斷.並不是空閒就會一直中斷,準確的說應該是上公升沿 停止位 後乙個byte,如果一直是低電平是不會觸發空閒中斷的 會觸發break中斷 2.關於第二點有要鋪墊的三個情況,datasheet中 當一空閒幀被檢測到時,其處理步驟...
stm32 利用DMA 串列埠空閒中斷接受任意長資料
二 串列埠空閒中斷 三 糾正 在進行stm32開發時,有時會遇到這種情況 需要在裝置間進行資料傳輸,由於stm32串列埠rdr和tdr暫存器都是8位有效的,我們往往需要定義傳輸協議 如一幀資料中,包含包含幀頭 幀id 資料幀 校驗幀等若干8位資料 我們希望可以一次收到一幀資料,並進行解碼操作。利dm...
STM32串列埠空閒中斷idle說明
1.空閒中斷的觸發機制 空閒中斷是在監測到資料接收後 即串列埠的rxne位被置位 開始檢測,當匯流排上在乙個位元組對應的週期內未再有新的資料接收時,觸發空閒中斷idle位被硬體置1.2.idel位清零實現 檢視stm32參考手冊,要注意idel位的清零是通過先讀取usart sr,再讀取usart ...