程序功能:
- 点击数码管,进入数码管界面,开发板上数码管与屏幕数码管界面同时计数
- 点击步进电机,进入电机界面,点击相应按钮,控制步进电机(视频这里未插入电机)
- 点击Buzzer,进入蜂鸣器界面,控制开发板的蜂鸣器实现警报音
- 点击NTC,进入NTC界面,开发板上数码管与屏幕NTC界面显示开发板温度(这里NTC程序发送给串口屏代码的控件号有误,所以NTC界面没有显示温度值)
效果图奉上:
HMI
HMI串口屏介绍
串口HMI就是已经封装好底层功能以后,通过串口与MCU进行交互,虽然价格较贵,但开发难度大大减小,只需要使用相关上位机软件设计好GUI界面,并写好一些命令,再通过串口与MCU实现人机交互。
这里使用的是陶晶驰的串口屏,官方教程网址:http://tjc1688.com/,上位机软件下载包也可在此网站找到。
上位机软件界面认识
讲几个常用或较重要的工具和页面:
- 下载:通过串口将设计的界面下载给串口屏
- 工具箱:里面有许多控件令我们挑选,也就是设计自己想要的GUI,例如,点击文本控件,插入到GUI:
- 在界面右下角的窗口,可以操作控件的属性,例如:将刚插入的文本控件文本改为“你好”,背景色为蓝色:
当如,要想写入自己想要的文本,必须要先创建自己的字库,并添加到左下角窗口字库页面
4.Page 页面
工具箱里随意按置一个控件都会有按下事件和弹起事件,选择控件后,在命令窗口的弹起事件输入page 1(1是页面的id号,也可改为自己更改后的名字),当使用时,点击控件,就会跳到相应的界面
勾选“发送键值”,串口屏会发送相应信息给MCU。
设计出了自己想要的GUI界面后,就可以点击左上角的调试功能,实现自己的界面。
实例
设计好自己的GUI界面后,我们就要下载到串口屏上了,首先在硬件上,将串口屏的发送和接收引脚与单片机的串口接收、发送引脚连好,之后,点击Program.s里设置波特率为115200,再点击下载
代码:
这里只给出部分代码作参考
HMI协议(接收串口屏键值信息)代码:
/*
* @name HMI_Protocol
* @brief 接口协议 - 接收键值信息
* @param None
* @retval None
*/
static void HMI_Protocol(void)
{
uint8_t Temp_Array[7] = {0x00};
uint8_t i = 0,Index = 0;
//串口1停止DMA接收
HAL_UART_DMAStop(&huart1);
//读取缓存,一共7个字节,起始值为0x65
for(i=0;i<HMI_Rec_Buffer_LENGTH;i++)
{
//检测起始值0x65
if(Index == 0)
{
if(*(HMI.pucRec_Buffer+i) != 0x65)
continue;
}
Temp_Array[Index] = *(HMI.pucRec_Buffer+i);
//已读取7个字节
if(Index == Protocol_Data_LEN)
break;
Index++;
}
//串口1开启DMA接收
HAL_UART_Receive_DMA(&huart1,HMI.pucRec_Buffer,(uint16_t)20);
//处理数据
if(Index == Protocol_Data_LEN)
{
//主页面键值信息
if(Temp_Array[1] == 0x00)
{
//控件2弹起
if((Temp_Array[2] == 0x02) && (Temp_Array[3] == 0x00))
{
//切换至数码管界面
HMI.Page = Page_Display;
Display.Disp_Clr();
}
//控件3信息
if((Temp_Array[2] == 0x03) && (Temp_Array[3] == 0x00))
{
//切换至步进电机页面
HMI.Page = Page_Step_Motor;
Display.Disp_Clr();
//ÏÔʾµç»úȦÊý
Display.Disp_HEX(Disp_NUM_6,Unipolar_Step_Motor.Circle,Disp_DP_OFF);
//ÏÔʾµç»úËÙ¶È
switch(Unipolar_Step_Motor.Speed)
{
case 100: Display.Disp_HEX(Disp_NUM_1,1,Disp_DP_OFF); break;
case 90: Display.Disp_HEX(Disp_NUM_1,2,Disp_DP_OFF); break;
case 80: Display.Disp_HEX(Disp_NUM_1,3,Disp_DP_OFF); break;
case 70: Display.Disp_HEX(Disp_NUM_1,4,Disp_DP_OFF); break;
case 60: Display.Disp_HEX(Disp_NUM_1,5,Disp_DP_OFF); break;
case 50: Display.Disp_HEX(Disp_NUM_1,6,Disp_DP_OFF); break;
case 40: Display.Disp_HEX(Disp_NUM_1,7,Disp_DP_OFF); break;
case 30: Display.Disp_HEX(Disp_NUM_1,8,Disp_DP_OFF); break;
case 20: Display.Disp_HEX(Disp_NUM_1,9,Disp_DP_OFF); break;
default: break;
}
}
//控件5弹起
if((Temp_Array[2] == 0x05) && (Temp_Array[3] == 0x00))
{
//切换至NTC界面
HMI.Page = Page_NTC;
Display.Disp_Clr();
}
//控件6弹起
if((Temp_Array[2] == 0x06) && (Temp_Array[3] == 0x00))
{
//切换至蜂鸣器界面
HMI.Page = Page_Buzzer;
Display.Disp_Clr();
}
}
//数码管页面信息
if(Temp_Array[1] == 0x01)
{
//控件1弹起
if((Temp_Array[2] == 0x01) && (Temp_Array[3] == 0x00))
{
//切换至主页面
HMI.Page = Page_Main;
Display.Disp_Clr();
}
}
//步进电机页面信息
if(Temp_Array[1] == 0x02)
{
//控件11弹起
if((Temp_Array[2] == 0x0B) && (Temp_Array[3] == 0x00))
{
//切换至主页面
HMI.Page = Page_Main;
Display.Disp_Clr();
//关闭步进电机
Unipolar_Step_Motor.Status = Stop_State;
CLR_Motor_A;
CLR_Motor_B;
CLR_Motor_C;
CLR_Motor_D;
LED.LED_OFF(LED3);
Unipolar_Step_Motor.Circle = 0;
}
//控件5弹起
if((Temp_Array[2] == 0x05) && (Temp_Array[3] == 0x00))
{
HMI.Page_Step_Motor_KEY_Flag = TRUE;
HAL_GPIO_EXTI_Callback(KEY1_Pin);
HMI.Page_Step_Motor_KEY_Flag = FALSE;
}
//控件8弹起
if((Temp_Array[2] == 0x08) && (Temp_Array[3] == 0x00))
{
HMI.Page_Step_Motor_KEY_Flag = TRUE;
HAL_GPIO_EXTI_Callback(KEY2_Pin);
HMI.Page_Step_Motor_KEY_Flag = FALSE;
}
//控件6弹起
if((Temp_Array[2] == 0x06) && (Temp_Array[3] == 0x00))
{
HMI.Page_Step_Motor_KEY_Flag = TRUE;
HAL_GPIO_EXTI_Callback(KEY3_Pin);
HMI.Page_Step_Motor_KEY_Flag = FALSE;
}
//控件7弹起
if((Temp_Array[2] == 0x07) && (Temp_Array[3] == 0x00))
{
HMI.Page_Step_Motor_KEY_Flag = TRUE;
HAL_GPIO_EXTI_Callback(KEY4_Pin);
HMI.Page_Step_Motor_KEY_Flag = FALSE;
}
}
//NTC页面信息
if(Temp_Array[1] == Page_NTC)
{
if((Temp_Array[2] == 0x03) && (Temp_Array[3] == 0x00))
{
//切换至主页面
HMI.Page = Page_Main;
Display.Disp_Clr();
}
}
//蜂鸣器页面信息
if(Temp_Array[1] == Page_Buzzer)
{
//控件2弹起
if((Temp_Array[2] == 0x02) && (Temp_Array[3] == 0x00))
{
//Çл»ÖÁÖ÷Ò³Ãæ
HMI.Page = Page_Main;
Display.Disp_Clr();
}
//控件3弹起
if((Temp_Array[2] == 0x03) && (Temp_Array[3] == 0x00))
{
HMI.Page_Buzzer_Flag = TRUE;
HAL_GPIO_EXTI_Callback(KEY1_Pin);
HMI.Page_Buzzer_Flag = FALSE;
}
}
}
}
数码管计数代码:
/*
* @name Fun_Page_Display
* @brief 数码管显示页面
* @param None
* @retval None
*/
static void Fun_Page_Display()
{
static uint32_t Cnt = 0;
uint32_t i = 0;
uint8_t Disp_Str[9] = {'n','6','.','v','a','l','=','0','\0'};
uint8_t Cnt_Arr[6] = {0x00};
Cnt_Arr[0] = Cnt%10;
Cnt_Arr[1] = Cnt/10%10;
Cnt_Arr[2] = Cnt/100%10;
Cnt_Arr[3] = Cnt/1000%10;
Cnt_Arr[4] = Cnt/10000%10;
Cnt_Arr[5] = Cnt/100000;
//数码管显示计数值
Display.Disp_HEX(Disp_NUM_1,Cnt_Arr[0], Disp_DP_OFF);
Display.Disp_HEX(Disp_NUM_2,Cnt_Arr[1], Disp_DP_OFF);
Display.Disp_HEX(Disp_NUM_3,Cnt_Arr[2], Disp_DP_OFF);
Display.Disp_HEX(Disp_NUM_4,Cnt_Arr[3], Disp_DP_OFF);
Display.Disp_HEX(Disp_NUM_5,Cnt_Arr[4], Disp_DP_OFF);
Display.Disp_HEX(Disp_NUM_6,Cnt_Arr[5], Disp_DP_OFF);
//数据传给HMI串口屏
for(i=0;i<6;i++)
{
Disp_Str[1] = i + '1';
Disp_Str[7] = Cnt_Arr[i] + '0';
HMI.SendString(Disp_Str);
}
//更新计数值
if(++Cnt > 999999)
Cnt = 0;
//延时50ms
HAL_Delay(50);
}
!GUI界面下载后,硬件一定要改变为HMI串口屏与单片机通信