STM32F103xE的USART異步數據傳輸示例
USART全稱Universal Synchronous/Asynchronous Receiver/Transmitter
,是一種可以進行同步/異步通信的串行設備接口。
通過查閱STM32官方手冊得之,STM32f10x系列一共有五個USART傳輸串口。其中USART1、USART2、USART3為同步/異步串行通信接口,USART4、USART5為異步串行通信接口。
STM32外設的初始化步驟基本上是:
- 使能外設時鍾
- 配置外設所需要的I/O端口
- 配置外設
- 使能外設
根據這個步驟首先我們使能外設時鍾
使能外設時鍾
查閱手冊
通過該圖我們看到USART1位於總線APB2上面,而USART2、3和UART4、5位於總線APB1上面。
因此我們開啟USART1的時鍾
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//開啟USART1時鍾
配置外設所需I/O端口
通過查閱STM32官方手冊得之,STM32f10x系列一共有五個USART傳輸串口。其中USART1、USART2、USART3為同步/異步串行通信接口,USART4、USART5為異步串行通信接口。
在這里我們將使用USART1同步/異步串行通信接口為例,進行介紹。既然想通過USART1通信接口發送數據,那肯定GPIO引腳呀,因此繼續在官方手冊中查找
該表格清楚明了的說明了USART1的各個引腳。其中TX(Transmit data
發送數據輸出)、RX(Receive data
接受數據輸入)、CK(Clock
發送時鍾輸出)、CTS(Clear to Send
允許發送)、RTS(Request to Send
請求發送)分別對應於PA09、PA10、PA08、PA11、PA12。
因此我們配置I/O端口:
GPIO_InitTypeDef GPIO_InitStrue;
//時鍾使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
//GPIO10使能TX
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;//復用推挽輸出
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10; //10腳
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度為50MHz
GPIO_Init(GPIOB,&GPIO_InitStrue); //根據設定參數初始化GPIOB_10
//GPIO10使能RX
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空輸入
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_11;//11腳
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度為50MHz
GPIO_Init(GPIOB,&GPIO_InitStrue); //根據設定參數初始化GPIOB_11
配置外設
在這里外設當然是USART1啦。我們只需要根據自己的需要配置就行啦。主要的配置項有波特率
,有無硬件控制流
,發送/接受
,有無奇偶校驗
,停止位
,數據位
。
其中波特率指的是數據傳輸到速度指每秒鍾發送多少bit的數據;硬件控制流指是否通過CTS和RTS控制數據傳輸;有無奇偶校驗則比較簡單就是是否對傳輸的數據進行奇偶校驗;因為USART接口傳輸需要對數據進行封裝,即在原有的數據中加上開始位,在原始數據的尾部加上停止位,因此停止位值得就是停止位的長度;數據位指的是每次傳輸中有效數據的長度。
一個配置的示例:
USART_InitStrue.USART_BaudRate=9600;//波特率9600
USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//無硬件流控制
USART_InitStrue.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//使能發送、接收
USART_InitStrue.USART_Parity=USART_Parity_No;//無基偶校驗
USART_InitStrue.USART_StopBits=USART_StopBits_1;//停止位1位
USART_InitStrue.USART_WordLength=USART_WordLength_8b;//數據8位
USART_Init(USART1,&USART_InitStrue);//根據設定初始化USART1
使能外設
直接使能USART即可
USART_Cmd(USART1,ENABLE);
接下來配置USART1的中斷
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//開中斷USART1
NVIC_InitStrue.NVIC_IRQChannel=USART1_IRQn;//通道
NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;//使能
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1;//搶占優先級
NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;//子優先級
NVIC_Init(&NVIC_InitStrue);
以及中斷服務函數
在該函數中我們首先判斷中斷類型,是否為接受中斷;如果是接受中斷則接受字符並通過USART1發送出去,最后我們使用了一個while函數來確保數據成功發送。
//中斷服務函數
void USART1_IRQHandler(void)
{
u8 USART1_in;
if(USART_GetITStatus(USART1,USART_IT_RXNE))
{
USART1_in=USART_ReceiveData(USART1);
USART_SendData(USART1, USART1_in);//向串口3發送數據
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待發送結束
}
}
廢話少說,直接上最終代碼
配置IO引腳、USART、中斷向量優先級等參數:
//串口初始化
void USART1_init()
{
GPIO_InitTypeDef GPIO_InitStrue;
USART_InitTypeDef USART_InitStrue;
NVIC_InitTypeDef NVIC_InitStrue;
//時鍾使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
//GPIO10使能TX
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;//復用推挽輸出
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10; //10腳
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度為50MHz
GPIO_Init(GPIOB,&GPIO_InitStrue); //根據設定參數初始化GPIOB_10
//GPIO10使能RX
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空輸入
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_11;//11腳
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度為50MHz
GPIO_Init(GPIOB,&GPIO_InitStrue); //根據設定參數初始化GPIOB_11
//USART初始化
USART_InitStrue.USART_BaudRate=9600;//波特率9600
USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//無硬件流控制
USART_InitStrue.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//使能發送、接收
USART_InitStrue.USART_Parity=USART_Parity_No;//無基偶校驗
USART_InitStrue.USART_StopBits=USART_StopBits_1;//停止位1位
USART_InitStrue.USART_WordLength=USART_WordLength_8b;//數據8位
USART_Init(USART1,&USART_InitStrue);//根據設定初始化USART1
//USART1使能
USART_Cmd(USART1,ENABLE);
//開中斷
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//開中斷USART1
NVIC_InitStrue.NVIC_IRQChannel=USART1_IRQn;//通道
NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;//使能
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1;//搶占優先級
NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;//子優先級
NVIC_Init(&NVIC_InitStrue);
}
中斷接受函數
//中斷服務函數
void USART1_IRQHandler(void)
{
u8 USART1_in;
if(USART_GetITStatus(USART1,USART_IT_RXNE))
{
USART1_in=USART_ReceiveData(USART1);
USART_SendData(USART1, USART1_in);//向串口3發送數據
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待發送結束
}
}
將使用USART1同步/異步串行通信接口為例,進行介紹。既然想通過USART1通信接口發送數據,那肯定GPIO引腳呀,因此繼續在官方手冊中查找
廢話少說,直接上代碼
配置IO引腳、USART、中斷向量優先級等參數:
//串口初始化
void USART1_init()
{
GPIO_InitTypeDef GPIO_InitStrue;
USART_InitTypeDef USART_InitStrue;
NVIC_InitTypeDef NVIC_InitStrue;
//時鍾使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART1,ENABLE);
//GPIO10使能TX
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;//復用推挽輸出
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10; //10腳
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度為50MHz
GPIO_Init(GPIOB,&GPIO_InitStrue); //根據設定參數初始化GPIOB_10
//GPIO10使能RX
GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空輸入
GPIO_InitStrue.GPIO_Pin=GPIO_Pin_11;//11腳
GPIO_InitStrue.GPIO_Speed=GPIO_Speed_50MHz;//IO口速度為50MHz
GPIO_Init(GPIOB,&GPIO_InitStrue); //根據設定參數初始化GPIOB_11
//USART初始化
USART_InitStrue.USART_BaudRate=9600;//波特率9600
USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//無硬件流控制
USART_InitStrue.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//使能發送、接收
USART_InitStrue.USART_Parity=USART_Parity_No;//無基偶校驗
USART_InitStrue.USART_StopBits=USART_StopBits_1;//停止位1位
USART_InitStrue.USART_WordLength=USART_WordLength_8b;//數據8位
USART_Init(USART1,&USART_InitStrue);//根據設定初始化USART1
//USART1使能
USART_Cmd(USART1,ENABLE);
//開中斷
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//開中斷USART1
NVIC_InitStrue.NVIC_IRQChannel=USART1_IRQn;//通道
NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;//使能
NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1;//搶占優先級
NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;//子優先級
NVIC_Init(&NVIC_InitStrue);
}
中斷接受函數
//中斷服務函數
void USART1_IRQHandler(void)
{
u8 USART1_in;
if(USART_GetITStatus(USART1,USART_IT_RXNE))
{
USART1_in=USART_ReceiveData(USART1);
USART_SendData(USART1, USART1_in);//向串口3發送數據
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待發送結束
}
}