之前一直用正点原子的LCD屏,但是占用太多GPIO引脚,所以打算换一块串口屏,某宝上看了一圈,看中了广州大彩的M系列8寸屏,厂家提供了单片机例程,但是芯片是F103的,而我的板子是ST的STM32F4DISCOVERY,需要进行移植,移植花了我半天时间,踩了不少坑,为了避免后来者少踩坑,所以决定写一下移植过程。其实之前有人写过怎么移植,个人觉得写得不够透彻,而且有些步骤多余,所以决定自己来。
作为工控行业从业十年的工程师,接触过不少外国牌子的触摸屏,如西门子的TP1200\TP900,三菱的GOT1000、GOT2000,等等,还有台达的触摸屏。这回做项目开发,本着支持国产的初衷(省钱),在某宝选中了广州大彩的M系列串口屏,确实很惊艳,功能丝毫不逊色与一线品牌,全中文的组态软件也很友好。
我选的串口屏型号是DC80600M080AV_1111_0X(T/C/N) ,M系列8寸医用级,支持RS232/TTL串口通讯,带了个小喇叭,支持AV输入(可流畅播放外部视频),声音输出。其实不管F系列还是M系列,都可以参照我的方法移植。
先看一下触摸屏背部构成,看下图。
需要我们接线的主要在最下方的通信接口,这是一个8Pin的接口,局部图片如下:
购买串口屏,厂家提供了相应的例程,但是例程是基于F103开发的,在厂家官网可以下载。而当你用的是别的MCU的时候,就比较头疼了。并且最苦恼的是什么?这个例程是基于标准库函数写的,而现在大部分项目都用HAL库函数写,导致很多地方不可以直接复制粘贴,要针对性地修改!直接拷贝过去的话,error大概有45条,warming大概200多条! 是不是很麻烦?
把厂家的例程下下来之后,打开这个例程项目。
void SendChar(uint8_t t)
{
USART3->DR=t;
while((USART3->SR&0X40)==0);//等待发送结束 等待发送结束
}
官网有出厂工程文件,直接下载下来根据自己需求修改就行,背景图片可以用photoshop之类的软件修改,大家可以看看我修改后的主画面内容。
效果还行吧,毕竟是基于官方的工程修改的。以主画面里面的状态指示画面为例,讲述如何实现程序设计及调用。
while(1)
{
size = queue_find_cmd(cmd_buffer,CMD_MAX_SIZE); //从缓冲区中获取一条指令
if(size>0&&cmd_buffer[1]!=0x07) //接收到指令 ,及判断是否为开机提示
{
ProcessMessage((PCTRL_MSG)cmd_buffer, size); //指令处理
}
if(time%20==0)
{
UpdateUI();
}
}
第一个if的作用是接收缓存区的第一条指令,判定如果非开机提示,则调用ProcessMessage()函数,解析串口屏发过来的指令集,以我上面的状态指示画面为例,当解析到串口屏发过来的画面切换指令时,将自动调用NotifyScreen()函数,判定切换到了哪个画面,然后在对应if(screen_id == X)的条件语句中写入自己需要执行的动作函数,比如我需要在状态指示画面的文本控件2上显示左轮速度(整数),在文本控件4上显示航向角(浮点数),则调用的函数如下:
void NotifyScreen(uint16 screen_id)
{
//TODO: 添加用户代码
current_screen_id = screen_id; //在工程配置中开启画面切换通知,记录当前画面ID
//进到画面1亮
if(screen_id == 1) //判断如果是画面1,则操作以下控件更新数据显示
{
AnimationPlayFrame(1,9,0);
SetTextInt32(1,2,Left_val,0,1); //更新画面ID=1,控件ID=2上的数据,其中Left_val为你需要传入的数据,整数型
SetTextInt32(1,3,Right_val,0,1);
SetTextFloat(1,4,attitude.yaw,1,1); //更新画面ID=1,控件ID=4上的数据,其中attitude.yaw为你需要传入的数据,浮点型
SetTextInt32(1,5,mag_letf_sensor,0,1);
SetTextInt32(1,6,mag_right_sensor,0,1);
}
}
显示整数需要调用SetTextInt32(),显示浮点数需要调用SetTextFloat(),所有需要执行动作的指令函数,都在hmi_driver.c文件里可以找到,你想实现什么功能就相应地调用哪个函数。此外我在UpdateUI()函数里也添加了同样的判定语句,只要检测到画面切换到1,那么就更新文本控件内的数据。大家可以看我的主循环while(1)里,UpdateUI()函数并不是每次都调用,而是有一定的间隔时间,大家注意一定不要频繁调用,因为厂家建议10~100ms往屏写一次数据比较好,避免内存溢出,我是间隔200ms发一次。
void UpdateUI()
{
//文本设置和显示 定时20ms刷新一次
if(current_screen_id==1) //判断如果是画面1,则操作以下控件更新数据显示
{
AnimationPlayFrame(1,9,0);
SetTextInt32(1,2,Left_val,0,1);
SetTextInt32(1,3,Right_val,0,1);
SetTextFloat(1,4,attitude.yaw,2,1);
SetTextInt32(1,5,mag_letf_sensor,0,1);
SetTextInt32(1,6,mag_right_sensor,0,1);
}
}
最后贴一个我移植成功后的效果图吧,画面ID=1时,各个控件每200ms刷新一次数据,效果图如下:
经过一番操作,相信你已经成功移植串口屏例程到自己项目里面了,如果有问题,可以私信我,文章转载,请注明作者跟出处哦。