基于HMI串口屏的协议(STM32)
提示:
硬件:STM32H750VBT6、USART_HMI(3.5寸基本型)(TJC4832T035_011X)
官方资料网站:HMI
文章目录
前言
一、协议
提示:此处仅作为演示,完整版在文章末尾会有下载方式
注:一帧完整的数据一共有7Byte
,所以在发送功能类数据时需要把其他位用0x00
补全。
数据的缩放等级有0x00
、0x01
、0x02
三个等级,分别对应数据扩大0倍
、数据扩大10倍
、数据扩大100倍
。数据采用低端模式,即低字节在地址的低地址中,(例如:发送0x43AA
,则协议中的数据位的顺序是AA
43
,所以在单片机解析数据中需要注意)。STM32
也是采用小端模式。
二、协议示例
在调试的时候可以把这些数据采用上位机的形式发送给单片机。
三、协议程序
1、Hmi_Agreements.c
代码如下(示例):
#include "hmi_agreement.h"
#include "stdlib.h"
#include "stdio.h"
_usarthmi UHMI;
// _User HMI_User; //用户数据
/******************************
**** 函数功能:HMI复位
**** 形参: 无
**** 返回值: 无
*******************************/
void HMI_Usart_Rest(void) //显示屏复位
{
uint8_t End_Bit[3] = {0xff,0xff,0xff};
uint8_t Rest[4] = "rest";
HAL_UART_Transmit(&uart, (uint8_t*)&Rest, 4, 0xffff); //发送数据
HAL_UART_Transmit(&uart, (uint8_t*)&End_Bit, 3, 0xffff); //发送结束位
}
/******************************
**** 函数功能:刷新HMI界面
**** 形参: Page:需要刷新的页面(字符串形式)
**** 返回值: 无
*******************************/
void HMI_Usart_Refresh(uint8_t *Page) //刷新页面
{
uint8_t End_Bit[3] = {0xff,0xff,0xff};
uint8_t Head[5] = "page ";
uint8_t *str;
uint16_t size = strlen((char*)Page);
str = (uint8_t*)malloc(size + 5); //申请内存
if(str != NULL) //申请内存成功
{
// sprintf((char*)str,"%s %s",Head,Page);
memcpy(str,Head,5);
memcpy(str + 5,Page,size);
HAL_UART_Transmit(&uart, (uint8_t*)str, size + 5, 0xffff); //发送数据
HAL_UART_Transmit(&uart, (uint8_t*)&End_Bit, 3, 0xffff); //发送结束位
free(str); //释放内存
}
}
// /******************************
// **** 函数功能:发送数据到HMI屏幕
// **** 形参: SData:需要发送的数值(字符串形式)
// **** 返回值: 无
// *******************************/
// void HMI_Usart_SendDataValue(uint8_t *SData) //串口发送数值数据到HMI屏幕
// {
// uint8_t End_Bit[3] = {0xff,0xff,0xff};
// HAL_UART_Transmit(&uart, (uint8_t*)&SData, strlen((char*)SData), 0xffff); //发送数据
// HAL_UART_Transmit(&uart, (uint8_t*)&End_Bit, sizeof(End_Bit), 0xffff); //发送结束位
// }
/******************************
**** 函数功能:隐藏或显示控件
**** 形参: Obj:控件名字,State:状态(1,显示。0,隐藏)
**** 返回值: 无
*******************************/
void HMI_Usart_ShowHideobj(uint8_t *Obj,uint8_t State) //对指定的控件的显示和隐藏进行操作
{
uint8_t End_Bit[3] = {0xff,0xff,0xff};
uint8_t Sho[4] = "vis ";
uint8_t *str;
uint16_t size = sizeof(Obj);
str = (uint8_t*)malloc(size + 6);
if(str != NULL)
{
memcpy(str,Sho,4);
memcpy(str + 4,Obj,size);
memcpy(str + 4 + size,(uint8_t*)",",1);
if(State)
memcpy(str + 5 + size,(uint8_t*)"1",1);
else
memcpy(str + 5 + size,(uint8_t*)"0",1);
HAL_UART_Transmit(&uart, (uint8_t*)str, size + 6, 0xffff); //发送数据
HAL_UART_Transmit(&uart, (uint8_t*)&End_Bit, 3, 0xffff); //发送结束位
free(str); //释放内存
}
}
/******************************
**** 函数功能:发送字符数据到HMI
**** 形参: Head:控件的名字,SData:显示的字符
**** 返回值: 无
*******************************/
void HMI_Usart_SendDataText(uint8_t *Head, uint8_t *SData) //串口发送字符数据到HMI屏幕
{
uint8_t End_Bit[3] = {0xff,0xff,0xff};
uint8_t *str;
uint16_t size1 = strlen((char*)Head);
uint16_t size2 = strlen((char*)SData);
str = (uint8_t*)malloc(size1 + size2 + 3);
if(str != NULL)
{
memcpy(str,Head,size1);
memcpy(str + size1,(uint8_t*)"=",1);
memcpy(str + size1 + 1,(uint8_t*)"\"",1);
memcpy(str + size1 + 2,SData,size2);
memcpy(str + size1 + size2 + 2,(uint8_t*)"\"",1);
HAL_UART_Transmit(&uart, (uint8_t*)str, size1 + size2 + 3, 0xffff); //发送数据
HAL_UART_Transmit(&uart, (uint8_t*)&End_Bit, 3, 0xffff); //发送结束位
free(str); //释放内存
}
}
/******************************
**** 函数功能:发送数据到控件(value)
**** 形参: Head:控件的名字,data:数据
**** 返回值: 无
*******************************/
void HMI_Usart_SendDataValue(uint8_t *Head, int16_t data)
{
uint8_t End_Bit[3] = {0xff,0xff,0xff};
uint8_t buf[10];
uint8_t *str;
uint16_t size1 = strlen((char*)Head);
sprintf((char*)&buf,"%d",data);
uint16_t size2 = strlen((char*)buf);
str = (uint8_t*)malloc(size1 + 1);
if(str != NULL)
{
memcpy(str,Head,size1);
memcpy(str + size1,(uint8_t*)"=",1);
str = (uint8_t*)realloc(str,size1 + 1 + size2); //再申请内存
memcpy(str + size1 + 1, buf,size2);
HAL_UART_Transmit(&uart, (uint8_t*)str, size1 + size2 + 1, 0xffff); //发送数据
HAL_UART_Transmit(&uart, (uint8_t*)&End_Bit, 3, 0xffff); //发送结束位
free(str); //释放内存
}
}
/******************************
**** 函数功能: 数据解算
**** 形参: _DA接收到的数据
**** 返回值: 数据
*******************************/
static float ResolvingData(uint8_t *_DA)
{
int16_t DataBUf = 0;
switch (_DA[2]) //数据缩放等级(0(0),1(10),2(100))
{
case _1E_0: //无缩放
DataBUf = *((int16_t*)(&_DA[3]));
return (float)DataBUf; //解算数据
case _1E_1: //10倍缩放
DataBUf = *((int16_t*)(&_DA[3]));
return (float)DataBUf / 10.f; //解算数据
case _1E_2: //100倍缩放
DataBUf = *((int16_t*)(&_DA[3]));
return (float)DataBUf / 100.f; //解算数据
default:
return -1.f;
}
}
/******************************
**** 函数功能: 接收数据处理
**** 形参: _DA接收到的数据
**** 返回值: 无
*******************************/
static void Acceptance_Data(uint8_t *_DA)
{
float DataBuf = 0;
DataBuf = ResolvingData(_DA); //数据解算
if(DataBuf != -1) //解算成功
{
UHMI.ID = _DA[1];
switch (_DA[1]) //数据ID
{
case _INT_VAID1: UHMI._IntRecData->_Data01 = (int16_t)DataBuf; break;
case _INT_VAID2: UHMI._IntRecData->_Data02 = (int16_t)DataBuf; break;
case _INT_VAID3: UHMI._IntRecData->_Data03 = (int16_t)DataBuf; break;
case _INT_VAID4: UHMI._IntRecData->_Data04 = (int16_t)DataBuf; break;
case _INT_VAID5: UHMI._IntRecData->_Data05 = (int16_t)DataBuf; break; //整型数据
case _FLO_VAID1: UHMI._FloatRecData->_Data10 = DataBuf; break;
case _FLO_VAID2: UHMI._FloatRecData->_Data20 = DataBuf; break;
case _FLO_VAID3: UHMI._FloatRecData->_Data30 = DataBuf; break;
case _FLO_VAID4: UHMI._FloatRecData->_Data40 = DataBuf; break;
case _FLO_VAID5: UHMI._FloatRecData->_Data50 = DataBuf; break; //小数数据
}
}
}
/******************************
**** 函数功能:HMI接收数据函数
**** 形参: RData:接收到的数据
**** 返回值: 无
*******************************/
void HMI_Usart_ReciveData(uint8_t *RData,uint8_t size)
{
if(size == 7) //数据长度正确
{
if(RData[0] == 0xCC) //数值类帧,帧头正确
Acceptance_Data(RData); //数据处理
else if(RData[0] == 0xDD) //功能类,帧头正确
HMI_Usart_FunctionSelect(&RData[1]); //功能执行
}
}
/******************************
**** 函数功能:HMI功能类执行函数选择
**** 形参: Rfun:接收的数据
**** 返回值: 无
*******************************/
void HMI_Usart_FunctionSelect(uint8_t *Rfun)
{
switch (*Rfun)
{
case Start: UHMI.StartFlag = 1; break;
case Stop: UHMI.StartFlag = 0; break;
case mode1: UHMI.Mode = 1; break;
case mode2: UHMI.Mode = 2; break;
case mode3: UHMI.Mode = 3; break;
case mode4: UHMI.Mode = 4; break;
case mode5: UHMI.Mode = 5; break;
default: UHMI.Mode = 0; UHMI.StartFlag = 0; break;
}
}
2、Hmi_Agreements.h
代码如下(示例):
#ifndef __HMI_AGREEMENT_H
#define __HMI_AGREEMENT_H
#include "stm32h7xx.h" // Device header
#include "stdio.h"
#include "string.h"
#include "usart.h"
#define uart huart2 //使用的串口
#define _DataNum 5 //可接收数据数量
enum _Var
{
Start = 0x00,
Stop = 0x01, //工作状态
mode1 = 0x11,
mode2 = 0x12,
mode3 = 0x13,
mode4 = 0x14,
mode5 = 0x15, //模式
_1E_0 = 0, //数据缩放等级
_1E_1,
_1E_2,
_INT_VAID1 = 0x01, //整型数据ID
_INT_VAID2,
_INT_VAID3,
_INT_VAID4,
_INT_VAID5,
_FLO_VAID1 = 0x10, //小数数据ID
_FLO_VAID2,
_FLO_VAID3,
_FLO_VAID4,
_FLO_VAID5,
};
struct IntRecData //接收的数据缓存(整数)
{
int16_t _Data01;
int16_t _Data02;
int16_t _Data03;
int16_t _Data04;
int16_t _Data05;
};
struct FloatRecData //接收的数据缓存(小数)
{
float _Data10;
float _Data20;
float _Data30;
float _Data40;
float _Data50;
};
typedef struct
{
uint8_t StartFlag; //程序开始运行标志位
uint8_t ID; //数据ID
uint8_t Mode; //工作模式
struct IntRecData _IntRecData[_DataNum/5]; //接收的数据结构体
struct FloatRecData _FloatRecData[_DataNum/5]; //接收的数据结构体
}_usarthmi;
extern _usarthmi UHMI;
/********************** 用户上传指令 ********************/
void HMI_Usart_Rest(void); //HMI显示屏复位
void HMI_Usart_Refresh(uint8_t *Page); //HMI刷新页面
void HMI_Usart_SendDataValue(uint8_t *Head, int16_t data); //串口发送数据到HMI屏幕
void HMI_Usart_SendDataText(uint8_t *Head, uint8_t *SData); //串口发送字符数据到HMI屏幕
void HMI_Usart_ShowHideobj(uint8_t *Obj,uint8_t State); //对指定的控件的显示和隐藏进行操作
/********************* 用户接收数据处理 *******************/
static float ResolvingData(uint8_t *_DA); //数据解算
static void Acceptance_Data(uint8_t *_DA); //接收数据处理
/********************* 用户可调用的函数 *******************/
void HMI_Usart_ReciveData(uint8_t *RData,uint8_t size); //HMI接收数据函数
void HMI_Usart_FunctionSelect(uint8_t *Rfun); //HMI功能类执行函数选择
#endif
四、使用说明
1、接收数据
本程序暂未采用DMA
形式发送接收数据,只需在串口回调函数中调用数据接收处理函数
void HMI_Usart_ReciveData(uint8_t *RData,uint8_t size)
接收的数据会分为两类:整型和浮点型的数据,整型数据保存在以下结构体中:
struct IntRecData //接收的数据缓存(整数)
{
int16_t _Data01;
int16_t _Data02;
int16_t _Data03;
int16_t _Data04;
int16_t _Data05;
};
浮点型数据保存在以下结构体中:
struct FloatRecData //接收的数据缓存(小数)
{
float _Data10;
float _Data20;
float _Data30;
float _Data40;
float _Data50;
};
他们的ID
与HMI
发送的数据的ID
相同(注:发送时整型和浮点型数据开始的ID
不一样)
而他们都在以下结构体中:
typedef struct
{
uint8_t StartFlag; //程序开始运行标志位
uint8_t ID; //数据ID
uint8_t Mode; //工作模式
struct IntRecData _IntRecData[_DataNum/5]; //接收的数据结构体
struct FloatRecData _FloatRecData[_DataNum/5]; //接收的数据结构体
}_usarthmi;
2、发送数据
发送数据可使用以下函数:
void HMI_Usart_SendDataValue(uint8_t *Head, int16_t data); //串口发送数据到HMI屏幕
void HMI_Usart_SendDataText(uint8_t *Head, uint8_t *SData); //串口发送字符数据到HMI屏幕
五、下载方式
有积分的同学可以用csdn
下载哦,没积分的同学可以去我GitHub
仓库下载