七、USART
STM32F407xx內嵌四個通用同步/異步接收器(USART1,USART2,USART3和USART6)和兩個通用異步收發器(UART4和UART5)。這6個接口提供異步通信的IrDASIR ENDEC支持,多機通信模式,單線半雙工通信模式LIN主/從功能。 USART1和USART6接口能夠速度高達10.5 Mbit / s的通信其他可用的接口通信高達5.25bit/s。USART1,USART2,USART3和USART6還提供硬件管理的CTS,RTS信號,智能卡的模式(ISO7816兼容)和類似的SPI通信能力。所有接口都可以通過DMA控制器。
USART name |
Standard features |
Modem (RTS/CTS) |
LIN |
SPI master |
irDA |
Smartcard (ISO 7816) |
Max. baud rate in Mbit/s (oversampling by 16) |
Max. baud rate in Mbit/s (oversampling by 8) |
APB mapping |
USART1 |
X |
X |
X |
X |
X |
X |
5.25 |
10.5 |
APB2 (max. 84 MHz) |
USART2 |
X |
X |
X |
X |
X |
X |
2.62 |
5.25 |
APB1 (max. 42 MHz) |
USART3 |
X |
X |
X |
X |
X |
X |
2.62 |
5.25 |
APB1 (max. 42 MHz) |
UART4 |
X |
- |
X |
- |
X |
- |
2.62 |
5.25 |
APB1 (max. 42 MHz) |
UART5 |
X |
- |
X |
- |
X |
- |
2.62 |
5.25 |
APB1 (max. 42 MHz) |
USART6 |
X |
X |
X |
X |
X |
X |
5.25 |
10.5 |
APB2 (max. 84 MHz) |
這裏只介紹兩根線的最簡單串口設置。
波特率的計算:
USART用的波特率是由APB時鐘線和波特率寄存器USART_BRR確定的,USART_BRR爲32位寄存器,其中高16位保留,低十六位確定波特率,低16位又分爲[15:4]和[3:0]或[15:4]和[2:0],具體分法由OVER8決定,[15:4]存放USARTDIV的整數部分,小數部分由[3:0]或[2:0]存放。
小數部分USARTDIV的小數部分乘以16或8,結果保留整數存於USART_BRR[3:0]或[2:0]中
比如:要求波特率爲115200
設置OVER8=0
解得:USARTDIV=22.768
USART_BRR[15:4]=22=0x16
USART_BRR[3:0]=0.768*16=13=0xC
USART_BRR=0x0000016C
設置步驟:
1. 設置中斷優先級分組(如果之前沒有設置),這個最好一個程序裏只在開頭設置一次。
2. 使能相關時鐘。
3. 設置波特率。
4. 設置控制寄存器CR。
5. 選擇相關GPIO引腳的複用功能。
6. 設置相關GPIO引腳爲複用模式。
7. 設置相關GPIO引腳的速度,方式。
8. 如果要用到中斷,設置USART中斷優先級。
9. 如果要用到中斷,使能USART中斷。
10. 如果要用中斷,編寫中斷服務函數(函數名是固定的)。
11. 中斷服務函數裏檢查是哪個中斷。
12. 編寫相應服務程序。
電路參見本博客:小工具之——max232電平轉換
程序:
/*********************************************
標題:操作USART的練習
軟件平臺:IAR for ARM6.21
硬件平臺:stm32f4-discovery
主頻:168M
描述:從其他設備接收數據,再把數據發送出去
author:小船
data:2012-02-01
**********************************************/
#include <stm32f4xx.h>
u32 Gb_TimingDelay;
u8 suffer[100];
u8 ok_to_send;
u8 Rx_data_counter;
void Delay(uint32_t nTime);
void main ()
{
char Tx_data_counter;
SCB->AIRCR = 0x05FA0000 | 0x400; //中斷優先級分組 搶佔:響應=3:1
SysTick_Config(SystemCoreClock / 1000); //設置systemtick一毫秒中斷
RCC->AHB1ENR |= 0x00000008; //使能GPIOD時鐘
RCC->APB1ENR |= (1<<18); //使能usart3時鐘
USART3->BRR = 0x0000016C; //波特率115200
/*
使能usart3
usart3發送使能
usart3接收使能
接收緩衝區非空中斷使能
8bit
一位停止位
無校驗
*/
USART3->CR1 |= (( 1<<13 ) | ( 1<<3 ) | ( 1<<2 ) | ( 1<<5 ));
GPIOD->AFR[1] |= 0x00000077;//選擇PD8,9複用功能
GPIOD->MODER &= 0xFFF0FFFF; //設置PD8,9,複用模式
GPIOD->MODER |= 0x000A0000;
// GPIOD->OTYPER &= 0xFFFFDFFF; //設置PD9推輓輸出
GPIOD->OSPEEDR &= 0xFFFCFFFF; //PD8速度50m
GPIOD->OSPEEDR |= 0x00020000;
GPIOD->PUPDR &= 0xFFFCFFFF; //PD8
GPIOD->PUPDR |= 0x00010000;
NVIC->IP[39] = 0xf0; //最低搶佔優先級,最低響應優先級1111
NVIC->ISER[1] |= (1<<(39-32)); //使能中斷線39,也就是usart3中斷
while(1)
{
if(ok_to_send) //接收到數據,可以將數據發送
{
if((USART3->SR & (1<<7))) //發送數據寄存器空
{
USART3->DR = suffer[Tx_data_counter];
Tx_data_counter++;
if( suffer[Tx_data_counter] == '\r' )
{
Tx_data_counter = 0;
USART3->CR1 |= 1<<5; //使能接收中斷
ok_to_send = 0;
}
}
}
}
}
void Delay(uint32_t nTime)
{
Gb_TimingDelay = nTime;
while(Gb_TimingDelay != 0);
}
void SysTick_Handler(void)
{
if (Gb_TimingDelay != 0x00)
{
Gb_TimingDelay--;
}
}
void USART3_IRQHandler(void)
{
if(USART3->SR & (1<<5)) //接收數據寄存器非空
{
suffer[Rx_data_counter] = USART3->DR;
Rx_data_counter++;
if(suffer[Rx_data_counter - 1] == '\r')
{
Rx_data_counter = 0;
USART3->CR1 &= ~(1<<5); //除能接收中斷
ok_to_send = 1;
}
}
}
運行結果: