一、什么是串口
区别于并口,指的是用于逐位传输数据的通信接口的总称。
二、帧格式和波特率
1.帧格式
(1)空闲:高电平
(2)非空闲:有如下类型的帧:
- 起始位 (Start Bit):
起始位通常是一个逻辑低电平,用于指示一个新字符的开始。 - 数据位 (Data Bits):
数据位是实际要传输的信息位,可以是5到8位不等,最常见的配置是8位。 - 奇偶校验位 (Parity Bit)(可选):
这是一个用于错误检测的位,可以是无校验(None)、奇校验(Odd)、偶校验(Even)、标记校验(Mark)或空位校验(Space)。 - 停止位 (Stop Bit):
停止位是一个或多个逻辑高电平,用于指示一个字符的结束。停止位可以是0.5、1位、1.5位或2位。通常是1位。
他们的关系如下图:
常用的帧格式为:1位起始位+8位数据位(一个字节)+无校验位+1位停止位 即一帧10个bit
2.波特率
官方说法:
在串口通信中,波特率(Baud rate)是一个非常重要的参数,它表示数据传输的速率。具体来说,波特率定义了信号单位时间内载波调制状态改变的次数,通常用作衡量串行通信中数据传输速度的标准。
在数字通信领域,一个“波特”(Baud)是指每秒的信号变化次数。对于大多数现代数字通信系统而言,一次信号变化通常对应一位(bit)的数据传输。因此,在很多情况下,波特率与比特率(bits per second, bps)是等同的,尤其是在每个信号变化只代表一位信息的情况下。
通常来讲:
对于串口通信,波特率代表每秒传输的bit的数量。
如常用的9600波特率代表了一秒钟可以传输9600个bit的信息。即信号宽度为0.104ms,如下图:
其他常用的波特率如:19200、38400、115200等。
注意:9600波特率包含了起始位数据位校验位和终止位所有的信息,不仅仅是数据位。
2.硬件和接口标准
(1)硬件
对于芯片(soc和mcu)来说,芯片内部集成了uart(异步通信)和usart(支持同步和异步通信)模块。其直接产生的为ttl电平。
(2)接口标准
串口通信常用的电气标准有ttl、rs232和rs485、rs422等。
注:RTS (Request to Send):请求发送 CTS (Clear to Send):清除发送
三.常见问题
(1)如何判断串口已经发送完成
串口通信没有时序控制,如何判断串口数据已经发送完成了呢?
- 通过中断:
1)空闲中断(IDL Interrupt)
当USART检测到输入线上连续出现一定数量的空闲状态(通常为10个连续的空闲位)时,会触发此中断。
伪代码:
int main(void)
{
//初始化硬件。。。。。
__HAL_UART_ENABLE_IDLELINEDETECTION(&huart2); //使能空闲线检测中断
HAL_UART_EnableIT(&huart2, UART_IT_IDLE); // 使能USART中断
}
void USART2_IRQHandler(void)
{
// 处理空闲线检测中断
if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_IDLE))
{
__HAL_UART_CLEAR_FLAG(&huart2, UART_FLAG_IDLE); // 清除中断标志
HAL_UART_IRQHandler(&huart2); // 调用中断处理函数
}
}
void HAL_UART_IdleLineCpltCallback(UART_HandleTypeDef *huart)
{
if (huart == &huart2)
{
// 空闲线检测完成
// 这里可以添加处理逻辑
}
}
2)非空中断 (RXNE Interrupt)
当USART接收到新的数据并且接收数据寄存器非空(RXNE,Receive Data Register Not Empty)时,会触发此中断。
伪代码:
int main(void)
{
//初始化硬件。。。。。
// 使能接收数据寄存器非空中断
HAL_UART_EnableIT(&huart2, UART_IT_RXNE);
}
void USART2_IRQHandler(void)
{
// 处理接收数据寄存器非空中断
if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_RXNE))
{
uint8_t data = 0;
// 读取接收的数据
data = HAL_UART_Receive_IT(&huart2, (uint8_t *)&data, 1);
// 检查接收缓冲区是否已满
if (receivedLen < sizeof(receivedData))
{
receivedData[receivedLen++] = data;
}
// 清除中断标志
__HAL_UART_CLEAR_RXNEFLAG(&huart2);
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart == &huart2)
{
// 接收完成
// 可以在这里添加额外的操作,例如打印接收到的数据
// 或者重置接收长度以准备下一次接收
receivedLen = 0; // 重置接收长度
}
}
- 通过时间
对于一些相关中断的单片机,可以通过时间来判断,即通过波特率计算每个信号的具体时间,如9600波特率信号的时间为0.104ms,则可以建立软件定时器,在3~5个信号时间内未收到新数据则视为接收完成
- 通过特定字符或者长度
即通过协议约定的特定尾帧进行判别,或进行长度判别,当检测到数据为结束尾帧或者数据长度超过阈值时,视为接收完成。