[应用相关] STM32串口读写迪文屏8位、16位、32位数据

[复制链接]
2111|17
 楼主| 远芳侵古道 发表于 2022-7-26 15:51 | 显示全部楼层 |阅读模式
前言

基于STM32F407实现与迪文串口屏T5L系列的串口通信,实现8位,16位,32位的数据读写。
PS:不包含完整程序,这里只说一下核心的代码,本文之前读取数据使用的是阻塞方式,需要使用关闭了82指令回应的屏幕内核,在新版本代码(文章末尾)中采用了非阻塞方式读取数据。

一、移植相关实现数据类型

后面的数据处理需要根据MCU的大小端方式,移植到其他平台的话,需要检验一下是大端还是小端。

  1. #define u8 unsigned char
  2. #define u16 unsigned short
  3. #define u32 unsigned int
  4. //32位int与8位char互转
  5. typedef union
  6. {
  7.         u32 intdata;
  8.         u8 chardata[4];
  9. }int_char_unioin;
  10. //16位short与8位char互转
  11. typedef union
  12. {
  13.         u16 shortdata;
  14.         u8 chardata[2];
  15. }short_char_unioin;


 楼主| 远芳侵古道 发表于 2022-7-26 16:03 | 显示全部楼层
需要自定义的变量和函数
buffer——串口收发缓冲区数组,一段数据帧一般不超过20字节,根据实际使用设置大小。
 楼主| 远芳侵古道 发表于 2022-7-26 16:04 | 显示全部楼层
send_buffer()——向串口发送buffer数组。
 楼主| 远芳侵古道 发表于 2022-7-26 16:06 | 显示全部楼层
delay_time——等待迪文屏返回数据的时间,例:5ms,迪文屏上OS的周期是20ms,读写过快可能出问题。(接收数据实际上是在串口中断,这里只是阻塞等待处理屏幕回应的数据)
 楼主| 远芳侵古道 发表于 2022-7-26 16:08 | 显示全部楼层
clear_usart()——清空串口缓冲区数组buffer,如用memset()将数组置零即可。
 楼主| 远芳侵古道 发表于 2022-7-26 16:09 | 显示全部楼层
迪文屏读写
STM32与迪文屏的通信核心在于向迪文屏中定义的变量进行读写,迪文屏中的变量用一个16位数据表示其地址。迪文屏的用户可操作地址空间为0x1000-0xFFFF,我们要做的就是在这个区间内的一个地址上读写数据,这个地址指向的数据类型由DGUS(迪文屏开发上位机软件)设置,详细内容可以查看迪文公司的应用开发指南。
 楼主| 远芳侵古道 发表于 2022-7-26 16:10 | 显示全部楼层
RAM 空间固定 128KB,分割为 0x0000-0xFFFF 子空间范围,每 1 个变量地址对应相应空间的 2 字节,每 1 个 字节对应相应空间的 8 个位。
 楼主| 远芳侵古道 发表于 2022-7-26 16:11 | 显示全部楼层
其中 0x0000-0x0FFF 是系统变量接口地址空间,用户不能自定义;0x1000-0xFFFF 变量存储空间用户可以任意使用。如果 8 通道曲线同时使用,0x1000-0x4FFF 将作为曲线缓冲区地址,此时该部分变 量地址不能被其他控键使用,其他控键地址使用范围为:0x5000-0xFFFF。
 楼主| 远芳侵古道 发表于 2022-7-26 16:36 | 显示全部楼层
 楼主| 远芳侵古道 发表于 2022-7-26 16:43 | 显示全部楼层
变量示例——代码中的addr基本都是指这个“变量地址”,不同的控件会有不同的属性,但至少会有“变量地址”和“变量值”,某些变量属性可以通过“描述指针”来修改,每种控件的具体使用方式参考一下开发指南。
 楼主| 远芳侵古道 发表于 2022-7-26 16:45 | 显示全部楼层
 楼主| 远芳侵古道 发表于 2022-7-26 16:47 | 显示全部楼层
基本原理
DGUS 屏采用异步、全双工串口(UART),串口模式为 8n1,即每个数据传送采用十个位,包括 1 个起始位, 8 个数据位,1 个停止位。串口的所有指令或数据都是 16 进制(HEX)格式,采用高字节先传送(MSB)方式。以下内容默认采用不带CRC校验。
6574462dfaa2b407d9.png
 楼主| 远芳侵古道 发表于 2022-7-26 16:49 | 显示全部楼层
5886862dfaa76f4049.png
PS: DGUS里的字(word)一般指的是16位数据,不是指32位。
 楼主| 远芳侵古道 发表于 2022-7-26 16:53 | 显示全部楼层
向迪文屏写数据
向迪文屏上的16位地址写8位,16位,32位数据。
 楼主| 远芳侵古道 发表于 2022-7-26 16:54 | 显示全部楼层
  1. /************************************************************************************
  2. * @name                :        write_to_dwin
  3. * @brief        :        串口4向迪文屏写数据
  4. * @param        :         addr_h 变量地址高字节
  5.                                 addr_l 变量地址低字节
  6.                                 value_h 变量值高字节
  7.                                 value_l 变量值低字节
  8. * @retval        :
  9. ************************************************************************************/
  10. void write_to_dwin(u8 addr_h, u8 addr_l, u8 value_h, u8 value_l)
  11. {
  12.     u8 write_cmd[8] = {0x5A, 0xA5, 0x05, 0x82, addr_h, addr_l, value_h, value_l};
  13.     send_buffer(write_cmd, sizeof(write_cmd));
  14. }

  15. void writeu8_to_dwin(u16 addr, u8 data)
  16. {
  17.     short_char_unioin m;
  18.     m.shortdata = addr;
  19.     write_to_dwin(m.chardata[1], m.chardata[0], 0x00, data);
  20. }

  21. void writeu16_to_dwin(u16 addr, u16 data)
  22. {
  23.     short_char_unioin m;
  24.     m.shortdata = addr;
  25.     short_char_unioin n;
  26.     n.shortdata = data;
  27.     write_to_dwin(m.chardata[1], m.chardata[0], n.chardata[1], n.chardata[0]);
  28. }

  29. void writeu32_to_dwin(u16 addr, u32 data)
  30. {
  31.     short_char_unioin m;
  32.     m.shortdata = addr;
  33.     int_char_unioin n;
  34.     n.intdata = data;
  35.     u8 write_cmd[10] = {0x5A, 0xA5, 0x07, 0x82, m.chardata[1], m.chardata[0], n.chardata[3], n.chardata[2], n.chardata[1], n.chardata[0]};
  36.     send_buffer(write_cmd, sizeof(write_cmd));
  37. }
 楼主| 远芳侵古道 发表于 2022-7-26 16:59 | 显示全部楼层
从迪文屏读数据
从迪文屏上的16位地址上读取8位,16位,32位数据。
迪文屏的基本单位采用的是字(16位),所以读取数量的单位也是以字来计算的。
上位机里某些控件会有“数据自动上传”的选项,这里为了防止接收数据被打乱,统一都设置为了关闭(不选)。
 楼主| 远芳侵古道 发表于 2022-7-26 17:01 | 显示全部楼层
本文采用等待的方式接收迪文屏返回的数据,这个等待时间需要根据实际调整。
为了能正确处理数据,需要程序自主地保证buffer合法,所以会有clear、delay等操作。
 楼主| 远芳侵古道 发表于 2022-7-26 17:03 | 显示全部楼层

  1. /************************************************************************************
  2. * @name                :        read_from_dwin
  3. * @brief        :        串口4从迪文屏读数据
  4. * @param        :         addr_h 变量地址高字节
  5.                                 addr_l 变量地址低字节
  6.                                 size 数据大小(单位:字/两字节/16位)
  7. * @retval        :
  8. ************************************************************************************/
  9. void read_from_dwin(u8 addr_h, u8 addr_l, u8 size)
  10. {
  11.     clear_usart();
  12.     u8 read_cmd[7] = {0x5A, 0xA5, 0x04, 0x83, addr_h, addr_l, size};
  13.     send_buffer(read_cmd, sizeof(read_cmd));
  14. }

  15. u8 readu8_from_dwin(u16 addr)
  16. {
  17.     u8 data = 0;
  18.     short_char_unioin m;
  19.     m.shortdata = addr;
  20.     read_from_dwin(m.chardata[1], m.chardata[0], 0x01);
  21.     delay_xms(delay_time);
  22.     if (buffer[0] == 0x5A && buffer[1] == 0xA5 && buffer[3] == 0x83) //返回数据检查
  23.     {
  24.         if(buffer[4] == m.chardata[1] && buffer[5] == m.chardata[0]) //地址检查
  25.         {
  26.             data = buffer[8];
  27.         }
  28.     }
  29.     clear_usart();
  30.     return data;
  31. }
  32. u16 readu16_from_dwin(u16 addr)
  33. {
  34.     u16 data = 0;
  35.     short_char_unioin m;
  36.     short_char_unioin n;
  37.     m.shortdata = addr;
  38.     read_from_dwin(m.chardata[1], m.chardata[0], 0x01);
  39.     delay_xms(delay_time);
  40.     if (buffer[0] == 0x5A && buffer[1] == 0xA5 && buffer[3] == 0x83) //返回数据检查
  41.     {
  42.         if(buffer[4] == m.chardata[1] && buffer[5] == m.chardata[0]) //地址检查
  43.         {
  44.             
  45.             n.chardata[1] = buffer[7];
  46.             n.chardata[0] = buffer[8];
  47.             data = n.shortdata;
  48.         }

  49.     }
  50.     clear_usart();
  51.     return data;
  52. }
  53. u32 readu32_from_dwin(u16 addr)
  54. {
  55.     u32 data = 0;
  56.     short_char_unioin m;
  57.     m.shortdata = addr;
  58.     int_char_unioin n;
  59.     read_from_dwin(m.chardata[1], m.chardata[0], 0x02);
  60.     delay_xms(delay_time);
  61.     if (buffer[0] == 0x5A && buffer[1] == 0xA5 && buffer[3] == 0x83) //返回数据检查
  62.     {
  63.         if(buffer[4] == [1] && buffer[5] == m.chardata[0]) //地址检查
  64.         {
  65.             n.chardata[3] = buffer[7];
  66.             n.chardata[2] = buffer[8];
  67.             n.chardata[1] = buffer[9];
  68.             n.chardata[0] = buffer[10];
  69.             data = n.intdata;
  70.         }
  71.     }
  72.     clear_usart();
  73.     return data;
  74. }
您需要登录后才可以回帖 登录 | 注册

本版积分规则

86

主题

887

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部