軟件設(shè)計(jì)
代碼如下:
//初始化 IO 串口 1
//bound:波特率
void uart_init(u32 bound)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//①串口時(shí)鐘使能,GPIO 時(shí)鐘使能,復(fù)用時(shí)鐘使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|
RCC_APB2Periph_GPIOA, ENABLE); //使能 USART1,GPIOA 時(shí)鐘
//②串口復(fù)位
USART_DeInit(USART1); //復(fù)位串口 1
//③GPIO 端口模式設(shè)置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //ISART1_TX PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //USART1_RX PA.10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空輸入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化 GPIOA.10
//④串口參數(shù)初始化
USART_InitStructure.USART_BaudRate = bound; //波特率設(shè)置
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字長(zhǎng)為 8 位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //一個(gè)停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //無(wú)奇偶校驗(yàn)位
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None; //無(wú)硬件數(shù)據(jù)流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//收發(fā)模式
USART_Init(USART1, &USART_InitStructure); //初始化串口
#if EN_USART1_RX //如果使能了接收
//⑤初始化 NVIC
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ; //搶占優(yōu)先級(jí) 3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子優(yōu)先級(jí) 3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道使能
NVIC_Init(&NVIC_InitStructure); //中斷優(yōu)先級(jí)初始化
//⑤開(kāi)啟中斷
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //開(kāi)啟中斷
#endif
//⑥使能串口
USART_Cmd(USART1, ENABLE); //使能串口
}
此代碼的編寫(xiě)順序即USART的配置順序:
我們用標(biāo)號(hào)①~⑥標(biāo) 示了順序:
① 串口時(shí)鐘使能,GPIO 時(shí)鐘使能
② 串口復(fù)位
③ GPIO 端口模式設(shè)置
④ 串口參數(shù)初始化
⑤ 初始化 NVIC 并且開(kāi)啟中斷
⑥ 使能串口
配置全雙工的串口 1,那么 TX(PA9) 管腳需要配置為推挽復(fù)用輸出,RX(PA10)管腳配置為浮空輸入或者帶上拉輸入。
模式配置參考下面表格:
使用了串口的中斷接收,必須在 usart.h 里面設(shè)置 EN_USART1_RX 為 1(默認(rèn)設(shè)置就是 1 的) 。該函數(shù)才會(huì)配置中斷使能,以及開(kāi)啟串口 1 的 NVIC 中斷。這里我們把串口 1 中斷放在組 2,優(yōu)先級(jí)設(shè)置為組 2 里面的最低。
接下來(lái),根據(jù)之前講解的步驟 7,還要編寫(xiě)中斷服務(wù)函數(shù)。串口 1 的中斷服務(wù)函數(shù) USART1_IRQHandler。
USART1_IRQHandler 函數(shù)
void USART1_IRQHandler(void)函數(shù)是串口 1 的中斷響應(yīng)函數(shù),當(dāng)串口 1 發(fā)生了相應(yīng)的中斷后,就會(huì)跳到該函數(shù)執(zhí)行。中斷相應(yīng)函數(shù)的名字是不能隨便定義的,一般我們都遵循 MDK定義的函數(shù)名。這些函數(shù)名字在啟動(dòng)文件 startup_stm32f10x_hd.s 文件中可以找到。
函數(shù)體里面通過(guò)函數(shù):
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
判斷是否接受中斷,如果是串口接受中斷,則讀取串口接受到的數(shù)據(jù):
Res =USART_ReceiveData(USART1);//(USART1->DR); //讀取接收到的數(shù)據(jù)
讀到數(shù)據(jù)后接下來(lái)就對(duì)數(shù)據(jù)進(jìn)行分析。
這里我們?cè)O(shè)計(jì)了一個(gè)小小的接收協(xié)議:通過(guò)這個(gè)函數(shù),配合一個(gè)數(shù)組 USART_RX_BUF[],一個(gè)接收狀態(tài)寄存器 USART_RX_STA(此寄存器其實(shí)就是一個(gè)全局變量,由作者自行添加。由于它起到類(lèi)似寄存器的功能,這里暫且稱之為寄存器)實(shí)現(xiàn)對(duì)串口數(shù)據(jù)的接收管理。
USART_RX_BUF 的大小由 USART_REC_LEN 定義,也就是一次接收的數(shù)據(jù)最大不能超過(guò)USART_REC_LEN 個(gè)字節(jié)。USART_RX_STA 是一個(gè)接收狀態(tài)寄存器其各的定義如表 5.3.1.1 所示:
設(shè)計(jì)思路如下:
當(dāng)接收到從電腦發(fā)過(guò)來(lái)的數(shù)據(jù),把接收到的數(shù)據(jù)保存在 USART_RX_BUF 中,同時(shí)在接收狀態(tài)寄存器(USART_RX_STA)中計(jì)數(shù)接收到的有效數(shù)據(jù)個(gè)數(shù),當(dāng)收到回車(chē)(回車(chē)的表示由 2個(gè)字節(jié)組成:0X0D 和 0X0A)的第一個(gè)字節(jié) 0X0D 時(shí),計(jì)數(shù)器將不再增加,等待 0X0A 的到來(lái),而如果 0X0A 沒(méi)有來(lái)到,則認(rèn)為這次接收失敗,重新開(kāi)始下一次接收。
如果順利接收到 0X0A,則標(biāo)記 USART_RX_STA 的第 15 位,這樣完成一次接收,并等待該位被其他程序清除,從而開(kāi)始下一次的接收,而如果遲遲沒(méi)有收到 0X0D,那么在接收數(shù)據(jù)超過(guò) USART_REC_LEN 的時(shí)候,則會(huì)丟棄前面的數(shù)據(jù),重新接收。
中斷相應(yīng)函數(shù)代碼如下:
void USART1_IRQHandler(void) //串口1中斷服務(wù)程序
{
u8 Res;
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)//接收未完成
{
if(USART_RX_STA&0x4000)//接收到了0x0d
{
if(Res!=0x0a)USART_RX_STA=0;//接收錯(cuò)誤,重新開(kāi)始
else USART_RX_STA|=0x8000; //接收完成了
}
else //還沒(méi)收到0X0D
{
if(Res==0x0d)USART_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收數(shù)據(jù)錯(cuò)誤,重新開(kāi)始接收
}
}
}
}
}
main.c中的代碼
int main(void)
{
u16 t;
u16 len;
u16 times=0;
delay_init(); //延時(shí)函數(shù)初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //設(shè)置NVIC中斷分組2:2位搶占優(yōu)先級(jí),2位響應(yīng)優(yōu)先級(jí)
uart_init(115200); //串口初始化為115200
LED_Init(); //LED端口初始化
KEY_Init(); //初始化與按鍵連接的硬件接口
while(1)
{
if(USART_RX_STA&0x8000)
{
len=USART_RX_STA&0x3fff;//得到此次接收到的數(shù)據(jù)長(zhǎng)度
printf("\\r\\n您發(fā)送的消息為:\\r\\n\\r\\n");
for(t=0;t<len;t++)
{
USART_SendData(USART1, USART_RX_BUF[t]);//向串口1發(fā)送數(shù)據(jù)
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待發(fā)送結(jié)束
}
printf("\\r\\n\\r\\n");//插入換行
USART_RX_STA=0;
}else
{
times++;
if(times%5000==0)
{
printf("\\r\\n精英STM32開(kāi)發(fā)板 串口實(shí)驗(yàn)\\r\\n");
printf("正點(diǎn)原子@ALIENTEK\\r\\n\\r\\n");
}
if(times%200==0)printf("請(qǐng)輸入數(shù)據(jù),以回車(chē)鍵結(jié)束\\n");
if(times%30==0)LED0=!LED0;//閃爍LED,提示系統(tǒng)正在運(yùn)行.
delay_ms(10);
}
}
}
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2)函數(shù), 該函數(shù)是設(shè)置中斷分組號(hào)為 2,也就是 2 位搶占優(yōu)先級(jí)和 2 位子優(yōu)先級(jí)。
USART_SendData(USART1, USART_RX_BUF[t]); //向串口 1 發(fā)送數(shù)據(jù)
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
第一句,其實(shí)就是發(fā)送一個(gè)字節(jié)到串口。
第二句,就是我們?cè)谖覀儼l(fā)送一個(gè)數(shù)據(jù)到串口之后,要檢測(cè)這個(gè)數(shù)據(jù)是否已經(jīng)被發(fā)送完成了。USART_FLAG_TC 是宏定義的數(shù)據(jù)發(fā)送完成標(biāo)識(shí)符。
下載驗(yàn)證
首先打開(kāi)串口調(diào)試助手。任何一個(gè)串口調(diào)試助手都是可以的。正點(diǎn)原子中使用的是舊版本的XCOM2.0。
我們?cè)诔绦蛏?面設(shè)置了必須輸入回車(chē),串口才認(rèn)可接收到的數(shù)據(jù),所以必須在發(fā)送數(shù)據(jù)后再發(fā)送一個(gè)回車(chē)符, 這里 XCOM 提供的發(fā)送方法是通過(guò)勾選發(fā)送新行實(shí)現(xiàn)。
只要勾選了這個(gè)選項(xiàng),每次發(fā)送數(shù)據(jù)后,XCOM 都會(huì)自動(dòng)多發(fā)一個(gè)回車(chē)(0X0D+0X0A)。設(shè)置好了發(fā)送新行,我們?cè)僭诎l(fā)送區(qū)輸入你想要發(fā)送的文字,然后單擊發(fā)送,就能實(shí)現(xiàn)發(fā)送數(shù)據(jù)。
發(fā)送的數(shù)據(jù)被打印出來(lái)了,說(shuō)明實(shí)驗(yàn)成功。
-
串口通訊
+關(guān)注
關(guān)注
1文章
260瀏覽量
24931 -
通訊協(xié)議
+關(guān)注
關(guān)注
10文章
274瀏覽量
20354 -
串行通訊
+關(guān)注
關(guān)注
2文章
77瀏覽量
16376
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論