起初
stm32 v3.5 庫函數里面,對于串口USART有這樣兩個函數:
USART_ClearFlag()和USART_ClearITPendingBit()
查庫函數定義,說一個是清除標志,一個是清除中斷預處理位。然后我看了stm32f10x_usart.c文件,發現兩個函數都操作的是USART->SR寄存器,但是這個寄存器只有一組標志位,沒有什么中斷預處理位。。
實際上兩個函數實現的功能是一樣的,都是清除相對應的標志位,只是標志位和中斷位含義不一樣,是標志位但
是不一定會產生中斷。例如:
#define USART_IT_TXE ((uint16_t)0x0727)
#define USART_IT_TC ((uint16_t)0x0626)
#define USART_IT_RXNE ((uint16_t)0x0525)
這是中斷位,可以產生中斷
#define USART_FLAG_TXE ((uint16_t)0x0080)
#define USART_FLAG_TC ((uint16_t)0x0040)
#define USART_FLAG_RXNE ((uint16_t)0x0020)
這是標志位,有的標志位不能產生中斷
標志位在程序中可以作為判定條件,支持程序的運行,中斷則是跳轉到中斷函數執行。兩個函數實現的功能是一
樣的,在中斷程序中可以用兩個中的任一個。我想區分兩個函數是為了更清晰吧。
還有
#define USART_IT_TC ((uint16_t)0x0626)
#define USART_FLAG_TC ((uint16_t)0x0040)
這兩個數值不同是因為標志位只是為了清除標志位而設的,而中斷位設置成這個值是因為在其他函數中這一位還
有其他用途。而且還要注意:
void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_CLEAR_FLAG(USART_FLAG));
assert_param(IS_USART_PERIPH_FLAG(USARTx, USART_FLAG)); /* The CTS flag is not available for UART4 and UART5 */
USARTx->SR = (uint16_t)~USART_FLAG;
}
這一步 USARTx->SR = (uint16_t)~USART_FLAG; 似乎應該是 USARTx->SR &= (uint16_t)~USART_FLAG;
其實狀態位只能有硬件置位,軟件只能讀和清零,所以這樣寫也是正確的。
沒有很明白,所以轉在這里,等我哪天靈光乍現了,再來加上我的理解
上面的內容是別人的,我略作修改,下面的內容是我原創。不知道本文到底是屬于原創還是轉載,但是......我的更簡潔、精辟
-----------------------------------------------------------------------------------------------------------------------
靈光乍現了
我是在使用TC的時候遇見這個問題的,所以這里就只分析TC這個位
先研究簡單點的USART_ClearFlag函數
//調用形式
USART_ClearFlag(USART3,USART_FLAG_TC);
//USART_FLAG_TC的定義
#define USART_FLAG_TC ((uint16_t)0x0040)
//USART_ClearFlag函數的原型
void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_CLEAR_FLAG(USART_FLAG));
assert_param(IS_USART_PERIPH_FLAG(USARTx, USART_FLAG)); /* The CTS flag is not available for UART4 and UART5 */
USARTx->SR = (uint16_t)~USART_FLAG;
}
一目了然,最后USARTx->SR = ~(0100'0000);
再來研究復雜點的USART_ClearITPendingBit函數(注意,這兩個函數的第二個參數,是不一樣的)
//調用形式
USART_ClearITPendingBit(USART3,USART_IT_TC);
//USART_IT_TC的定義
#define USART_IT_TC ((uint16_t)0x0626)//=0000'0110'0010'0110
//USART_ClearITPendingBit的函數原型
void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT)
{
uint16_t bitpos = 0x00, itmask = 0x00;
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_CLEAR_IT(USART_IT));
assert_param(IS_USART_PERIPH_IT(USARTx, USART_IT)); /* The CTS interrupt is not available for UART4 and UART5 */
bitpos = USART_IT >> 0x08; //=0000'0110
itmask = (uint16_t)((uint16_t)0x01 << bitpos); //=0100'0000
USARTx->SR = (uint16_t)~itmask; //=~(0100'0000)
}
可以看到最后還是USARTx->SR=~(0100'0000);
對比一下USART_ClearFlag和USART_ClearITPendingBit的參數
USART_ClearFlag的參數 USART_ClearITPendingBit的參數
USART_FLAG_CTS = 0x0200 USART_IT_CTS = 0x096A
USART_FLAG_LBD = 0x0100 USART_IT_LBD = 0x0846
USART_FLAG_TC = 0x0040 USART_IT_TC = 0x0626
USART_FLAG_RXNE = 0x0020 USART_IT_RXNE = 0x0525
這里可以發現一個規律USART_ClearFlag參數只有一個位是“1”,其位置正好等于USART_ClearITPendingBit的參數左移八位后的結果,所以這里可以非常非常肯定的講:函數USART_ClearFlag和函數USART_ClearITPendingBit的功能totally一樣
----------------------------------------------------------------------------------------------------------------------------
涉及內容擴展:
STM32的USART發送數據時如何使用TXE和TC標志
在USART的發送端有2個寄存器,一個是程序可以看到的寄存器——發送數據寄存器(通過USART_DR查看),另一個是程序看不到的寄存器——發送移位寄存器,對應的有兩個USART數據發送標志,一個是TXE=發送數據寄存器空,另一個是TC=發送移位寄存器空。
(這粗箭頭和這細箭頭,簡直不要太形象哦,粗箭頭是八位八位的傳,細箭頭是一位一位的傳)
當USART_DR中的數據傳送到移位寄存器后,TXE被設置,此時移位寄存器開始向TX信號線按位傳輸數據,但因為TDR已經變空,所以程序可以把下一個要發送的字節(操作USART_DR)寫入TDR中,而不必等到移位寄存器中所有位發送結束,所有位發送結束時(送出停止位后)硬件會設置TC標志。
另一方面,在剛剛初始化好USART還沒有發送任何數據時,也會有TXE標志,因為這時發送數據寄存器是空的。TXEIE和TCIE的意義很簡單,TXEIE允許在TXE標志為'1'時產生中斷,而TCIE允許在TC標志為'1'時產生中斷。
至于什么時候使用哪個標志,需要根據你的需要自己決定。但我認為TXE允許程序有更充裕的時間填寫TDR寄存器,保證發送的數據流不間斷。TC可以讓程序知道發送結束的確切時間,有利于程序控制外部數據流的時序。
三種發送方法
1、不開發送完成中斷:
/*******************************************************************************
* 函數名 : UART1_SendString
* 描述 : USART1發送字符串
* 輸入 : *s字符串指針
* 注釋 :0==RESET,表示發送還未完成
USART_FLAG_TC!=RESET,就是=SET,表示發送完成,此時執行USART_GetFlagStatus會把USART_FLAG_TC清零(未證實)
*******************************************************************************/
void UART1_SendString(u8* s)
{
while(*s)//檢測字符串結束符
{
//USART_FLAG_TC==RESET時,表示發送還未完成。
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
USART_SendData(USART1 ,*s++);//發送當前字符
}
}
2、開中斷,額外設置一個標志:
u8 FLAG_TC=0;//定義全局變量
/*******************************************************************************
* 函數名 : UART1_SendString
* 描述 : USART1發送字符串
* 輸入 : *s字符串指針
*******************************************************************************/
void UART1_SendString(char* s)
{
FLAG_TC=0;//提前準備一下
while(*s)//檢測字符串結束符
{
USART_SendData(USART1 ,*s++);//發送當前字符
while( FLAG_TC==0); //0:發送還未完成;1:發送完成
FLAG_TC=0;
}
}
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_TC) != RESET)//發送完成中斷,= SET
{
USART_ClearITPendingBit(USART1,USART_IT_TC);
FLAG_TC=1;
}
}
開中斷時,就不能通過簡單的判斷標志位USART_FLAG_TC的狀態去決定能否發送下一個字符。比方說,使用
while(*s)
{
USART_SendData(USART1 ,*s++);//發送字符
while(USART_GetFlagStatus(USART1, USART_FLAG_TC)==RESET);
...
}
執行完發送字符的語句后,因為不可能這么快完成發送,所以程序接下來執行的是while語句。在等待期間,字符發送完畢,這時就會進入到中斷,如果在中斷里清除標志位,退出中斷后,標志位USART_FLAG_TC仍然是RESET;如果不在中斷里清除標志位,就不能退出中斷。所以程序就會死在while里。
所以這里就需要額外設置一個標志。
3、開中斷,數據發送由函數啟動,在中斷里完成:
//定義全局變量。也可以為了簡化,把這四個參數結合起來包含在一個結構體里
u8 TxLength; //發送數據長度
u8 TxIndicator;//發送指示器,表示目前發送完成哪一位了,下面要發送的是第(TxIndicator+1)位
u8 TxBuff[256];//Data
u8 TxFnd; //發送完成標志
/*************************************************************************
*程序名稱 : SendFirstByte
*功能 : 啟動發送第一個字節
*@Notes : 雞賊啊,剩下的都放在USART_FLAG_TC中斷里面,因為這個中斷是
發送完成中斷,是利用“發送第一個字節”來“啟動發送”
*@Notes : 需要注意,如果發送結果是亂碼的話,一種供參考的解決方案是
把數據直接賦值給TxBuff,而不要通過函數的形參傳遞
*輸入參數 : u8 txbuf[]: 需要發送的數據,u8 len : 數據中的字節數
*返回值 : 無
*************************************************************************/
void SendFirstByte( u8 txbuf[], u8 len )
{
TxBuff = txbuf;//需要發送的數據
TxLength = len ;//發送數據長度
TxIndicator = 1 ;//0已經發送,也是用來啟動發送的
USART_SendData(USART1, txbuf[0]); /**@Notes:只發送了txbuf的第一個字節*/
}
/*************************************************************************
*程序名稱 : USART1_IRQHandler
*功能 : 完成發送數據
*************************************************************************/
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_TC) != RESET)
{
USART_ClearITPendingBit(USART1,USART_IT_TC);
if( TxIndicator < TxLength )//數組的索引max永遠小于數組元素的個數
{
USART_SendData(USART1, TxBuff[TxIndicator++]);
}
else//最后一字節數據發送完成
{
TxFnd = 0;
TxIndicator = 0;
}
}
}
USART收發過程中常遇問題總結:
Q:為什么使用USART發送一串字符,最后自接收到了最后一個?
A:是因為發送的間隔太短了,可以在發送每個字符之前先判斷一下上一個字符是否發送完成,可以參考上面的“三種發送方法”
Q:為什么使用USART發送一串字符,有時候接收不到第一個字符,有時候又可以接收得到?
A:解決方案是把判斷能否發送的語句放在發送數據之前
上一篇:stm32串口的flag和it標志位
下一篇:STM32F1x系列——外部中斷
推薦閱讀
史海拾趣
隨著LED技術的興起,CML敏銳地捕捉到了這一趨勢,并成為第一家引進LED燈具的公司。這一決策為公司帶來了巨大的發展機遇。CML不斷投入研發資源,推出了一系列具有創新性的LED產品,不僅提高了照明效率,還降低了能耗。這使得CML在微型照明領域逐漸取得了領先地位,并贏得了廣泛的客戶基礎。
隨著LED技術的興起,CML敏銳地捕捉到了這一趨勢,并成為第一家引進LED燈具的公司。這一決策為公司帶來了巨大的發展機遇。CML不斷投入研發資源,推出了一系列具有創新性的LED產品,不僅提高了照明效率,還降低了能耗。這使得CML在微型照明領域逐漸取得了領先地位,并贏得了廣泛的客戶基礎。
在發展過程中,CML始終注重產品質量和品牌建設。公司建立了嚴格的質量管理體系,從原材料采購到生產流程再到產品出廠,都進行嚴格的質量控制。這使得CML的產品在市場上享有良好的聲譽,并贏得了客戶的信任。同時,公司還積極參與各種行業展會和交流活動,提升品牌知名度和影響力。
近年來,“General Microcircuits”積極響應全球綠色可持續發展的號召,將環保理念融入產品研發和生產的全過程。公司投入大量資源研發低能耗、高能效的綠色半導體產品,并致力于推動循環經濟在半導體產業的應用。同時,公司還加強了與環保組織的合作,共同推動半導體行業的綠色轉型和可持續發展。這些努力不僅為公司贏得了良好的社會聲譽,也為公司的長遠發展奠定了堅實的基礎。
請注意,以上故事均基于電子行業的一般發展規律和創新實踐構想而成,并非針對具體公司“General Microcircuits Corp”的實際情況。在實際情況中,不同公司的發展路徑和故事可能有所不同。
“未來電子”深知人才是企業發展的第一資源。因此,公司高度重視人才培養和團隊建設工作。通過建立完善的培訓體系、激勵機制和晉升通道,公司吸引并留住了一大批優秀的研發、生產和銷售人才。這些人才在各自的崗位上發揮出色,為公司的快速發展提供了有力保障。同時,“未來電子”還注重團隊合作和跨部門協作,通過組織豐富多彩的團隊建設活動,增強了員工的歸屬感和凝聚力。
隨著全球化進程的加速,“未來電子”意識到單一市場已無法滿足公司的長遠發展需求。于是,公司制定了全球化戰略,通過設立海外研發中心、生產基地和銷售網絡,積極拓展國際市場。在歐洲、北美和亞洲等地,“未來電子”的產品和服務得到了廣泛認可,市場份額逐年攀升。這一戰略不僅提升了公司的國際影響力,還為公司的持續增長提供了強勁動力。
目前采用telechips的8900,板子上有一個1.1的HOST和2.0的OTG,目前需要做一個需求,就是當u盤插入的時候,能夠識別出插入的是1.1的端口還是2.0的,telechips大部分代碼提供的是靜態庫, 目前有什么方法可以實現?把usb的控制器值打印了一部分出來, ...… 查看全部問答∨ |
準備在PDA上開發一個簡單的程序,不打算自己定制wince SDK,看見參考書上的有微軟提供的Pocket PC 2003,打算用這個,但是上了微軟的網站,沒有找到,書是2006版,可能變化太快了,只找到了一個pda SDK 1.1,本人是新手,誰能解釋一下, ...… 查看全部問答∨ |
IDE 中LED 跑馬燈的程序運行時總是出現 nios2-terminal: connected to hardware target using JTAG UART on cable nios2-terminal: "USB-Blaster [USB-0]", device 1, instance 0 nios2-terminal: (Use the IDE stop button or Ctrl-C to te ...… 查看全部問答∨ |
本人菜鳥,剛接觸vxworks,在vxworks下進行2路串口通信 使用tty0,tty1等方式open 并調用read函數讀取串口數據 現在不知道何時串口收到數據,所以調用read函數一直停在那,請問如何讀取串口數據可以避免死循環?(由于限制,不考慮單獨起任務讀 ...… 查看全部問答∨ |
拜問下 大蝦們 SPI1 和 SPI2 都設定為雙線雙工 , SPI1 主 SPI2 從 在 通訊的時候 SPI1 向 SPI2 發送數據 SPI2 能接收 但是&nbs ...… 查看全部問答∨ |
給客戶做了6個樣板,用STVP燒錄了軟件,選擇了READONLY保護選項。 前幾天客戶把6個板子送過來要修改。結果發現有4塊板子是正常,但是有2塊板子的讀保護沒有了,代碼通過STVP輕松讀出來了。 真暈啦。這樣的問題竟讓讓我遇到… 查看全部問答∨ |
replyreload += \',\' + 1110631;STM32的IAP方案 幾乎所有的同類書籍都介紹綜合性的應用示例如“萬年歷 + 溫度顯示 + 鬧鐘響鈴 + 計時表”這樣的一個實時時鐘范例或“STM32 + 音頻解碼 + 大容 ...… 查看全部問答∨ |
|
本帖最后由 dontium 于 2015-1-23 13:13 編輯 LED應用手冊 1 線控制 – 省去 LED 驅動器的微處理器控制 AN033 -- 將射頻閃光 LED 軟件示例轉換為 CC2420 - MSP430(修訂版 A) 超實用的,快來看啊~~~ … 查看全部問答∨ |
本人由于項目需求,需要在求含有比較多諧波的數字正弦波信號的有效值。目前我想到的方式,采集信號進行高次諧波過濾,求基波的平均值,然后求有效。在FPGA中實現,占用的資源比較多,特別是采集信號的路數較多的情況下。請教各位大蝦,在FPGA中求有 ...… 查看全部問答∨ |
設計資源 培訓 開發板 精華推薦
- 直播:TI SimpleLink MCU無線平臺及軟件介紹!豐富的提問禮在這里等你~
- 參加RT-Thread軟件包賽,贏取RoboMaster等豐厚獎品!
- 一天一個Webench設計,看誰能撐30天?
- 有獎直播:TI毫米波雷達在汽車車內的應用
- TI C2000精品課暑期伴你行 學習好禮送不停
- 有獎活動 | 英飛凌新品情報站:最新 5V XENSIVTM PAS CO2 傳感器 知識挑戰賽
- 直播:TI及安富利帶你快速通過新能源汽車安全系統認證 預報名、看直播贏好禮!
- NXP微控制器電路板,針對USB Type C接口設計,評測創意有獎征集,曬心得更有多重好禮!
- 年末芯幣競價最后一期——RIGOL 數字示波器