串口USART
1 常见的通信方式
1.1串行通信和并行通信
串行通信:速度教并行慢,但是占用的硬件资源少,通常只需要时钟线,一两根数据线还
有片选线即可。
并行通信:速度快,但是需要很多根数据线、地址线等。
1.2全双工,半双工和单工通信
全双工:同一时刻双方可以互相发送数据、接收数据
半双工:同一时刻只能有一方可以给另外一方发送数据,即此发彼收,此收彼发
单工:只能由发送方数据发送给接收方
1.3.同步通信和异步通信
同步通信和异步通信都是针对串行通信而言
异步通信
1.数据是以字符为单位组成字符帧传输的。
2.字符帧由发送端一帧一帧的发送,每帧数据均是低位在前,高位在后,通过传输线被接收端 一帧一帧的接收。
3.发送端和接收端可以有各自独立的时钟来控制数据的发送和接收,这两个时钟各自独立,互 不同步。
4.
接收端依靠字符帧格式来判断发送端是何时开始和结束发送的。
5.
字符帧也叫做数据帧,由起始位,数据位,奇偶校验位,停止位等部分组成,是异步通信的 一个重要指标。
6.
同步通信的另一个重要指标是波特率。
同步通信
1.
同步是指在约定的通信速率下,发送端和接收端的时钟信号和相位始终保持一致,保证通信 双方在发送和接收数据时具有完全一致的定时关系。
2.
同步通信把许多字符组成一个信息帧,每帧的开始用同步字符来表示。
3.
在绝大多数场合下,发送端和接收端,采用的都是同一个时钟,所以在传送数据的同时还要 发送时钟信号,以便接收端可以使用时钟信号来确定每一个信息位。
4.
同步通信一次通信只能传送一帧信息。
1.4.通信速率
对于同步通信,通信速率由时钟信号决定,时钟信号越快,传输速度越快。
对于异步通信来说,需要收发双方提前统一通信速率,这也就是我们串口调试时,波特率不对显示乱码的原因。
1.4.1比特率:系统在单位时间内传输的比特率(二进制0或1)个数,通常用Rb
表示,单位是比特(bit/s
),缩写为
bps
。
1.4.2.
波特率:系统在单位时间内传输的码元个数,通常用
RB
来表示,单位是波特(
Bd
)
1.4.3.
码元有
N
个状态时,比特率与波特率的关系式:
RB=Rb x log2N
1.5.常见的通信协议
在嵌入式中,有众多的通信协议,往往从性能,成本,稳定性,易用性等角度考虑选择合
适的协议。

2 串口基础知识
2.1.电平特性

常见通信接口标准:

2.2串口传输协议
串口设备连接示意图:

参数概念:
波特率:一般选波特率都会有
9600
,
19200
,
115200
等选项,其实意思就是每秒传输这么多个比特数(bit
)。
起始位:先发出一个逻辑
‘0’
的信号,表示传输数据的开始。
数据位:可以是
5~8
位逻辑
“0”
或
“1”,
先传输
Bit0
,再传输
bit1
,以此类推。
校验位:数据位加上这一位之后,使得
“1”
的位数应为偶数(偶校验)或者奇数(奇校验),以此来校验数据传送的正确性,校验位是可选的,可以不传输。
停止位:它是一个字符数据的结束标志,数据线变回逻辑
“1”
。
2.3STM32F103的USART资源
1. STM32103
有三个通用同步异步收发器
USART
,两个通用异步收发器
UART
,
USART也可以当作UART
使用。
2.
通常使用的是
UART
功能,
USART
在某些场合会使用到,选择通信方式使用场合决定。
3.
可以通过电平转化芯片变为
RS232/RS485
电平。

2.4STM32F103的UART框图
端口引脚:
1. TX:
数据发送端口
2. RX:
数据接收端口
3. SW_RX:
在单线和智能卡模式下接收数据,属于内部端口,没有实际的外部引脚
4. RTS:
在硬件流控制下用于指示设备准备好可以接收数据了,低电平表示可以接收数据。
5. CTS:
在硬件流控制下用于指示设备以及发送完数据了,如果是高电平那么在本次数据发送完成后会阻塞下一次的传输,只有在低电平的时候才允许下一次传输。
6. CK:
同步时钟端口,在同步通信模式下使用,用于输出同步时钟信号。
数据寄存器单元:

1. TDR:
发送数据寄存器
2. RDR:
接收数据寄存器
3.
在
UART
外设中只有一个寄存器
USART_DR,
是一个双向寄存器,取决于
CPU
是读这个寄存器还是写这个寄存器;如果是读就是RDR
,如果是写就是
TDR
。
发送接收控制单元:
1. CR1/CR2/CR3
:控制寄存器,控制各种使能,比如
UART
使能、收发中断使能、
DMA使能等等。
2. SR:
状态寄存器:用来表明
UART
的收发状态和错误状态等等。
3. GTPR
:
Smartcard
和
IrDA
模式下专用的寄存器
波特率发生器:
1. fPCLK:
外设总线时钟,
USART1
在
APB1
,最高可取
72MHZ,
剩下四个在
APB2
,最高可取36MHZ
2. USARTVIV:USART/UART
时钟分频器
3. DIV_Mantissa:BBR
寄存器的高
12bit
,用于存放波特率设置的整数部分
4. DIV_Fraction
:
BRR
寄存器的低
4bit.
用于存放波特率设置值的小数部分,每一位对应的精度是1/2
的四次方
= 0.0625
5.
波特率计算公司:
baudrate=fPCLK / USARTDIV * 16
UART
框图配置步骤:
选择需要使用的
USART/UART
(根据地址映射表得到地址)
根据需要的波特率设置
BRR
寄存器
根据需求配置控制寄存器中的停止位和校验位
根据需求配置同步时钟使能位
使能
USART
的发送和接收位
根据需求使能发送和接收的中断位
使能
RCC
中的选中的
USART/UART
的时钟
使能
USART/UART
写
USART_DR
寄存器发送数据,读
USART_DR
寄存器接收数据
3 实现串口发送
软件流程设计:
初始化系统
初始化
GPIO
、串口外设时钟
初始化串口引脚
串口发送
usart.c文件
#include "stm32f10x.h"
#include "usart.h"
#include "stdio.h"
void myusart_init(void)
{
GPIO_InitTypeDef GPIOInitStruct;
USART_InitTypeDef USART_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);
GPIOInitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
GPIOInitStruct.GPIO_Pin=GPIO_Pin_9;
GPIOInitStruct.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &GPIOInitStruct);
GPIOInitStruct.GPIO_Mode=GPIO_Mode_IPU;
GPIOInitStruct.GPIO_Pin=GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIOInitStruct);
USART_InitStruct.USART_BaudRate=115200;
USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
USART_InitStruct.USART_Parity=USART_Parity_No;
USART_InitStruct.USART_StopBits=USART_StopBits_1;
USART_InitStruct.USART_WordLength=USART_WordLength_8b;
USART_Init(USART1,&USART_InitStruct);
USART_Cmd(USART1, ENABLE);
}
void My_Usart_Send_Byte(USART_TypeDef* USARTx,uint16_t Data)
{
USART_SendData(USARTx, Data);
while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE)==RESET);
}
void My_Usart_Send_Sting(USART_TypeDef* USARTx,char* str)
{
uint16_t i=0;
do
{
My_Usart_Send_Byte(USARTx,*(str+i));
i++;
}while(*(str+i)!='\0');
while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)==RESET);
}
main.c文件
#include "stm32f10x.h"
#include "main.h"
#include "usart.h"
#include "stdio.h"
void delay(uint16_t time)
{
uint16_t i=0;
while(time--)
{
i=12000;
while(i--);
}
}
int main()
{
myusart_init();
My_Usart_Send_Byte(USART1,'A');
My_Usart_Send_Byte(USART1,'B');
My_Usart_Send_Byte(USART1,'C');
My_Usart_Send_Sting(USART1,"wuyong \r\n");
while(1)
{
}
}
每按下一次复位串口发送一次数据
4 实现串口接收
实现串口中断接收和串口发送控制
LED
灯
软件流程设计
初始化系统
初始化GPIO
、串口外设、
LED
时钟
初始化串口和LED
引脚
串口发送控制
LED
灯
usart.c文件
#include "stm32f10x.h"
#include "usart.h"
#include "stdio.h"
void myusart_init(void)
{
GPIO_InitTypeDef GPIOInitStruct;
USART_InitTypeDef USART_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
GPIOInitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
GPIOInitStruct.GPIO_Pin=GPIO_Pin_9;
GPIOInitStruct.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA, &GPIOInitStruct);
GPIOInitStruct.GPIO_Mode=GPIO_Mode_IPU;
GPIOInitStruct.GPIO_Pin=GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIOInitStruct);
USART_InitStruct.USART_BaudRate=115200;
USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
USART_InitStruct.USART_Parity=USART_Parity_No;
USART_InitStruct.USART_StopBits=USART_StopBits_1;
USART_InitStruct.USART_WordLength=USART_WordLength_8b;
NVIC_InitStruct.NVIC_IRQChannel=USART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
NVIC_Init(&NVIC_InitStruct);
USART_Init(USART1,&USART_InitStruct);
USART_Cmd(USART1, ENABLE);
USART_ITConfig(USART1,USART_IT_RXNE, ENABLE);
}
void My_Usart_Send_Byte(USART_TypeDef* USARTx,uint16_t Data)
{
USART_SendData(USARTx, Data);
while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE)==RESET);
}
void My_Usart_Send_Sting(USART_TypeDef* USARTx,char* str)
{
uint16_t i=0;
do
{
My_Usart_Send_Byte(USARTx,*(str+i));
i++;
}while(*(str+i)!='\0');
while(USART_GetFlagStatus(USARTx,USART_FLAG_TC)==RESET);
}
int fputc(int ch,FILE *p)
{
USART_SendData(USART1,(u8)ch);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
return ch;
}
void USART1_IRQHandler()
{
char str;
if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)
{
str=USART_ReceiveData(USART1);
printf("receive:%c \r\n",str);
if(str=='0')
{
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
printf("led open \r\n");
}
if(str=='1')
{
GPIO_SetBits(GPIOA,GPIO_Pin_1);
printf("led close \r\n");
}
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
}
main.c文件
#include "stm32f10x.h"
#include "main.h"
#include "led.h"
#include "usart.h"
#include "stdio.h"
int main()
{
myusart_init();
My_Usart_Send_Byte(USART1,'A');
My_Usart_Send_Byte(USART1,'B');
My_Usart_Send_Byte(USART1,'C');
My_Usart_Send_Sting(USART1,"wuyong \r\n");
LED_Init();
GPIO_SetBits(GPIOA,GPIO_Pin_1);
while(1)
{
}
}
串口接收到0,灯亮
串口接收到1,灯灭