1. 串口通信方式
UART:universal asynchronous receiver and transmitter 通用异步收/发器,即串行异步全双工收发器。 USART: universal synchronous asynchronous receiver and transmitter 通用同步/异步收/发器,即串行异步/同步全双工收发器 说明: (1) 串行通信和并行通信区别:
串行通信 | 每次同时只能传输 1 个二进制位 |
---|
并行通信 | 数据各个位同时传输 |
(2)同步和异步的区别:
同步通信 | 发送方和接收方按照同一个时钟节拍工作,所以需要时钟信号 |
---|
异步通信 | 发送方和接收方没有统一的时钟节拍,各自按照自己的节拍工作 |
(3) 单工、半双工、全双工的区别:
单工 | 数据传输只支持数据在一个方向上传输 |
---|
半双工 | 允许数据在两个方向上传输。但是,在同一时刻,只允许数据在一个方向上传输 | 全双工 | 允许数据同时在两个方向上传输 |
2.RS232 电平和 TTL 电平(都是全双工)
电平类型 | 电压与逻辑电平关系 |
---|
TTL(单片机电平) | 逻辑1:2.4V ~ 5V ; 逻辑0: 0V ~ 0.5V | RS232(如电脑) | 逻辑1:-15V ~ -3V; 逻辑0: 3V ~ 15V |
注意:单片机要和PC通信时,需要电平转换芯片如CH340。
3.波特率
3.1 波特率:等同比特率,表示每秒钟传送的二进制位数,单位是比特每秒(bit/s)。 3.2 常见波特率:9600 、19200、115200
如串口的波特率为9600,表示1秒中可传输9600个bit; 其中,传输1个bit需要104us(计算1000ms/9600 = 104us)。
4.通信协议
4.1 串口传输的数据包格式
每个数据包包含1个起始位,5至9个数据位,可选的奇偶校验位和1或1.5或2个停止位:
起始位 | 数据位 | 数据位 | 停止位 |
---|
1bit | 5 ~ 8bit | 0 ~ 1 bit | 1 ~ 2bit | 低电平(下降沿) | 先发送低位,再发送高位 | 奇偶校验或无校验 | 高电平 |
注意: ① 空闲状态:高电平,此时无数据传输
②奇偶校验: 奇校验:如果数据位中“1”的数目是偶数,则校验位为高电平1, 如果数据位中“1”的数目是奇数,则校验位为低电平0 偶校验:如果数据位中“1”的数目是奇数,则校验位为高电平1, 如果数据位中“1”的数目是偶数,则校验位为低电平0
③停止位配置:表示传输的结束,并且提供计算机校正时钟同步的机会。 1个停止位:停止位位数的默认值。 2个停止位:可用于常规USART模式、单线模式以及调制解调器模式。 0.5个停止位:在智能卡模式下接收数据时使用。 1.5个停止位:在智能卡模式下发送和接收数据时使用。
④编程可配置的数据长度:8位或者9位(包含校验位),如9位是指8bit数据+1bit奇偶校验。
传输示例: 波特率115200,无校验,1个停止位,数据长度为8,传输数据0x55 0xAA 0x03,示波器波形如下:
4.2 STM32串口框图
说明: 如上框图所示,在接收移位寄存器、发送移位寄存器还有一个进入的箭头,分别连接到接收器控制、发送器控制。而这两者连接的又是接收器时钟、发送器时钟。也就是说,异步通信尽管没有时钟同步信号,但是在串口内部,是提供了时钟信号来进行控制的。接收器时钟和发送器时钟又被连接到同一个控制单元,也就是说它们共用一个波特率发生器。 读操作:数据从RX进入到接收移位寄存器,后进入到接收数据寄存器,最终供CPU或者DMA来进行读取; 写操作:数据从CPU或者DMA传递过来,进入发送数据寄存器,后进入发送移位寄存器,最终通过TX发送出去。
STM32与外部设备串口通信过程:
5.STM32 串口相关寄存器
参考《STM32F10x参考手册》
6.串口操作的一般步骤
代码示例:配置串口5 6.1 GPIO时钟使能,串口时钟使能。调用函数:RCC_APB2PeriphClockCmd()(可以参阅:【STM32】 STM32端口复用和重映射(AFIO辅助功能时钟) 的部分内容);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);
6.2 串口复位(这一步不是必须的)。调用函数:USART_DeInit();
USART_DeInit(UART5);
6.3 GPIO外设功能下的端口模式设置。调用函数:GPIO_Init();
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
6.4 串口参数初始化。调用函数:USART_Init();
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = p_baudrate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(UART5, &USART_InitStructure);
6.5 开启中断并且初始化NVIC(如果需要开启中断才需要这个步骤)。调用函数:NVIC_Init();USART_ITConfig();
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_ITConfig(UART5, USART_IT_RXNE, ENABLE);
USART_ITConfig(UART5, USART_IT_TXE, ENABLE);
6.6 使能串口。调用函数:USART_Cmd();
USART_Cmd(UART5, ENABLE);
6.7 编写中断处理函数。调用函数:USARTx_IRQHandler();
void UART5_IRQHandler(void)
{
if(USART_GetITStatus(UART5, USART_IT_RXNE) != RESET)
{
uart5_recv_int_handle();
}
if(USART_GetITStatus(UART5, USART_IT_TXE) != RESET)
{
uart5_send_int_handle();
}
}
6.8 串口数据收发。调用函数:USART_SendData();USART_ReceiveData();
void uart5_recv_int_handle(void)
{
U8 m_data;
m_data = USART_ReceiveData(UART5);
……
}
void uart5_send_int_handle(void)
{
U8 m_data;
if(需要发送数据)
{
USART_SendData(UART5, m_data);
}
else
{
USART_ITConfig(UART5, USART_IT_TXE, DISABLE);
}
……
}
注:如有问题,欢迎大家指出,谢谢!
|