STM32(2)-串口通讯实际应用:串口屏

文章以UART基础知识和串口屏实际应用来说明串口的作用。

文章目录

  • 前言
  • 一、UART是什么?
  • 二、USART HMI
    • 1.引入字库和图片库
    • 2.控件与指令集的使用
    • (1)控件的事件编写
    • (2)STM32串口程序编写
  • 总结


前言

一、UART是什么?

UART是通用异步收发传输器(Universal Asynchronous Receiver/Transmitter)的缩写,是一种串行通讯协议,通常用于将计算机或微处理器与其他设备(如传感器、模块、显示器等)进行通信。UART可以将数据以一定速率和格式(如数据位、校验位、停止位等)从发送器传输到接收器,从而实现双方的数据交换。常见的串口通讯协议如RS-232、RS-485等都是基于UART的。
异步是什么意思?
异步通信是指在通信过程中,数据的传输不依赖于时钟信号的同步。在异步通信中,数据是以字符为单位进行传输的,每个字符之间可能存在不等的时间间隔。通常使用UART协议来实现异步通信,其中发送端和接收端通过约定好的波特率、数据位、校验位、停止位等参数来进行通信。相对于同步通信,异步通信具有传输速率不受限制、成本低廉等优点,但也存在传输错误率高等缺点。
USART
USART是通用同步/异步收发传输器(Universal Synchronous/Asynchronous Receiver/Transmitter)的缩写,包含了UART的异步传输和同步传输两种模式。在异步模式下,USART与UART的通讯方式相同,支持异步串行数据传输,数据以字符为单位进行传输,每个字符之间可能存在不等的时间间隔;在同步模式下,USART可以将数据与时钟信号同步传输,数据和时钟信号的传输速率完全一致,并且不需要停止位,在传输速率较高的应用场景中,同步模式更为常用。USART可以支持多种数据格式和传输速率,具有较高的通信灵活性和可靠性
并行与串行
串行传输是指数据以一位一位的方式进行传输,每次只能传输1位数据,传输速度比较慢;并行传输是指多个数据位同时传输,每次可以传输多个二进制位,传输速度比串行传输快,但是需要使用更多的电线或光纤来传输数据。

二、USART HMI

适用于陶晶驰串口屏的上位机开发软件,无需代码即可完成屏幕内容DIY。
STM32(2)-串口通讯实际应用:串口屏_第1张图片

1.引入字库和图片库

STM32(2)-串口通讯实际应用:串口屏_第2张图片
这里可以选择引入图片、字库、动画等等,
引入字库方法是:点击左上角工具:
STM32(2)-串口通讯实际应用:串口屏_第3张图片
选择字库制作,弹出该界面,可自定义字高、编码方式和字体:
STM32(2)-串口通讯实际应用:串口屏_第4张图片
点击所有语言,只选择CJK表意字符(目的是减少字符占用空间),
STM32(2)-串口通讯实际应用:串口屏_第5张图片
自定义字库名称,保存后在左下角就会出现保存的字库。
引入图片:
较为简单,只需要点击左下角的加号,把你文件夹中的图片添加进来就可以。
STM32(2)-串口通讯实际应用:串口屏_第6张图片

2.控件与指令集的使用

这是串口屏使用的核心。这里以一个实例:串口屏设置按钮,发送特定信息给STM32,STM32接收后,根据指令控制LED亮灭。
首先是HMI部分:
STM32(2)-串口通讯实际应用:串口屏_第7张图片
界面如图,其中b0控件是按钮,t2文本控件,他的显示(熄灭或点亮)会随着LED状态而改变。

(1)控件的事件编写

这里,对LED按钮的弹起事件编写:printh 01,即按下串口屏的LED按钮并弹起后,将通过串口发送16进制的数据:0x01到STM32中去。对于t2文本控件,不做编写,t2控件的改变是接收STM32串口发送来的字符串数据而改变的,这是在stm32中编写。
STM32(2)-串口通讯实际应用:串口屏_第8张图片

(2)STM32串口程序编写

这里参考CSDN一位大佬的程序:首先进行串口配置(串口初始化),使用stm32的USART3,所以硬件连接应为
RX------------PB10
TX------------PB11
先看头文件:

#ifndef __USART3_H
#define __USART3_H
#include "sys.h" 

void HMISendb(u8 k)	;
void HMISends(char *buf1);

void uart3_init(u32 bound);
void USART3_IRQHandler(void);     	//串口1中断服务程序
#endif

这里声明了四个函数:
1.uart3_init(u32 bound)

void uart3_init(u32 bound)
{
	//GPIO端口设置
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//时钟GPIOB、USART3
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
	
	//USART1_TX   PB10
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	//USART1_RX	  PB11
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOB, &GPIO_InitStructure);  
	
	  //Usart1 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
	//USART 初始化设置
	USART_InitStructure.USART_BaudRate = bound;//一般设置为9600;
	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(USART3, &USART_InitStructure);
	
	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启中断
	USART_Cmd(USART3, ENABLE);                    //使能串口 
}

和我文章第一讲的串口初始化基本一样,主要是对GPIO、USART、NVIC的配置。

2.USART3_IRQHandler(void)

void USART3_IRQHandler(void)   
{
	u8 Res;
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
		{
		Res =USART_ReceiveData(USART3);	//读取接收到的数据
			
		if(Res==0x01)  LED_Flag=1;//若接收到数据为0x01,则LED标识符设置为1
        } 
}

函数中首先判断是否接收到数据(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET),如果接收到了数据,就调用USART_ReceiveData函数读取接收到的数据。

接下来,使用if-else语句判断接收到的数据是哪个命令。如果接收到的数据是0x01,就将LED_Flag置为1,表示LED为高电平点亮状态。
注意,这里要设置一个全局变量,用以判断LED当前状态:

u8 LED_Flag=0;

3.HMISendb(u8 k)

void HMISendb(u8 k)		         //字节发送函数
{		 
	u8 i;
	 for(i=0;i<3;i++)
	 {
	 if(k!=0)
	 	{
			USART_SendData(USART3,k);  //发送一个字节
			while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET){};//等待发送结束
		}
	 else 
	 return ;

	 } 
} 

该函数中使用了for循环,连续发送3次同样的字节。这是因为在HMI通信中,0xff是作为结束发送的信息的,也就是说,必须连续发送3次0xff作为结束传输的标志。
具体而言,函数中使用了USART_SendData函数向USART3发送一个字节(k),然后使用while循环等待发送结束(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET)。在发送结束后,函数返回。如果传入的字节k为0,则直接返回,不进行发送。

*HMISends(char buf1)

 void HMISends(char *buf1)		  //字符串发送函数
{
	u8 i=0;
	while(1)
	{
	 if(buf1[i]!=0)
	 	{
			USART_SendData(USART3,buf1[i]);  //发送一个字节
			while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET){};//等待发送结束
		 	i++;
		}
	 else 
	 return ;

		}
	}

函数中使用了while循环,不断发送字符串的每一个字符,直到遇到字符串结尾(‘\0’)为止。具体而言,函数中使用了USART_SendData函数向USART3发送一个字符(buf1[i]),然后使用while循环等待发送结束(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET)。在发送结束后,i自增1,继续发送下一个字符。如果遇到字符串结尾,则直接返回,不进行发送。

总结

本文仅对串口和HMI的基本设计进行了说明,下一篇文章我将写出STM32主程序,并详细分析STM32与HMI之间的串口通信方式,以及实物的实验效果。

你可能感兴趣的:(stm32,单片机,嵌入式硬件)