STM32f103zet6 串口的基本配置及詳細說明


玩stm32也有一段時間了,對串口中斷接受和DAM方式發送總一下總結,但是本節只講述串口中斷接受的基本配置,既然是基本就說明他很重要,如有疏忽,就會讓串口失靈。下一節主要講述DAM的用法。言歸正傳:首先我們要知道開啟一個功能的步驟如下,

(1)RCC配置

(2)GPIO配置

(3)USART配置

(4)發送/接收數據

在RCC配置中,我們除了常規的時鍾設置之外,需要打開USART相應的IO口時鍾,USART時鍾,還有管腳功能復用時鍾。

1、在GPIO配置中,將發送端的管腳配置為復用推挽輸出,講接受端的管腳設置為浮空輸入。注意紅色標記,這兩種模式很重要,注意其區別。

2、在USART的配置中,通過USART_InitTypeDdf結構體對USART進行初始化操作。如用中斷方式:在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時鍾

 //配置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位數據
 USART_InitStructure.USART_StopBits = USART_StopBits_1;   //在幀結尾傳輸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;  //發送、接收使能
 //配置USART1時鍾
 USART_ClockInitStruct.USART_Clock = USART_Clock_Disable;  //時鍾低電平活動
 USART_ClockInitStruct.USART_CPOL = USART_CPOL_Low;  //SLCK引腳上時鍾輸出的極性->低電平
 USART_ClockInitStruct.USART_CPHA = USART_CPHA_2Edge;  //時鍾第二個邊沿進行數據捕獲
 USART_ClockInitStruct.USART_LastBit = USART_LastBit_Disable; //最后一位數據的時鍾脈沖不從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
 //將向量表起始地址設置為0x00000000
 NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
 #else //VECT_TAB_FLASH
 NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
 #endif

 //配置用1位表示優先級
 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);     //選擇第1組優先級 解釋如下第

//0 組:所有 4bit 用於指定響應優先級;
//第 1 組:最高 1 位用於指定搶占式優先級,后面 3 位用於指定響應優先級;
//第 2 組:最高 2 位用於指定搶占式優先級,后面 2 位用於指定響應優先級;
//第 3 組:最高 3 位用於指定搶占式優先級,后面 1 位用於指定響應優先級;
//第 4 組:所有 4 位用於指定搶占式優先級。

  //允許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); 

}

/**************************************************************************************
函數名:USART1_SendData
描述 :USART1發送函數
輸入 :無
輸出 :無
返回 :無
**************************************************************************************/
void USART1_SendData(uint16_t Data)
{
 USART1->DR = (Data & (uint16_t)0x01FF);
 
 while(((USART1->SR)&0x0080)==RESET); 
}

/****************************************************************************
* 名稱:USART1_Printf()
* 功能:向串口發送一字符串 用法同Printf()函數
* 入口參數:format 要發送的字符串的指針 ... 為參數
* 出口參數:發送的字符串的字符個數
****************************************************************************/
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)  //中斷接收函數
{
 if((USART1->SR)&0x0020) //是否接收中斷 (接收寄存器非空)    
 {

  //寫入執行動作
  }
 
 USART1->SR = 0xFFDF;

}

注意1:

所謂搶占式優先級和響應優先級,他們之間的關系是:具有高搶占式優先級的中斷可以在具有低搶占式優先級
的中斷處理過程中被響應,即中斷嵌套。
當兩個中斷源的搶占式優先級相同時,這兩個中斷將沒有嵌套關系,當一個中斷到來后,如果正在處理另一個
中斷,這個后到來的中斷就要等到前一個中斷處理完之后才能被處理。如果這兩個中斷同時到達,則中斷控制器根
據他們的響應優先級高低來決定先處理哪一個;如果他們的搶占式優先級和響應優先級都相等,則根據他們在中斷
表中的排位順序決定先處理哪一個。每一個中斷源都必須定義 2 個優先級。
有幾點需要注意的是:
1)如果指定的搶占式優先級別或響應優先級別超出了選定的優先級分組所限定的范圍,將可能得到意想不到的結
果;

2)搶占式優先級別相同的中斷源之間沒有嵌套關系;
3)如果某個中斷源被指定為某個搶占式優先級別,又沒有其它中斷源處於同一個搶占式優先級別,則可以為這個
中斷源指定任意有效的響應優先級別。

注意2:

注意在對數據進行發送和接收的時候,要檢查 USART 的狀態,只有等到數據發送或接收完畢之后才能進行下
一幀數據的發送或接收。采用 USART_GetFlagStatus()函數。
同時還要注意的是,在發送數據的最開始,需要清除一下 USART 的標志位,否則,第 1 位數據會丟失。因為
在硬件復位之后,USART 的狀態位 TC 是置位的。當包含有數據的一幀發送完成之后,由硬件將該位置位。只要當
USART 的狀態位 TC 是置位的時候,就可以進行數據的發送。然后 TC 位的置零則是通過軟件序列來清除的,具體的
步驟是“先讀 USART_SR,然后寫入 USART_DR”,只有這樣才能夠清除標志位 TC,但是在發送第一幀數據的
時候,並沒有進行讀 USART_SR 的操作,而是直接進行寫操作,因此 TC 標志位並沒有清空,那么,當發送第一幀
數據,然后用 USART_GetFlagStatus()檢測狀態時返回的是已經發送完畢(因為 TC 位是置 1 的),所以程序會馬上
發送下一幀數據,那么這樣,第一幀數據就被第二幀數據給覆蓋了,所以看不到第一幀數據的發送。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM