STM32有數(shù)個(gè)串口,每個(gè)串口都有一個(gè)自己獨(dú)立的波特率寄存器USART_BRR,通過(guò)設(shè)置該寄存器就可以達(dá)到配置不同波特率的目的,由于STM32采用分?jǐn)?shù)波特率,所以STM32的串口波特率設(shè)置范圍很寬,而且誤差很小。
在STM32的參考手冊(cè)中,串口被描述成通用同步異步收發(fā)器(USART),它提供了一種靈活的方法與使用工業(yè)標(biāo)準(zhǔn)NRZ異步串行數(shù)據(jù)格式的外部設(shè)備之間進(jìn)行全雙工數(shù)據(jù)交換。USART利用分?jǐn)?shù)波特率發(fā)生器提供寬范圍的波特率選擇。它支持同步單向通信和半雙工單線通信,也支持LIN(局部互聯(lián)網(wǎng)),智能卡協(xié)議和IrDA(紅外數(shù)據(jù)組織)SIR ENDEC規(guī)范,以及調(diào)制解調(diào)器(CTS/RTS)操作。它還允許多處理器通信。還可以使用DMA方式,實(shí)現(xiàn)高速數(shù)據(jù)通信。
USART通過(guò)3個(gè)引腳與其他設(shè)備連接在一起,任何USART雙向通信至少需要2個(gè)引腳:接受數(shù)據(jù)輸入(RX)和發(fā)送數(shù)據(jù)輸出(TX)。
RX: 接受數(shù)據(jù)串行輸入。通過(guò)過(guò)采樣技術(shù)來(lái)區(qū)別數(shù)據(jù)和噪音,從而恢復(fù)數(shù)據(jù)。
TX: 發(fā)送數(shù)據(jù)輸出。當(dāng)發(fā)送器被禁止時(shí),輸出引腳恢復(fù)到它的I/O端口配置。當(dāng)發(fā)送器被激活,并且不發(fā)送數(shù)據(jù)時(shí),TX引腳處處于高電平。在單線和智能卡模式里,此I/O口被同時(shí)用于數(shù)據(jù)的發(fā)送和接收。
一般有兩種工作方式:查詢和中斷。
(1)查詢:串口程序不斷地循環(huán)查詢,看看當(dāng)前有沒(méi)有數(shù)據(jù)要它傳送。如果有,就幫助傳送(可以從PC到STM32板子,也可以從STM32板子到PC)。
(2)中斷:平時(shí)串口只要打開(kāi)中斷即可。如果發(fā)現(xiàn)有一個(gè)中斷來(lái),則意味著要它幫助傳輸數(shù)據(jù)——它就馬上進(jìn)行數(shù)據(jù)的傳送。同樣,可以從 PC到STM3板子,也可以從STM32板子到PC
注意:
發(fā)動(dòng)和接受都需要配合標(biāo)志等待。
只能對(duì)一個(gè)字節(jié)操作,對(duì)字符串等大量數(shù)據(jù)操作需要寫函數(shù)
使用串口所需設(shè)置:RCC初始化里面打開(kāi)RCC_APB2PeriphClockCmd
(RCC_APB2Periph_USARTx);GPIO里面管腳設(shè)定:串口RX(50Hz,IN_FLOATING);串口TX(50Hz,AF_PP);
printf函數(shù)重定義(不必理解,調(diào)試通過(guò)以備后用)
需要c標(biāo)準(zhǔn)函數(shù):#include "stdio.h"
增加為putchar函數(shù)。
int putchar(int c) //putchar函數(shù)
{if (c == '\n'){putchar('\r');} //將printf的\n變成\r
USART_SendData(USART1, c); //發(fā)送字符
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){} //等待發(fā)送結(jié)束
return c; //返回值
}
printf使用變量輸出:%c字符,%d整數(shù),%f浮點(diǎn)數(shù),%s字符串,/n或/r為換行。注意:只能用于main.c中。
另外:
STM32支持三個(gè)串口,在usart1默認(rèn)引腳被占用的情況下可以將usart1映射到PB0.6和PB0.7上。實(shí)現(xiàn)的方法 如下:
1、打開(kāi)GPIO的AFIO時(shí)鐘,使用stm32功能模塊之前,必須開(kāi)時(shí)鐘;
2、使能USART1的映射,
3、配置USART1映射后的GPIO(PB0.6,PB0.7)
具體實(shí)現(xiàn):
1、在set_systm函數(shù)中添加如下模塊,打開(kāi)AFIO時(shí)鐘,使能USART1映射
#ifdef USB_TO_KLINE_USART1_REMAP
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);
#endif
2、在set_systm函數(shù)中添加如下模塊,配置USART1映射后的GPIO
#ifdef USB_TO_KLINE_USART1_REMAP
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
#else
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
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);
#endif
例:
#include "stm32f10x.h"
#include "stm32_eval.h"
#include <stdio.h>
USART_InitTypeDef USART_InitStructure; //定義結(jié)構(gòu)體類型變量
void GPIO_Configuration(void); //聲明GPIO配置函數(shù)
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch) //此處定義為putchar應(yīng)用
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
int main(void)
{
SystemInit(); //配置系統(tǒng)時(shí)鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1| RCC_APB2Periph_AFIO, ENABLE); //打開(kāi)APB2功能時(shí)鐘(UART1為連接在APB2上的高速外設(shè))開(kāi)啟了串口時(shí)鐘和復(fù)用功能時(shí)鐘
GPIO_Configuration(); //調(diào)用GPIO配置函數(shù)
USART_InitStructure.USART_BaudRate = 115200; //設(shè)置USART傳輸波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //設(shè)置USART傳輸數(shù)據(jù)位一幀為8位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //設(shè)置USART傳輸每幀一個(gè)停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //設(shè)置USART無(wú)奇偶校驗(yàn)
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //設(shè)置USART無(wú)硬件流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//開(kāi)啟USART發(fā)送和接受功能
USART_Init(USART1, &USART_InitStructure); //初始化USART1設(shè)置
USART_Cmd(USART1, ENABLE); //開(kāi)啟USART1
printf("\n\r 李繼超是個(gè)好人嗎? \n\r");
printf("\n\r 回答:李繼超是個(gè)大好人! \n\r");
printf("\n\r 菏澤是個(gè)是個(gè)美麗的地方! \n\r");
printf("\n\r 發(fā)生了什么?你是猴子請(qǐng)來(lái)的救兵嗎? \n\r");
printf("\n\r 嗯!李繼超的確是個(gè)大好人�。�!你才魔道呢!哼�。。� \n\r"); //配置輸出數(shù)據(jù)
while (1)
{
}
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //定義結(jié)構(gòu)體變量類型
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //打開(kāi)GPIOA的功能時(shí)鐘
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //選擇GPIO引腳GPIO_Pin_9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //設(shè)置GPIO速率
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //設(shè)置GPIO_pin_9為 復(fù)用功能 推挽輸出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIO_Pin_9設(shè)置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //選擇GPIO引腳GPIO_Pin_10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //設(shè)置GPIO_Pin_10浮空輸入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIO_Pin_10設(shè)置
}
PUTCHAR_PROTOTYPE //重定義printf函數(shù)
{
USART_SendData(USART1, (uint8_t) ch); //發(fā)送字符串
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)// 檢測(cè)是否發(fā)送完成
{}
return ch;
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
while (1)
{}
}
#endif