文章目录

  • RS485通信协议
  • 开发包
  • 屏幕显示位置与区域划分
  • 串口收发函数替换
  • 汉字编码
    • 字库下载
    • 编码转换
  • 遇到的问题
    • 问题1-无法分行
    • 问题2-颜色问题
    • 问题3-没有显示星期的函数
  • LED显示照片

一个项目上用到视展LED全彩屏,第一次对接这种LED屏幕,发现这个屏幕的功能还是很强大的!技术支持也挺给力的,两天时间对接完成;这里把主要的东西记录一下,做个笔记。

RS485通信协议

刚开始拿到通信协议,有点懵了,虽然我对十六进制的协议并不陌生,但是协议里涉及到的字段、专用名词比较多,不容易理解,段时间去开发一套通信协议代码也不现实,还好提供了c语言的通信代码,虽然是Windows平台下的代码,稍微改了下就可以用在Linux下了。

开发包

视展提供的sdk代码与软件:

App: 是LED屏幕配套的软件;
EasyProtocolDemo是一个比较精简的内码发送显示的实例,我也是基于这个代码做的;

├── LedUtils.c --- led通信协议打包函数实现
├── LedUtils.h
├── crc.c    ----- 校验计算函数实现
├── main.c   ----- 测试main函数
├── packet.c ----- 网络接口实现,主要是用于网络通信,串口的话就不需要这个文件了
├── packet.h ----- 部分协议结构体定义
├── system.h ----- 协议中的宏定义、枚举、结构体定义
├── uart.c   ----- 串口读写接口实现
└── uart.h

如上,首先我们要弄清楚屏幕通信控制的执行流程,可以先看下main.c里面的函数:

#include <windows.h>
#include <stdio.h>
#include <conio.h>#include "system.h"
#include "packet.h"
#include "uart.h"
#include "LedUtils.h"char CardHost[16] = "192.168.1.99";
int com_port=1;void doprint(BYTE* buffer, DWORD size)
{/DWORD i;printf("------------------------------------------\n");for (i=1; i<=size; i++){printf("0x%0.2X,", buffer[i-1]);if ((i % 8)==0) printf(" ");if ((i % 16)==0) printf("\n");}printf("\n----------------------------------------\n");
/
}void net_send(BYTE* stream)
{DWORD size;BYTE buffer[6144];SOCKET s;DWORD i, K;char ip[16];WORD port;s=InitSocket(9011);//----generate and send the begin packet----size=DoBeginPacket(buffer, 0);SocketWrite(s, buffer, size, CardHost, 6666);Sleep(100);size=SocketRead(s, buffer, 6144, ip, &port);if (size>0) printf("==>begin packet ok\n\n"); else printf("==>begin packet time out\n\n");//----generate and send the data packet----// first, get the count of data packetK=GetDataPacketCount(stream);// second, generate and send the data packet one by onefor (i=1; i<=K; i++){size=DoDataPacket(stream, i, buffer, 0);SocketWrite(s, buffer, size, CardHost, 6666);Sleep(100);size=SocketRead(s, buffer, 6144, ip, &port);if (size>0) printf("==>data packet %d ok\n\n", i); else printf("==>data packet %d time out\n\n", i);}//----generate and send the end packet----size=DoEndPacket(buffer, K+1, 0);SocketWrite(s, buffer, size, CardHost, 6666);Sleep(100);size=SocketRead(s, buffer, 6144, ip, &port);if (size>0) printf("==>end packet ok\n\n"); else printf("==>end packet time out\n\n");CloseSocket(s);
}void com_send(BYTE* stream)
{DWORD size;BYTE buffer[6144];DWORD i, K;TDeviceInfo dev;uart_Initialize(com_port);//----generate and send the begin packet----size=DoBeginPacket(buffer, 0);uart_Write(buffer, size, NULL);Sleep(100);size=uart_Read(buffer, 6144, &dev);if (size>0) printf("==>begin packet ok\n\n"); else printf("==>begin packet time out\n\n");//----generate and send the data packet----// first, get the count of data packetK=GetDataPacketCount(stream);// second, generate and send the data packet one by onefor (i=1; i<=K; i++){size=DoDataPacket(stream, i, buffer, 0);uart_Write(buffer, size, NULL);Sleep(100);size=uart_Read(buffer, 6144, &dev);if (size>0) printf("==>data packet %d ok\n\n", i); else printf("==>data packet %d time out\n\n", i);}//----generate and send the end packet----size=DoEndPacket(buffer, K+1, 0);uart_Write(buffer, size, NULL);Sleep(100);size=uart_Read(buffer, 6144, &dev);if (size>0) printf("==>end packet ok\n\n"); else printf("==>end packet time out\n\n");uart_Destroy();
}void demo_string()
{BYTE stream[65536];char str1[]="HELLO WORLD!";char str2[]="你好";//genrate the display program data//this is a demo that there are two text display in the screen//one display in the rect (0, 0, 256, 16), another display in the rect (0, 16, 256, 32)//  /---------------\//  | HELLOW WORLD! |//  | hellow world! |//  \---------------/MakeRoot(stream);AddChapter(0x7fffffff, PLAY_MODE_WAIT);AddRegion(0, 0, 256, 32);AddLeaf(0x7fffffff, PLAY_MODE_WAIT);AddString(0, 0, 256, 16, str1, FONT_SET_16, RGB(255,255,0), 1, 0, 2, 0, 0, 0, 5000);  //display in yellowAddString(0, 16, 256, 16, str2, FONT_SET_16, RGB(0,255,0), 1, 0, 2, 0, 0, 0, 5000);  //display in green//send to screen//net_send(stream); //this is the network (udp)com_send(stream);  //this is the rs232
}void main(void)
{while (1){demo_string();Sleep(5000);}
}

代码比较简单,我们关注的函数就是:demo_string(),这个函数在这里就是实现了向屏幕发送要显示的内容:

#mermaid-svg-cRYRtc9MYAPb15ag {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-cRYRtc9MYAPb15ag .error-icon{fill:#552222;}#mermaid-svg-cRYRtc9MYAPb15ag .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cRYRtc9MYAPb15ag .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-cRYRtc9MYAPb15ag .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cRYRtc9MYAPb15ag .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cRYRtc9MYAPb15ag .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cRYRtc9MYAPb15ag .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cRYRtc9MYAPb15ag .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cRYRtc9MYAPb15ag .marker.cross{stroke:#333333;}#mermaid-svg-cRYRtc9MYAPb15ag svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cRYRtc9MYAPb15ag .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-cRYRtc9MYAPb15ag .cluster-label text{fill:#333;}#mermaid-svg-cRYRtc9MYAPb15ag .cluster-label span{color:#333;}#mermaid-svg-cRYRtc9MYAPb15ag .label text,#mermaid-svg-cRYRtc9MYAPb15ag span{fill:#333;color:#333;}#mermaid-svg-cRYRtc9MYAPb15ag .node rect,#mermaid-svg-cRYRtc9MYAPb15ag .node circle,#mermaid-svg-cRYRtc9MYAPb15ag .node ellipse,#mermaid-svg-cRYRtc9MYAPb15ag .node polygon,#mermaid-svg-cRYRtc9MYAPb15ag .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cRYRtc9MYAPb15ag .node .label{text-align:center;}#mermaid-svg-cRYRtc9MYAPb15ag .node.clickable{cursor:pointer;}#mermaid-svg-cRYRtc9MYAPb15ag .arrowheadPath{fill:#333333;}#mermaid-svg-cRYRtc9MYAPb15ag .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-cRYRtc9MYAPb15ag .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-cRYRtc9MYAPb15ag .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-cRYRtc9MYAPb15ag .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-cRYRtc9MYAPb15ag .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-cRYRtc9MYAPb15ag .cluster text{fill:#333;}#mermaid-svg-cRYRtc9MYAPb15ag .cluster span{color:#333;}#mermaid-svg-cRYRtc9MYAPb15ag div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-cRYRtc9MYAPb15ag :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

MakeRoot
AddChapter
AddRegion
AddLeaf
AddString
串口发送

AddString就是添加要显示的文字内码,LED屏幕支持内码发送和文本发送,内码发送就是发送的国标内码,文本文字就是将文字转换为点阵数据发送,这种方式数据量比较大,建议直接用内码发送。

如果想要发送的文字过长时滚动,需要将AddString的第8个参数(inmethod)传入2。

如果需要屏幕自动保存内码,则需要使用下载内码的方式(ROOT_DOWNLOAD):

void MakeRoot(BYTE* buffer)
{DWORD size;root=(PRoot)buffer;size=sizeof(TRoot);memset(root, 0, size);root->id=ROOT_PLAY;  //修改这里ROOT_DOWNLOAD可以让下载的内码保存root->color=LED_THREE;root->count=0;root->survive=0xffffffff;root->Reserved=0;root->size=size;BufferSeek=size;
}

屏幕显示位置与区域划分

AddStringDateTime: 是添加显示时间,这个时间是屏幕自己计时,需要屏幕控制卡的程序支持;
AddStringWeek : 是添加显示“星期”;
AddString: 就是添加显示内码文字;
这几个函数每调用一次就相当于产生一个显示对象(区域),LED屏幕上根据传入的坐标显示在不同的位置。

屏幕可以指定更新一个局部的显示对象,比如使用AddString添加的一个内容,需要定时更新,那么只需要调用定时更新对象的函数即可(我把sdk里的函数改造了一下):

void demo_update_object(int objectindex, const char* str, long left, long top, long width, long height)
{BYTE stream[65536];char outStr[512]={0};u2g((char *)str,strlen(str),outStr,sizeof(outStr));MakeObject(stream, 0, 0, 0, (long)objectindex);AddStrings(left, top, width, height, 1);AddChildString(outStr, FONT_SET_16, RGB(240,0,0), 2, 0, 0, 0, 0, 0, 5000);com_send(stream);
}

串口收发函数替换

Windows下与Linux下主要串口部分需要改下,别的代码不用修改,我把uart.c里的串口收发函数的实现改为了我这边Linux里的封装:

int uart_send(const void *pdata, int len)
{int ret = -1;
#ifdef _TEST_ret = 0;dPrint(WARN, ">%s\n", hexdump(pdata, len).c_str());
#elseret = gs_pSerial->sendData(pdata, len);if ( ret <= 0 ){dPrint(ERROR, "led screen send error.\n");}
#endifreturn ret;
}int uart_read(void *pdata, int len)
{int ret = -1;
#ifdef _TEST_ret = 0;
#elseret = readable_timeo(gs_pSerial->getObjectFd(), 10);if ( ret <= 0 ){dPrint(ERROR, "led screen read timeout : %d.\n",ret);return ret;}ret = gs_pSerial->readData(pdata, len);if ( ret <= 0 ){dPrint(WARN, "led screen send error.\n");}
#endifreturn ret;
}

我函数名字改了,如果函数名字不改的话,com_send函数就不用动了。

汉字编码

LED是采用的GB2312编码,使用内码进行通信时,需要LED事先下载好内码,下载内码是使用配套的软件进行下载的。

字库下载

如下图,点击下载字库,就会弹出让选择字库文件的对话框,然后下载即可。

编码转换

我们设备里面采用的UTF8编码,所以汉字的显示需要做一下内码转换,这里没有自己去写函数转换,直接移植了iconv库,用iconv库函数去做的转换,下面是从网上查找到的封装代码:

/*代码转换:从一种编码转为另一种编码*/
static int code_convert(char *from_charset,char *to_charset,char *inbuf,int inlen,char *outbuf,int outlen)
{iconv_t cd;int rc;char **pin = &inbuf;char **pout = &outbuf;cd = iconv_open(to_charset,from_charset);if (cd==0) return -1;memset(outbuf,0,outlen);if (iconv(cd,pin,(size_t*)&inlen,pout,(size_t*)&outlen)==-1) return -1;iconv_close(cd);return 0;
}/*UTF8码转为GB2312码*/
static int u2g(char *inbuf,int inlen,char *outbuf,int outlen)
{return code_convert("utf-8","gb2312",inbuf,inlen,outbuf,outlen);
}
/*GB2312码转为UTF8码*/
static int g2u(char *inbuf,size_t inlen,char *outbuf,size_t outlen)
{return code_convert("gb2312","utf-8",inbuf,inlen,outbuf,outlen);
}

这样在发送内码的地方统一做一次转换即可。

遇到的问题

问题1-无法分行

我用的这个屏幕是32032的,汉字是1616点阵,只能在第一行显示,即使把y坐标设置为16,还是在0处显示,这个问题是控制卡软件的问题,找技术支持升级后解决了。

问题2-颜色问题

即RGB的染色值顺序变了,这个在软件上可以配置R、G、B的顺序,可以配置为RGB、RBG、GBR等

问题3-没有显示星期的函数

这个首先可以通过发内码来解决,如果自己不想写这部分代码,可以找找支持,我这边找技术支持给加了一个函数~

整体上调试还是比较顺利的。

LED显示照片


视展LED屏幕RS485对接(C语言)相关推荐

  1. 华夏相机/臻识相机车牌识别器同LED屏幕语音对接以及javaDemo

    上篇文章说过在本地买的华夏相机T83因为当地的销售人员只懂安装,一点技术支持也给不了,导致语音/屏幕 均不能实现自己想要的功能(自定义修改文字,语音播放余额等),经过自己进一步的研究发现,这个led屏 ...

  2. LED:视展VSD控制卡网口闪烁不能访问

    摘要:对视展 VSD控制卡的操作简要记录一下,在本次协助处理过程中,居然已经遗忘了怎么连卡.按照自己的思路记录本次问题处理及控制卡的基础连接操作. 个人建议:遇到问题第一时间向厂家沟通,回复很快,这里 ...

  3. win7调整屏幕亮度_番禺区户外LED屏幕求购,区LCD屏幕解决方案

    广州市唯昕电子科技有限公司为您详细解读gVtwd番禺区户外LED屏幕求购的相关知识与详情,正在当今大尺寸液晶面板范畴,55英寸卖得货已经成为市场的支流.但是关于很多行业用户来说,李某们会担忧将来使用的 ...

  4. 圆形led屏幕_一种圆形LED显示屏幕的制作方法

    本实用新型涉及LED领域,具体的来说是涉及一种圆形LED显示屏幕. 背景技术: 当今世界,电子技术迅猛发展,点阵式显示器件作为信息显示的重要媒体,在金融证券.体育.邮电.电信.指挥调度.国防军事等许多 ...

  5. 开发LED屏幕页面遇到的问题

    上上个礼拜公司的展销会活动需要一个展示在LED大屏幕的页面,顶部显示平台交易总金额,左右两边分别是厂家和买家实时交易记录,具体页面长下面这个样子 需求评审的时候产品说顶部的总金额要有一个数字滚动或者翻 ...

  6. 透明LED屏幕一平米多少钱?详解透明LED显示屏价格组成

    LED透明屏属于新一代的显示设备,与传统显示屏相比,画面更通透炫酷,具有3D效果,科技感更强烈,非常受用户的喜爱.透明LED屏幕一平米多少钱?在了解透明LED显示屏价格之前,首先要了解一下影响价钱的几 ...

  7. proteus8单片机c语言仿真教程,入门学习Proteus 8仿真软件以及C51单片机的LED点亮(C语言)——实例...

    入门学习Proteus 8仿真软件以及C51单片机LED的点亮(C语言)--实例 一.点亮LED的程序编译 1.打开Keil uVision 4新建一个工程 2.在Atmel下寻找AT89C52芯片并 ...

  8. 苹果屏幕尺寸_搭载 mini LED 屏幕的 iPad Pro 要来了?!

    点击上方蓝色字体,关注我们 去年,分析师郭明錤曾预测苹果最快将在 2020 年末推出搭载 Mini LED 屏幕的产品,首款产品可能是 iPad Pro 或者 MacBook.郭明錤称 Mini LE ...

  9. led大屏按实际尺寸设计画面_主楼大报告厅LED屏幕使用须知

    为了更好地保障主楼报告厅各类会议.活动的开展,进一步规范厅内LED屏幕的使用,确保画面正常显示不变形,我部根据实际比例制作了相应背景图片模板供大家参考,借用单位可直接下载编辑后使用,也可按照比例自行设 ...

最新文章

  1. Android短信操作(通过内容提供者)
  2. 使用scipy实现简单神经网络
  3. FileCoin (1) 初步介绍
  4. csky linux 编译内核,TQ2440的EmbedSky_hello模块编译内核问题及解决
  5. 神经网络算法-论证单层感知器的局限性
  6. 笨方法“学习python笔记之打印及注释
  7. 一步一步學習partition之range分區如何創建
  8. buck电路pscad仿真_十二脉波整流器谐波抑制控制策略仿真
  9. python如何读取文件建立字典_如何使用python从文本文件创建字典
  10. php实现des加密,如何在PHP项目中实现一个DES加密解密功能
  11. Oracle11g exp 1445,oracle11g 导出表报EXP-00011:table不存在。
  12. c++ PP第九章最后一题
  13. jersey 过滤_Jersey
  14. journalctl用法详解
  15. 百度 图像识别Api logo识别 基于java的Demo
  16. android qq音乐歌词怎么实现,Android自定义View,高仿QQ音乐歌词滚动控件!
  17. [translate]Multimodal Self-Paced Learning for Multi-Omics Feature Selection and Data Integration
  18. UG NX 10 控制基准平面的显示大小
  19. python排名差怎么改,2017中国大学排名爬虫代码修改
  20. IP反查网站,ip反查接口,旁站查询接口大全,通过IP查域名汇总:

热门文章

  1. ThinkPad R400 全系列官方恢复盘及官方分区工具
  2. C++编译时提示:error: ‘x’ does not name a type
  3. 常见的local variable 'x' referenced before assignment问题
  4. stm32f103驱动SHT20( I2C )
  5. IntelliJ IDEA插件开发入门教程(一)
  6. Oracle 运维DBA工作日常
  7. js弹出对话确认框插件
  8. 支付宝小程序模板开发,协助商家一键创建小程序
  9. 淘宝评论接口可以获取PC端,app端
  10. animation动画案例