stm32 USART串口應(yīng)用不知道你會(huì)了多少(總結(jié)有用)

通用同步異步收發(fā)器(USART)提供了一種靈活的方法來(lái)與使用工業(yè)標(biāo)準(zhǔn)NR 異步串行數(shù)據(jù)格式的外部設(shè)備之間進(jìn)行全雙工數(shù)據(jù)交換脓杉。 USART利用分?jǐn)?shù)波特率發(fā)生器提供寬范圍的波特率選擇,支持同步單向通信和半雙工單線通信猛蔽。

1数焊、STM32固件庫(kù)使用外圍設(shè)備的主要思路

在STM32中蕉毯,外圍設(shè)備的配置思路比較固定檀训。首先是使能相關(guān)的時(shí)鐘王带,一方面是設(shè)備本身的時(shí)鐘砰嘁,另一方面如果設(shè)備通過(guò)IO口輸出還需要使能IO口的時(shí)鐘件炉;最后如果對(duì)應(yīng)的IO口是復(fù)用功能的IO口勘究,則還必須使能AFIO的時(shí)鐘。

其次是配置GPIO斟冕,GPIO的各種屬性由硬件手冊(cè)的AFIO一章詳細(xì)規(guī)定口糕,較為簡(jiǎn)單。

接著相關(guān)設(shè)備需要如果需要使用中斷功能磕蛇,必須先配置中斷優(yōu)先級(jí)景描,后文詳述。

然后是配置外圍設(shè)備的相關(guān)屬性秀撇,視具體設(shè)備而定超棺,如果設(shè)備需要使用中斷方式,必須使能相應(yīng)設(shè)備的中斷呵燕,之后需要使能相關(guān)設(shè)備棠绘。

最后如果設(shè)備使用了中斷功能,則還需要填寫相應(yīng)的中斷服務(wù)程序再扭,在服務(wù)程序中進(jìn)行相應(yīng)操作氧苍。

2、UART的配置步驟(查詢方式)

2.1泛范、打開時(shí)鐘

由于UART的TX和RX和AFIO都掛在APB2橋上让虐,因此采用固件庫(kù)函數(shù)RCC_APB2PeriphClockCmd()進(jìn)行初始化。UARTx需要分情況討論罢荡,如果是UART1赡突,則掛在APB2橋上,因此采用RCC_APB2PeriphClockCmd()進(jìn)行初始化区赵,其余的UART2~5均掛在APB1上惭缰。

? ? RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);

2.2、GPIO初始化

GPIO的屬性包含在結(jié)構(gòu)體GPIO_InitTypeDef惧笛,其中對(duì)于TX引腳从媚,GPIO_Mode字段設(shè)置為GPIO_Mode_AF_PP(復(fù)用推挽輸出)逞泄,GPIO_Speed切換速率設(shè)置為GPIO_Speed_50MHz患整;對(duì)于RX引腳,GPIO_Mode字段設(shè)置為GPIO_Mode_IN_FLOATING(浮空輸入)喷众,不需要設(shè)置切換速率各谚。最后通過(guò)GPIO_Init()使能IO口。

以下是GPIO設(shè)置的實(shí)例代碼:

? ? GPIO_InitTypeDef GPIO_InitStructure;

? ? //USART1 Tx(PA.09) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

? ? GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

? ? GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

? ? GPIO_Init(GPIOA, &GPIO_InitStructure);

? ? //USART1 Rx(PA.10) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

? ? GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

? ? GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

? ? GPIO_Init(GPIOA, &GPIO_InitStructure);

2.3到千、配置UART相關(guān)屬性

通過(guò)結(jié)構(gòu)體USART_InitTypeDef來(lái)確定昌渤。UART模式下的字段如下

USART_BaudRate:波特率,視具體設(shè)備而定

USART_WordLength:字長(zhǎng)

USART_StopBits:停止位

USART_Parity:校驗(yàn)方式

USART_HardwareFlowControl:硬件流控制

USART_Mode:?jiǎn)?雙工

最后設(shè)置憔四。實(shí)例代碼為:

//USART1配置

USART_InitTypeDef USART_InitStructure;

USART_InitStructure.USART_BaudRate =9600;

? ? USART_InitStructure.USART_WordLength = USART_WordLength_8b;

? ? USART_InitStructure.USART_StopBits = USART_StopBits_1;

? ? USART_InitStructure.USART_Parity = USART_Parity_No;

? ? USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

? ? USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;

? ? USART_Init(USART1, &USART_InitStructure);

? ? USART_Cmd(USART1, ENABLE);

別忘了最后要使用USART_Cmd()來(lái)啟動(dòng)設(shè)備UART1膀息。

2.4般眉、重定向print()函數(shù)。

intfputc(intch,FILE *f)

{

? ? USART1->SR;//USART_GetFlagStatus(USART1, USART_FLAG_TC) 解決第一個(gè)字符發(fā)送失敗的問(wèn)題

? ? //一個(gè)一個(gè)發(fā)送字符USART_SendData(USART1, (unsignedchar) ch);

? ? //等待發(fā)送完成while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);


? ? return(ch);

}

最后通過(guò)主函數(shù)直接輸出即可潜支。

intmain(void)

{

? ? // USART1 config 9600 8-N-1? ? USART1_Config();


? ? printf("hello world!");

}

3甸赃、UART的配置步驟(中斷方式)

打開時(shí)鐘、GPIO初始化冗酿、配置UART相關(guān)屬性埠对、重定向print()函數(shù) 與上面的相同。

3.1裁替、中斷優(yōu)先級(jí)的配置

這是STM32比較奇怪的地方项玛,在只有一個(gè)中斷的情況下,仍然需要配置優(yōu)先級(jí)弱判,其作用是使能某條中斷的觸發(fā)通道襟沮。STM32的中斷有至多兩個(gè)層次,分別是先占優(yōu)先級(jí)和從優(yōu)先級(jí)昌腰,而整個(gè)優(yōu)先級(jí)設(shè)置參數(shù)的長(zhǎng)度為4位臣嚣,因此需要首先劃分先占優(yōu)先級(jí)位數(shù)和從優(yōu)先級(jí)位數(shù),通過(guò)NVIC_PriorityGroupConfig()實(shí)現(xiàn)剥哑;

特定設(shè)備的中斷優(yōu)先級(jí)NVIC的屬性包含在結(jié)構(gòu)體NVIC_InitTypeDef中硅则,其中字段NVIC_IRQChannel包含了設(shè)備的中斷向量,保存在啟動(dòng)代碼中株婴;字段NVIC_IRQChannelPreemptionPriority為主優(yōu)先級(jí)怎虫,NVIC_IRQChannelSubPriority為從優(yōu)先級(jí),取值的范圍應(yīng)根據(jù)位數(shù)劃分的情況而定困介;最后NVIC_IRQChannelCmd字段是是否使能大审,一般定位ENABLE。最后通過(guò)NVIC_Init()來(lái)使能這一中斷向量座哩。實(shí)例代碼如下:

//配置UART1接收中斷voidNVIC_Configuration(void)

{

? ? NVIC_InitTypeDef NVIC_InitStructure;

? ? /* Configure the NVIC Preemption Priority Bits */?

? ? NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);


? ? /* Enable the USARTy Interrupt */? ? NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;? ?

? ? NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =0;

? ? NVIC_InitStructure.NVIC_IRQChannelSubPriority =1;

? ? NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

? ? NVIC_Init(&NVIC_InitStructure);

}


3.2徒扶、中斷的服務(wù)程序的設(shè)計(jì)

目前使用了UART的兩個(gè)中斷USART_IT_RXNE(接收緩存補(bǔ)空中斷)和USART_IT_TXE(發(fā)送緩存空中斷),前一個(gè)中斷保證了一旦有數(shù)據(jù)接收到就進(jìn)入中斷以接收特定長(zhǎng)度的數(shù)據(jù)根穷,后一個(gè)中斷表示一旦發(fā)完一個(gè)數(shù)據(jù)就進(jìn)入中斷函數(shù)姜骡,保證連續(xù)發(fā)送一段數(shù)據(jù)。一個(gè)設(shè)備的所有中斷都包含在一個(gè)中斷服務(wù)程序中屿良,因此必須首先分清楚這次響應(yīng)的是哪一個(gè)中斷圈澈,使用USART_GetITStatus()函數(shù)確定;采用USART_ReceiveData()函數(shù)接收一個(gè)字節(jié)數(shù)據(jù)尘惧,采用USART_SendData()函數(shù)發(fā)送一個(gè)字節(jié)數(shù)據(jù)康栈,當(dāng)關(guān)閉中斷時(shí)采用USART_ITConfig()失能響應(yīng)的中斷。實(shí)例程序:

voidUSART1_IRQHandler(void)

{

? ? uint8_t ch;


? ? if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)

? ? {? ?

? ? ? ? //ch = USART1->DR;ch = USART_ReceiveData(USART1);//接受數(shù)據(jù)printf("%c", ch );//返回打印? ? }


}


3.3、接收數(shù)據(jù)函數(shù):

//重定向scanf函數(shù)到USART1intfgetc(FILE *f)

{

? ? ? ? /*等待串口1輸入數(shù)據(jù)*/while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);

? ? ? ? return(int)USART_ReceiveData(USART1);

}

4啥么、?STM32串口在首次發(fā)送字符的時(shí)候登舞,首字符丟失解決辦法

網(wǎng)上關(guān)于發(fā)送字符的代碼大多如下:

USART_SendData(USART1,?(uint8_t)ch);

while(?USART_GetFlagStatus(USART1,?USART_FLAG_TC)?!=?SET);

其實(shí)咋一看是說(shuō)的通的,但是在仔細(xì)看手冊(cè)的時(shí)候發(fā)現(xiàn)?TC?和?TXE?標(biāo)志位在復(fù)位的時(shí)候被置1?悬荣,這樣第一次while循環(huán)就是沒(méi)有用的逊躁。這樣導(dǎo)致了首次第一個(gè)字符還沒(méi)有被輸出,就被后面的字符覆蓋掉隅熙,造成實(shí)際看到的丟失現(xiàn)象稽煤。解決辦法就很簡(jiǎn)單:在前面加上一句?USART1->SR;

具體代碼如下:

USART1->SR;

USART_SendData(USART1,?(uint8_t)ch);

while(?USART_GetFlagStatus(USART1,?USART_FLAG_TC)?!=?SET);

下面我來(lái)說(shuō)說(shuō)原因:?第一句讀取SR寄存器,第二句寫DR寄存器?剛好清除了TC標(biāo)志位?囚戚。第一次while循環(huán)就起作用了酵熙。

也可將USART1->SR;替換為USART_GetFlagStatus(USART1,?USART_FLAG_TC)


本實(shí)驗(yàn)所有程序可參考:? ?http://www.makeru.com.cn/live/1392_1164.html?s=45051


補(bǔ)充:一直有一個(gè)疑問(wèn)是關(guān)于接受和發(fā)送數(shù)據(jù)的問(wèn)題:對(duì)于“hello”這樣的字符串是一個(gè)一個(gè)接受還是整個(gè)接受顯示,下面的實(shí)驗(yàn)可以驗(yàn)證是一個(gè)一個(gè)進(jìn)行的驰坊。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末匾二,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子拳芙,更是在濱河造成了極大的恐慌察藐,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舟扎,死亡現(xiàn)場(chǎng)離奇詭異分飞,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)睹限,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門譬猫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人羡疗,你說(shuō)我怎么就攤上這事染服。” “怎么了叨恨?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵柳刮,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我痒钝,道長(zhǎng)秉颗,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任午乓,我火速辦了婚禮站宗,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘益愈。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布蒸其。 她就那樣靜靜地躺著敏释,像睡著了一般。 火紅的嫁衣襯著肌膚如雪摸袁。 梳的紋絲不亂的頭發(fā)上钥顽,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音靠汁,去河邊找鬼蜂大。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蝶怔,可吹牛的內(nèi)容都是我干的奶浦。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼踢星,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼澳叉!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起沐悦,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤成洗,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后藏否,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瓶殃,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年副签,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了碌燕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡继薛,死狀恐怖修壕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情遏考,我是刑警寧澤慈鸠,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站灌具,受9級(jí)特大地震影響青团,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜咖楣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一督笆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧诱贿,春花似錦娃肿、人聲如沸咕缎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)凭豪。三九已至,卻和暖如春晒杈,著一層夾襖步出監(jiān)牢的瞬間嫂伞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工拯钻, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留帖努,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓粪般,卻偏偏與公主長(zhǎng)得像拼余,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子刊驴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348