STM32-串口通信详解总结

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个停止位:

起始位数据位数据位停止位
1bit5 ~ 8bit0 ~ 1 bit1 ~ 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);		//使能afio时钟
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);		//使能GPIOC时钟
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
		RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);		//使能串口5时钟

6.2 串口复位(这一步不是必须的)。调用函数:USART_DeInit();

		USART_DeInit(UART5);

6.3 GPIO外设功能下的端口模式设置。调用函数:GPIO_Init();

		GPIO_InitTypeDef GPIO_InitStructure;

		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;					//串口5输入脚上拉
		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;					//串口5输出脚配成多功能上下拉
		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);
 
		 /* 配置 USART 为中断源 */
		 NVIC_InitStructure.NVIC_IRQChannel = UART5_IRQn;//
		 /* 抢断优先级为 1 */
		 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
		 /* 子优先级为 1 */
		 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
		 /* 使能中断 */
		 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 		/* 初始化配置 NVIC */
		 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);						//关闭发送中断
	}
	……
	//处理数据
}

注:如有问题,欢迎大家指出,谢谢!

  • 11
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值