stm32项目之uart通信

0.前言

不懂协议的同学,可以看看下面这个博客,可以帮助你简单了解一下通信协议的一些要点。

(3条消息) stm32之通信原理_@seven@的博客-CSDN博客

1.串口单双功问题

485、422、232都是全双工的。但是实际使用过程中我们一直是把485设计成半双工使用。其实485类似422,只不过在个别参数上比422更加灵活,也就是说485可以兼容422(一般情况下),但反过来就不一定了。485如果接成四线就是全双工,如果把输入和输出并接,并且只接两条线那么就是半双工的了。因为实际使用半双工的比较多。另外好多芯片内部就把输入和输出并接了。

1.1.USB和串口的区别

1.2.为什么有了USB还要用串口?

        ① 串口成本低,而且更主要的是,COM口对开发者和使用者而言,不需要去专门开发和安装驱动,这样又省了软件成本。

        ② COM虽然速度慢,使用繁杂,但它的抗干扰能力是远远超过USB的,在同等高频干扰情况下,使用USB通讯的设备经常会死机卡住,但COM口就不会。现在很多工业上还是会用COM口,就是这个原因。

        ③ 在传输速度要求不高的情况下,很多设备还是会保留COM口,只是COM口用起来真的没USB的方便。

1.3.如何理解串口,UART, RS232, RS485?

串口简单来说就是串行端口,什么是串行?与并行相对应,串行就是将一条数据线分时复用,在不同的时刻传递不同的数据,从而达到减少数据线的目的。如要发送0xAA=0b10101010,如果用8根数据线的并口,只需发一次即可,数据线7到0分别为:10101010。而如果用一根线,我需要先发0,然后发1,然后发0...最后发1。总共需要发8次。

        按这个定义,UART(TTL电平),232,485都是串口,它们都是在同一时间发送一位,区别是它们的传输协议不同。

UART特指单片机的UART端口,使用TTL电平:

标准TTL输入高电平最小2V,输出高电平最小2.4V,典型值3.4V,输入低电平最大0.8V,输出低电平最大0.4V,典型值0.2V。

RS232:

逻辑1(MARK)=-3V~-15V,逻辑0(SPACE)=+3~+15V

RS485采用差分方式传输:

逻辑"1”以两线间的电压差为+(2~6)V表示;逻辑"0"以两线间的电压差为-(2~6)V表示

 2.编程

2.1.USART 初始化结构体

typedef struct {
uint32_t USART_BaudRate; // 波特率
uint16_t USART_WordLength; // 字长
uint16_t USART_StopBits; // 停止位
uint16_t USART_Parity; // 校验位
uint16_t USART_Mode; // USART 模式
uint16_t USART_HardwareFlowControl; // 硬件流控制
} USART_InitTypeDef;

1) USART_BaudRate:波特率设置。一般设置为2400、9600、19200、115200。标准库函数会根据设定值计算得到USARTDIV 值,从而设置USART_BRR 寄存器值。
2) USART_WordLength:数据帧字长,可选8 位或9 位。它设定USART_CR1 寄存器的M 位的值。如果没有使能奇偶校验控制,一般使用8 数据位;如果使能了奇偶校验则一般设置为9 数据位。
3) USART_StopBits:停止位设置,可选0.5 个、1 个、1.5 个和2 个停止位,它设定USART_CR2
寄存器的STOP[1:0] 位的值,一般我们选择1 个停止位
4) USART_Parity:奇偶校验控制选择,可选USART_Parity_No(无校验)USART_Parity_Even(偶
校验) 以及USART_Parity_Odd(奇校验),它设定USART_CR1 寄存器的PCE 位和PS 位的值。
5) USART_Mode:USART 模式选择,有USART_Mode_Rx 和USART_Mode_Tx,允许使用逻辑或运算选择两个,它设定USART_CR1 寄存器的RE 位和TE 位。
6) USART_HardwareFlowControl:硬件流控制选择,只有在硬件流控制模式才有效,可选有􀀀 使
能RTS、􀀀 使能CTS、􀀀 同时使能RTS 和CTS、􀀀 不使能硬件流。当使用同步模式时需要配置SCLK 引脚输出脉冲的属性,标准库使用一个时钟初始化结构体USART_ClockInitTypeDef 来设置,该结构体内容也只有在同步模式才需要设置。 

2.1.USART 时钟初始化结构体

typedef struct {
uint16_t USART_Clock; // 时钟使能控制
uint16_t USART_CPOL; // 时钟极性
uint16_t USART_CPHA; // 时钟相位
uint16_t USART_LastBit; // 最尾位时钟脉冲
} USART_ClockInitTypeDef;

 1) USART_Clock:同步模式下SCLK 引脚上时钟输出使能控制,可选禁止时钟输出(USART_
Clock_Disable) 或开启时钟输出(USART_Clock_Enable);如果使用同步模式发送,一般都
需要开启时钟。它设定USART_CR2 寄存器的CLKEN 位的值。
2) USART_CPOL:同步模式下SCLK 引脚上输出时钟极性设置,可设置在空闲时SCLK 引脚为低
电平(USART_CPOL_Low) 或高电平(USART_CPOL_High)。它设定USART_CR2 寄存器的CPOL
位的值。
3) USART_CPHA:同步模式下SCLK 引脚上输出时钟相位设置,可设置在时钟第一个变化沿捕
获数据(USART_CPHA_1Edge) 或在时钟第二个变化沿捕获数据。它设定USART_CR2 寄存器的
CPHA 位的值。USART_CPHA 与USART_CPOL 配合使用可以获得多种模式时钟关系。
4) USART_LastBit:选择在发送最后一个数据位的时候时钟脉冲是否在SCLK 引脚输出,可以是
不输出脉冲(USART_LastBit_Disable)、输出脉冲(USART_LastBit_Enable)。它设定USART_CR2 寄存器的LBCL 位的值。

2.2.硬件

开发板上面硬件比较多,我们这里使用uart1.

 3.编程

要点:

1) 使能RX 和TX 引脚GPIO 时钟和USART 时钟;
2) 初始化GPIO,并将GPIO 复用到USART 上;
3) 配置USART 参数;
4) 配置中断控制器并使能USART 接收中断;
5) 使能USART;
6) 在USART 接收中断服务函数实现数据接收和发送。

不管是初始化GPIO,还是NVIC(uart中断),还是uart结构体,这些都是模板,我已经在另一篇博客提取出来了,需要的小伙伴可以去拿。

(4条消息) stm32 库函数开发初始化模板_@seven@的博客-CSDN博客

3.1.初始化GPIO

  	GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
	//USART1_TX   GPIOA.9
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
   
  //USART1_RX	  GPIOA.10初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  

3.2.初始化NVIC

    NVIC_InitTypeDef NVIC_InitStructure;
//Usart1 NVIC 配置
  	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器

3.3.初始化uart

   USART_InitTypeDef USART_InitStructure;
//USART 初始化设置

	USART_InitStructure.USART_BaudRate = bound;//串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	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(USART1, &USART_InitStructure); //初始化串口1
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断 中断有很多种,可以看看手册
  USART_Cmd(USART1, ENABLE);                    //使能串口1 

3.4uart中断服务函数

因为uart使用了中断,这里使用的是接受中断,所以需要我们去写中断服务函数。

//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   	
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记	 

void USART1_IRQHandler(void)                	//串口1中断服务程序
	{
	u8 Res;
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
		{
		Res =USART_ReceiveData(USART1);	//读取接收到的数据
		
		if((USART_RX_STA&0x8000)==0)//接收未完成
			{
			if(USART_RX_STA&0x4000)//接收到了0x0d
				{
				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
				}
			else //还没收到0X0D
				{	
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
					{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
					}		 
				}
			}   		 
     } 
} 

 其实就是对接收的二进制数据流进行判断,是否为整包数据,看不懂也没事,这种协议是标准,提出这个协议的公司帮我们写好了,我们会使用就可以了。具体的代码可以去看看野火或者正点原子的。

代码:后期会整理比较好的代码再上传。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用中的代码展示了一个基于STM32UART串口通信的示例程序。在这个示例中,首先通过引入相关头文件,包括"stm32f10x.h"和"bsp_usart.h"来实现对USART的初始化配置。然后,在主函数main中,通过调用USART_Config函数来进行USART的初始化配置,包括设置波特率、数据位数、停止位数等参数。接着使用Usart_SendString函数向串口发送一串字符串,并通过printf函数向终端输出一段欢迎信息。最后,通过一个无限循环来保持程序的运行。 引用和引用提供了更具体的关于初始化和配置串口的过程和代码说明。在这些引用中,首先要进行相关的时钟使能和GPIO配置,然后设置引脚的复用模式,接着进行串口参数的初始化配置,包括波特率、数据位数、停止位数等。如果需要开启中断,则需要进行中断配置和中断处理函数的编写。最后,使能串口以开始通信。 综上所述,如果您需要实现STM32UART串口通信,可以参考以上提供的代码和过程。请根据自己的具体需求进行相应的配置和修改。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [STM32——USART接发通信实验代码解析(适合野火stm32f103ZE)](https://blog.csdn.net/m0_57396609/article/details/120387284)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [(十三)STM32——串口通信UART)](https://blog.csdn.net/weixin_66578482/article/details/126270118)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值