STM32f103zet6 串口數(shù)基本配置及詳細(xì)說明:
玩stm32也有一段時(shí)間了,對(duì)串口中斷接受和DAM方式發(fā)送總一下總結(jié),但是本節(jié)只講述串口中斷接受的基本配置,既然是基本就說明他很重要,如有疏忽,就會(huì)讓串口失靈。下一節(jié)主要講述DAM的用法。言歸正傳:首先我們要知道開啟一個(gè)功能的步驟如下,
?。?)RCC配置
?。?)GPIO配置
(3)USART配置
?。?)發(fā)送/接收數(shù)據(jù)
在RCC配置中,我們除了常規(guī)的時(shí)鐘設(shè)置之外,需要打開USART相應(yīng)的IO口時(shí)鐘,USART時(shí)鐘,還有管腳功能復(fù)用時(shí)鐘。
1、在GPIO配置中,將發(fā)送端的管腳配置為復(fù)用推挽輸出,講接受端的管腳設(shè)置為浮空輸入。注意紅色標(biāo)記,這兩種模式很重要,注意其區(qū)別。
2、在USART的配置中,通過USART_InitTypeDdf結(jié)構(gòu)體對(duì)USART進(jìn)行初始化操作。如用中斷方式:在USART配置中要打開串口中斷。
3、在NVIC的配置中主要是USARTx_IRQChannel的配置。
下面是一段配置代碼:
void USART1_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
USART_ClockInitTypeDef USART_ClockInitStruct;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //開啟USART1時(shí)鐘
//配置PA9作為USART1 Tx
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);
//配置PA10作為USART1 Rx
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);
//配置USART1
//中斷被屏蔽了
USART_InitStructure.USART_BaudRate = 9600; //波特率可以通過地面站配置
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //8位數(shù)據(jù)
USART_InitStructure.USART_StopBits = USART_StopBits_1; //在幀結(jié)尾傳輸1個(gè)停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //禁用奇偶校驗(yàn)
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //硬件流控制失能
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //發(fā)送、接收使能
//配置USART1時(shí)鐘
USART_ClockInitStruct.USART_Clock = USART_Clock_Disable; //時(shí)鐘低電平活動(dòng)
USART_ClockInitStruct.USART_CPOL = USART_CPOL_Low; //SLCK引腳上時(shí)鐘輸出的極性-》低電平
USART_ClockInitStruct.USART_CPHA = USART_CPHA_2Edge; //時(shí)鐘第二個(gè)邊沿進(jìn)行數(shù)據(jù)捕獲
USART_ClockInitStruct.USART_LastBit = USART_LastBit_Disable; //最后一位數(shù)據(jù)的時(shí)鐘脈沖不從SCLK輸出
USART_Init(USART1, &USART_InitStructure);
USART_ClockInit(USART1, &USART_ClockInitStruct);
/* Enable USART1 DMA TX request */
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
//使能USART1接收中斷
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
//使能USART1
USART_Cmd(USART1, ENABLE);
}
void NVIC_Configuration(void)//配置中斷
{
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAM
//將向量表起始地址設(shè)置為0x00000000
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else //VECT_TAB_FLASH
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
//配置用1位表示優(yōu)先級(jí)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //選擇第1組優(yōu)先級(jí) 解釋如下第
//0 組:所有 4bit 用于指定響應(yīng)優(yōu)先級(jí);
//第 1 組:最高 1 位用于指定搶占式優(yōu)先級(jí),后面 3 位用于指定響應(yīng)優(yōu)先級(jí);
//第 2 組:最高 2 位用于指定搶占式優(yōu)先級(jí),后面 2 位用于指定響應(yīng)優(yōu)先級(jí);
//第 3 組:最高 3 位用于指定搶占式優(yōu)先級(jí),后面 1 位用于指定響應(yīng)優(yōu)先級(jí);
//第 4 組:所有 4 位用于指定搶占式優(yōu)先級(jí)。
//允許USART1中斷
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//選擇串口1中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/**************************************************************************************
函數(shù)名:USART1_SendData
描述?。篣SART1發(fā)送函數(shù)
輸入?。簾o
輸出?。簾o
返回?。簾o
**************************************************************************************/
void USART1_SendData(uint16_t Data)
{
USART1-》DR = (Data & (uint16_t)0x01FF);
while(((USART1-》SR)&0x0080)==RESET);
}
/****************************************************************************
* 名稱:USART1_Printf()
* 功能:向串口發(fā)送一字符串 用法同Printf()函數(shù)
* 入口參數(shù):format 要發(fā)送的字符串的指針 。。。 為參數(shù)
* 出口參數(shù):發(fā)送的字符串的字符個(gè)數(shù)
****************************************************************************/
int USART1_Printf(const char *format, 。。。)
{
va_list v_list;
char *ptr;
int i= 0;
va_start(v_list, format); // Initialize variable arguments.
vsprintf(tbuf1, format, v_list );
va_end(v_list);
ptr= tbuf1;
while( (*ptr) && i《MAX_TBUF1) {
USART1_SendData(*ptr);
ptr++; i++;
}//while
return i;
}
void USART1_IRQHandler(void) //中斷接收函數(shù)
{
if((USART1-》SR)&0x0020) //是否接收中斷 (接收寄存器非空)
{
//寫入執(zhí)行動(dòng)作
}
USART1-》SR = 0xFFDF;
}
注意1:
所謂搶占式優(yōu)先級(jí)和響應(yīng)優(yōu)先級(jí),他們之間的關(guān)系是:具有高搶占式優(yōu)先級(jí)的中斷可以在具有低搶占式優(yōu)先級(jí)
的中斷處理過程中被響應(yīng),即中斷嵌套。
當(dāng)兩個(gè)中斷源的搶占式優(yōu)先級(jí)相同時(shí),這兩個(gè)中斷將沒有嵌套關(guān)系,當(dāng)一個(gè)中斷到來后,如果正在處理另一個(gè)
中斷,這個(gè)后到來的中斷就要等到前一個(gè)中斷處理完之后才能被處理。如果這兩個(gè)中斷同時(shí)到達(dá),則中斷控制器根
據(jù)他們的響應(yīng)優(yōu)先級(jí)高低來決定先處理哪一個(gè);如果他們的搶占式優(yōu)先級(jí)和響應(yīng)優(yōu)先級(jí)都相等,則根據(jù)他們?cè)谥袛?/p>
表中的排位順序決定先處理哪一個(gè)。每一個(gè)中斷源都必須定義 2 個(gè)優(yōu)先級(jí)。
有幾點(diǎn)需要注意的是:
1)如果指定的搶占式優(yōu)先級(jí)別或響應(yīng)優(yōu)先級(jí)別超出了選定的優(yōu)先級(jí)分組所限定的范圍,將可能得到意想不到的結(jié)
果;
2)搶占式優(yōu)先級(jí)別相同的中斷源之間沒有嵌套關(guān)系;
3)如果某個(gè)中斷源被指定為某個(gè)搶占式優(yōu)先級(jí)別,又沒有其它中斷源處于同一個(gè)搶占式優(yōu)先級(jí)別,則可以為這個(gè)
中斷源指定任意有效的響應(yīng)優(yōu)先級(jí)別。
注意2:
注意在對(duì)數(shù)據(jù)進(jìn)行發(fā)送和接收的時(shí)候,要檢查 USART 的狀態(tài),只有等到數(shù)據(jù)發(fā)送或接收完畢之后才能進(jìn)行下一幀數(shù)據(jù)的發(fā)送或接收。采用 USART_GetFlagStatus()函數(shù)。
同時(shí)還要注意的是,在發(fā)送數(shù)據(jù)的最開始,需要清除一下 USART 的標(biāo)志位,否則,第 1 位數(shù)據(jù)會(huì)丟失。因?yàn)樵谟布?fù)位之后,USART 的狀態(tài)位 TC 是置位的。當(dāng)包含有數(shù)據(jù)的一幀發(fā)送完成之后,由硬件將該位置位。只要當(dāng)
USART 的狀態(tài)位 TC 是置位的時(shí)候,就可以進(jìn)行數(shù)據(jù)的發(fā)送。然后 TC 位的置零則是通過軟件序列來清除的,具體的步驟是“先讀 USART_SR,然后寫入 USART_DR”,只有這樣才能夠清除標(biāo)志位 TC,但是在發(fā)送第一幀數(shù)據(jù)的時(shí)候,并沒有進(jìn)行讀 USART_SR 的操作,而是直接進(jìn)行寫操作,因此 TC 標(biāo)志位并沒有清空,那么,當(dāng)發(fā)送第一幀數(shù)據(jù),然后用 USART_GetFlagStatus()檢測(cè)狀態(tài)時(shí)返回的是已經(jīng)發(fā)送完畢(因?yàn)?TC 位是置 1 的),所以程序會(huì)馬上發(fā)送下一幀數(shù)據(jù),那么這樣,第一幀數(shù)據(jù)就被第二幀數(shù)據(jù)給覆蓋了,所以看不到第一幀數(shù)據(jù)的發(fā)送
評(píng)論
查看更多