目录
一、串口简介
通用异步收发器 UART(Universal Asynchronous Receiver/Transmitter),是一种串行、异步、全双工的通信协议。通过发送线(TX)、接收线(RX)、GND就可以进行全双工通信。需要确定好通信双方的波特率(bps指每秒传输的码元数量)
串口通信是一位一位地传输,每传输一个字符总是以起始位开始,以停止位结束,字符之间没有固定的时间间隔要求。每一个字符的前面都有一位起始位(低电平),后面由7位数据位组成,接着是1位校验位,最后是1位停止位。停止位后面是不定长的空闲位,停止位和空闲位都规定为高电平。
一般的数据格式:(1bit)起始位+(7bit) 数据位 + (None)校验位 + (1bit)停止位
起始位:通信线路上空闲时为“1”,当检测到“0”即下降沿时,认为数据传输开始
有效数据位:传输开始后传递的需要接收和发送的数据值,可以表示指令或数据
奇偶校验位:奇偶校验,通过来校验传输数据中“1”的个数为奇数个(奇校验)或偶数个(偶校验)来指示传输数据是否正确
停止位:数据传输结束,传输线恢复常“1”状态
此外,还需关注数据传输波特率,波特率表示一秒内传输了多少个码元数量,一般波特率为300,1200,2400,9600,19200,38400,115200等。例如9600 Baud表示一秒内传输了9600个码元信息,当一个码元只含1 bit信息时,波特率=比特率
二、串口配置流程
一般我们使用串口,都需要有以下几个步骤:
1.开启GPIO时钟和串口时钟
2.配置GPIO模式并初始化
3.配置串口参数
4.使能串口
三、代码实现
Usart.c (这里的重定义函数需要勾选Use MicroLIB)
#include "stm32f10x.h" // Device header #include "Usart.h" u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节. //接收状态 //bit15, 接收完成标志 //bit14, 接收到0x0d //bit13~0, 接收到的有效字节数目 u16 USART_RX_STA=0; //接收状态标记 //重定义fputc函数 int fputc(int ch, FILE *f) { USART_SendData(USART1, (uint8_t) ch); while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); //等待发送完成 return ch; } void Usart1_Init(uint32_t bound) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE); //USART1_TX PA9 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); //USART1_RX PA10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_Init(GPIOA,&GPIO_InitStructure); //USART1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_Init(&NVIC_InitStructure); //USART1 初始化配置 USART_InitStructure.USART_BaudRate = bound; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_Init(USART1,&USART_InitStructure); //初始化串口 1 USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //开启串口接收中断 USART_Cmd(USART1,ENABLE); //使能串口 1 } void USART1_IRQHandler( void ) /* 串口1中断服务程序 */ { u8 Res; if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾) { Res =USART_ReceiveData(USART1); //读取接收到的数据 if((USART_RX_STA&0x8000)==0)//接收未完成 { if(USART_RX_STA&0x4000)//接收到了0x0d { if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始 else USART_RX_STA|=0x8000; //接收完成了 } else //还没收到0X0D { if(Res==0x0d)USART_RX_STA|=0x4000; else { USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ; USART_RX_STA++; if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收 } } } } }
Usart.h
#ifndef __USART_H_ #define __USART_H_ #include "stm32f10x.h" // Device header #include <stdio.h> #define USART_REC_LEN 200 //定义最大接收字节数 200 #define EN_USART1_RX 1 //使能(1)/禁止(0)串口1接收 extern u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符 extern u16 USART_RX_STA; //接收状态标记 void Usart1_Init(uint32_t bound); #endif
main.c
#include "stm32f10x.h" // Device header #include "Delay.h" #include "Usart.h" //硬件部分 #include "LED.h" #include "KEY.h" int main(void) { Usart1_Init(9600); //串口1 初始化 LED_Init(); while(1) { LED_ON; Delay_ms(500); LED_OFF; Delay_ms(500); printf("hello word\r\n"); if(USART_RX_STA & 0x8000) //接收完成 { printf("Received data: %s\n", USART_RX_BUF); USART_RX_STA = 0; //清除接收状态标记 } } }