参考教程:【STM32入门教程-2023版 细致讲解 中文字幕】
通信接口
通信接口是不同设备或系统之间进行通信时使用的物理连接和电气特性的规范。它定义了数据的传输方式、信号的传输速率、传输距离和电气标准等。通信接口允许设备之间交换信息和进行数据传输。
- 通信的目的:将一个设备的数据传送到另一个设备,扩展硬件系统
- 通信协议:制定通信的规则,通信双方按照协议规则进行数据收发
常用通信协议
串口通信
- 串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信
- 单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大地扩展了单片机的应用范围,增强了单片机系统的硬件实力
串口通信硬件连接
- 简单双向串口通信有两根通信线(发送端TX和接收端RX)
- TX与RX要交叉连接
- 当只需单向的数据传输时,可以只接一根通信线
- 当电平标准不一致时,需要加电平转换芯片
电平标准
电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用的电平标准有如下三种:
- TTL电平:+3.3V或+5V表示1,0V表示0
- RS232电平:-3~-15V表示1,+3~+15V表示0
- RS485电平:两线压差+2~+6V表示1,-2~-6V表示0(差分信号)
串口参数及时序
- 波特率:串口通信的速率,波特率表示单位时间内传送的码元符号的个数,它是对符号传输速率的一种度量,串口通信使用二进制电平信号,波特率与比特率在数值上相等
- 起始位:标志一个数据帧的开始,固定为低电平
- 数据位:数据帧的有效载荷,1为高电平,0为低电平,低位先行
- 校验位:用于数据验证,根据数据位计算得来
- 停止位:用于数据帧间隔,固定为高电平
STM32外设USART
- USART(Universal Synchronous/Asynchronous Receiver/Transmitter)通用同步/异步收发器
- USART是STM32内部集成的硬件外设,可根据数据寄存器的一个字节数据自动生成数据帧时序,从TX引脚发送出去,也可自动接收RX引脚的数据帧时序,拼接为一个字节数据,存放在数据寄存器里
- 自带波特率发生器,最高达4.5Mbits/s
- 可配置数据位长度(8/9)、停止位长度(0.5/1/1.5/2)
- 可选校验位(无校验/奇校验/偶校验)
- 支持同步模式、硬件流控制、DMA、智能卡、IrDA、LIN
- STM32F103C8T6 USART资源: USART1、 USART2、 USART3
USART基本结构
数据帧
波特率发生器
- 发送器和接收器的波特率由波特率寄存器BRR里的DIV确定
- 计算公式:波特率 = fPCLK2/1 / (16 * DIV)
数据模式
- HEX模式/十六进制模式/二进制模式:以原始数据的形式显示
- 文本模式/字符模式:以原始数据编码后的形式显示
代码实例
#include "stm32f10x.h" // Device header
uint16_t Serial_ReceiveData = 0;
uint8_t Serial_ReceiveFlag = 0;
void Serial_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
GPIO_InitTypeDef GPIOA_InitStructure;
GPIOA_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIOA_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIOA_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIOA_InitStructure);
GPIOA_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIOA_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA,&GPIOA_InitStructure);
USART_InitTypeDef USART1_InitStructure;
USART1_InitStructure.USART_BaudRate = 115200;
USART1_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART1_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART1_InitStructure.USART_Parity = USART_Parity_No;
USART1_InitStructure.USART_StopBits = USART_StopBits_1;
USART1_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1,&USART1_InitStructure);
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
USART_ClearFlag(USART1,USART_FLAG_RXNE);
USART_Cmd(USART1,ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
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);
}
void Serial_SendByte(uint16_t Byte)
{
USART_SendData(USART1,Byte);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
}
void Serial_SendArray(uint16_t *Array,uint16_t n)
{
uint16_t i;
for(i = 0;i < n;i++)
{
Serial_SendByte(Array[i]);
}
}
void Serial_SendString(char *String)
{
uint16_t i;
for(i = 0;String[i] != '\0';i++)
{
Serial_SendByte((uint16_t)String[i]);
}
}
uint16_t Serial_GetReceiveData(void)
{
return Serial_ReceiveData;
}
uint8_t Serial_GetReceiveFlag(void)
{
return Serial_ReceiveFlag;
}
void Serial_ResetReceiveFlag(void)
{
Serial_ReceiveFlag = 0;
}
void Serial_SetReceiveFlag(void)
{
Serial_ReceiveFlag = 1;
}
/*
void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1,USART_IT_RXNE) == SET)
{
Serial_ReceiveData = USART_ReceiveData(USART1);
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
}
*/