文章以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位数据,传输速度比较慢;并行传输是指多个数据位同时传输,每次可以传输多个二进制位,传输速度比串行传输快,但是需要使用更多的电线或光纤来传输数据。
适用于陶晶驰串口屏的上位机开发软件,无需代码即可完成屏幕内容DIY。
这里可以选择引入图片、字库、动画等等,
引入字库方法是:点击左上角工具:
选择字库制作,弹出该界面,可自定义字高、编码方式和字体:
点击所有语言,只选择CJK表意字符(目的是减少字符占用空间),
自定义字库名称,保存后在左下角就会出现保存的字库。
引入图片:
较为简单,只需要点击左下角的加号,把你文件夹中的图片添加进来就可以。
这是串口屏使用的核心。这里以一个实例:串口屏设置按钮,发送特定信息给STM32,STM32接收后,根据指令控制LED亮灭。
首先是HMI部分:
界面如图,其中b0控件是按钮,t2文本控件,他的显示(熄灭或点亮)会随着LED状态而改变。
这里,对LED按钮的弹起事件编写:printh 01,即按下串口屏的LED按钮并弹起后,将通过串口发送16进制的数据:0x01到STM32中去。对于t2文本控件,不做编写,t2控件的改变是接收STM32串口发送来的字符串数据而改变的,这是在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之间的串口通信方式,以及实物的实验效果。