缺點(diǎn):有些情況下會導(dǎo)致數(shù)據(jù)丟失(可能返回數(shù)據(jù)中0x0d、0a本身為有效數(shù)據(jù))
	適用:約定協(xié)議的數(shù)據(jù)幀(發(fā)送數(shù)據(jù)的設(shè)備必須以相應(yīng)的約定字節(jié)作為一次數(shù)據(jù)結(jié)束)
void USART1_IRQHandler(void)                	//串口中斷服務(wù)程序(函數(shù))
	{
	u8 Res;	//定義Res,用于Res =USART_ReceiveData(USART1);中存儲串口1發(fā)送的數(shù)據(jù)(這里的數(shù)據(jù)按位發(fā)送)
#if SYSTEM_SUPPORT_OS  //如果SYSTEM_SUPPORT_OS為真,則需要支持OS		
	OSIntEnter();    
#endif
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中斷(接收到的數(shù)據(jù)必須是0x0d 0x0a結(jié)尾)
		{
		Res =USART_ReceiveData(USART1);	//讀取接收到的數(shù)據(jù)
		
		if((USART_RX_STA&0x8000)==0)//接收未完成    1000 0000 0000 0000
//判斷USART_RX_STA的第一位是否為0,這時因為USART_RX_STA的初始值為0,所以我們進(jìn)入if(USART_RX_STA&0x4000)。
			{
			if(USART_RX_STA&0x4000)//接收到了0x0d	0100 0000 0000 0000
//判斷USART_RX_STA的第二位是否為1,所以我們進(jìn)入else //還沒收到0X0D。
				{
				if(Res!=0x0a)USART_RX_STA=0;//接收錯誤,重新開始
				else USART_RX_STA|=0x8000;	//接收完成了 
				}
			else //還沒收到0X0D
				{	
				if(Res==0x0d)USART_RX_STA|=0x4000;//再次判斷這次接收到的是不是0x0d,判斷了Res是否0x0d, 即Res是否為回車,這里如果串口有輸入數(shù)據(jù)的話明顯可以判斷的,所以我們進(jìn)入下面的else.
				else
					{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;  // 0011 1111 1111 1111
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收數(shù)據(jù)錯誤,重新開始接收	  
					}		 
				}
			}   		 
     } 
#if SYSTEM_SUPPORT_OS 	
	OSIntExit();  											 
#endif
}
	OSIntEnter()和OSIntExit()兩者必須成對出現(xiàn)。
	進(jìn)入中斷時調(diào)用OSIntEnter(),退出中斷時調(diào)用OSIntExit()。
	OSIntEnter 是進(jìn)?中斷服務(wù)函數(shù),?來記錄中斷嵌套層數(shù)(OSIntNesting增加 1);
	OSIntEnter()應(yīng)該在中斷關(guān)閉后調(diào)用,所以函數(shù)里面沒有使用OS_ENTER_CRITICAL() and OS_EXIT_CRITICAL(),如此在調(diào)用OSIntEnter()前需關(guān)閉中斷。
	OSIntExit():所有中斷結(jié)束后進(jìn)行任務(wù)調(diào)度,使系統(tǒng)更加實時。
	OSIntExit 是退出中斷服務(wù)函數(shù),該函數(shù)可能觸發(fā)?次任務(wù)切換(當(dāng) OSIntNesting==0&&調(diào)度器未上鎖&&就緒表最?優(yōu)先級任務(wù) != 被中斷的任務(wù)優(yōu)先級時),否則繼續(xù)返回原來的任務(wù)執(zhí)?代碼(如果 OSIntNesting 不為 0,則減 1)。
	OS_Sched():uCOS進(jìn)行任務(wù)調(diào)度,不在中斷調(diào)用。
	OSIntNesting:統(tǒng)計中斷嵌套數(shù),最多255。在OSIntExit()和OS_Sched()中都有判別。
	OS_ENTER_CRITICAL():保存中斷狀態(tài),關(guān)中斷。uCOS將無法再執(zhí)行任務(wù)調(diào)度,硬件中斷也被屏蔽。
void  OSIntEnter (void)
{
if (OSRunning == OS_TRUE) {
if (OSIntNesting < 255u) {
OSIntNesting++;                      /* Increment ISR nesting level                        */
}
}
}
這個函數(shù)的作用是對全局變量OSIntNesting增1,OSIntNesting為中斷嵌套深度。
void  OSIntExit (void)
{
#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
OS_CPU_SR  cpu_sr = 0u;
#endif
if (OSRunning == OS_TRUE) {
OS_ENTER_CRITICAL();
if (OSIntNesting > 0u) {                           /* Prevent OSIntNesting from wrapping       */
OSIntNesting--;
}
if (OSIntNesting == 0u) {                          /* Reschedule only if all ISRs complete ... */
if (OSLockNesting == 0u) {                     /* ... and not locked.                      */
OS_SchedNew();
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
if (OSPrioHighRdy != OSPrioCur) {          /* No Ctx Sw if current task is highest rdy */
#if OS_TASK_PROFILE_EN > 0u
OSTCBHighRdy->OSTCBCtxSwCtr++;         /* Inc. # of context switches to this task  */
#endif
OSCtxSwCtr++;                          /* Keep track of the number of ctx switches */
OSIntCtxSw();                          /* Perform interrupt level ctx switch       */
}
}
}
OS_EXIT_CRITICAL();
}
}
函數(shù)的前面部分對OSIntNesting減1,剛好與OSIntEnter() 相對應(yīng);后面部分則進(jìn)行任務(wù)調(diào)度。
總結(jié):任何中斷服務(wù)函數(shù),我們都應(yīng)該加上 OSIntEnter 和 OSIntExit 函數(shù),UCOSII 是?個可剝奪型的內(nèi)核,中斷服務(wù)?程序運(yùn)?之后,系統(tǒng)會根據(jù)情況進(jìn)??次任務(wù)調(diào)度去運(yùn)?優(yōu)先級別最?的就緒任務(wù),?并不?定接著運(yùn)?被中斷的任務(wù)!
#if...#endif是C++中的條件編譯預(yù)處理命令 有兩種格式:
1:#ifdef 標(biāo)示符
程序段1
#else
程序段2
#endif
表示:如果標(biāo)示符已經(jīng)被#define命令定義過,則編譯程序段1,否則編譯程序段2。期中else部分可以沒有。
2:#if 表達(dá)式
程序段1
#else
程序段2
#endif
	表示:如果表達(dá)式為真,則編譯程序段1,否則編譯程序段2.
	if((USART_RX_STA&0x8000)==0) //0x8000,即二進(jìn)制1000 0000 0000 0000,與變量USART_RX_STA,按位與(&),并與0比較,作用是判斷USART_RX_STA數(shù)值第16位是否為0。
	USART_RX_STA&0x8000有兩種可能:
	第一種1××× ×××× ×××× ××××&1000 0000 0000 0000=1000 0000 0000 0000
	第二種0××× ×××× ×××× ××××&1000 0000 0000 0000=0000 0000 0000 0000
	由此可以判斷USART_RX_STA第16位是否為0
	
	USART_RX_STA的作用,USART_RX_STA一共有16位,前兩位為標(biāo)記位,后14位記錄了串口發(fā)送的數(shù)的位數(shù)。第一位標(biāo)記位標(biāo)記了Res是否為0x0a,第二位標(biāo)記位標(biāo)記了Res是否為0x0d。
	知識點(diǎn):0x0d是回車的ASCLL碼,0x0a是換行的ASCLL碼
	USART_RX_BUF這個是用來保存接收到的數(shù)據(jù)的可以看到每次結(jié)束判斷會有
	USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
	USART_RX_STA=0; //接收狀態(tài)標(biāo)記
	USART_RX_STA的作用就是在全部函數(shù)之間實現(xiàn)一個消息傳遞,自己設(shè)置,自己管理,自己識別。
	bit15   bit14  bit13~0
	接收完成標(biāo)志0x0a 接收到0X0d標(biāo)志 接收到的有效數(shù)據(jù)個數(shù)
	USART_RX_STA|=0x4000;將第二位狀態(tài)標(biāo)志位置為1;在倒數(shù)第1次循環(huán)中使用USART_RX_STA|=0x8000;將第一位狀態(tài)標(biāo)志位也置為1,;而后串口數(shù)據(jù)接收結(jié)束,所有從串口接收的數(shù)據(jù)保存在USART_RX_BUF[ ]數(shù)組中,串口所發(fā)送的數(shù)據(jù)長度保存在USART_RX_STA的后14位中。
	審核編輯:湯梓紅
- 
                                STM32
                                +關(guān)注
關(guān)注
2302文章
11107瀏覽量
370250 - 
                                串口
                                +關(guān)注
關(guān)注
15文章
1603瀏覽量
81653 
發(fā)布評論請先 登錄
Labview讀取二進(jìn)制文件(有的時候會自動添加0X0D到0x0A前面)
stm32串口怎么用DMA接收不定長數(shù)據(jù)?
串口接收,0x0a和0x0d表示的什么?
stm32識別TC35短信有兩個“0x0d 0x0a”怎么解決?
Labview串口時候數(shù)據(jù)中的0x0A與換行符沖突怎么解決?
針對接收一幀含有多個字節(jié)的不定長數(shù)據(jù)接收方式進(jìn)行討論
STM32串口接收不定長數(shù)據(jù)的程序免費(fèi)下載
    
STM32串口通信 (采用鏈表接收不定長數(shù)據(jù)幀)
    
STM32串口接收不定長數(shù)據(jù)的幾種方法
    
stm32 串口接收不定長度數(shù)據(jù)及黏包處理 + 串口DMA接收
    
RM0451_超低功耗 STM32L0x0 先進(jìn)的基于 Arm? 的 32 位 MCU
    
          
        
        
STM32串口接收不定長數(shù)據(jù):采用標(biāo)志位(比如0X0D,0X0A)結(jié)束法
                
 
           
            
            
                
            
評論