首页 > 其他分享 >GD32F103VET6通过仰邦BX_6K1字符卡控制96*16LED显示

GD32F103VET6通过仰邦BX_6K1字符卡控制96*16LED显示

时间:2024-06-01 15:28:27浏览次数:12  
标签:00 led 16LED show ++ 6K1 len header GD32F103VET6

1.GD32F103VET6介绍

        GD32系列单片机和STM32系列单片机在应用上十分类似,需要注意的是本系统GD32的最大时钟频率是108MHz。本系统的功能是实现LORA网关,GD32F103VET6相较于STM32系列单片机的性价比更高。  

        GD32F103VET6是一款基于Arm®的32位通用微控制器,其核心是Cortex®-M3 RISC内核。这款微控制器在处理能力方面具有最佳比率,同时降低了功耗和外设消耗。GD32F103VET6可运行在108 MHz的频率下,并且具有闪存访问零等待状态以获取最大效率的特点。它提供高达3 MB的片上闪存和高达96 KB的SRAM存储器,以及广泛的连接到两条APB总线的一系列增强型I/O和外围设备。该器件适用于广泛的应用领域,包括工业控制、电机驱动、电力监控和报警系统,以及消费类和手持设备、POS、车载GPS、可视对讲、PC外围设备等12。其工作电压范围为2.6至3.6 V,温度范围为-40至+85 °C,且提供了多种省电模式以优化功耗和唤醒延迟,这对于低功率应用来说尤为重要13。此外,GD32F103VET6还包含多个ADC和DAC,通用定时器,以及多种通信接口,如SPI、I2C、USART、UART、I2S、USBD、CAN等,使其能够满足各种复杂的通信和控制需求。

 

2. BX_6K1字符卡

        BX_6K1是一种仰邦科技生产的一种LED控制卡,本系统用BX_6K1字符卡控制96*16的LED双色显示屏实现指定内容的显示和超阈值警示。BX_6K系列字符卡有基于6K1款的升级版,其中有支持网口和 4G模块的升级款字符卡,本系统采用的是基础班的字符卡,用它带的RS485接口和单片机进行通信。BX_6K1有以下特点:

  1. 支持单色、双色、三基色屏,支持信息实时更新;
  2. 提供通讯协议,专用于工业现场,设备配套、车载显示,智能公交站牌和集群显示系统等领域的二次开发;
  3. 兼容6K协议,简化开发难度;  
  4. 更高刷新技术,更丰富的显示效果,实时更新信息时画面稳定无闪烁;
  5. 对于大中型集群项目板载通讯接口,显示接口和面向各种特殊应用系统,灵活地满足用户的特殊需求;
  6. 控制面积灵活,显示功能丰富,性价比超高;
  7. 支持字库内码格式的信息传输方式,并且支持图片点阵格式的信息传输方式;
  8. 标配亮度、温度、温湿度传感器和红外遥控头接口座。目前已经实现温度、温湿度接口,其他接口根据项目需要可考虑支持。
  9. 支持GBK编码的繁体字库,当然也支持GB2312的编码。只需下载相应字库并设置相应参数即可。
  10. 工艺精良,品质稳定。3.5V-6V宽电压工作,-40℃~80℃宽环境温度;

 3.操作说明

3.1  BX_6K1字符卡相关软件的使用

         LedShowZk是仰邦科技针对BX系列字符卡的可视化操作工具,通过此软件可以向字符卡内烧录字库和固件,通过在软甲内创建“节目”并发送可以实现指定内容在LED屏幕上的显示。需要注意的是首次使用软甲时需要配置好通讯参数,否则会通讯失败。BX_6K1预留的有232端子接口和485端子接口,两个接口都能实现上位机和字符卡的通讯,前提是设置好通讯参数!用一条USB转232数据线将电脑主机和BX_6K1的232口连接,需要注意的是通信引脚要接线准确。连线正确后进入软件配置屏幕参数(默认密码“168”),如图3.1所示。

 图3.1 屏参配置

         屏参配置完成后,在屏幕中创建节目和字库测试字符卡和LED屏幕是否适配和能否正常通信。测试过程如图3.2所示,LED显示文本内容则通讯成功。

 3.2 发送内容至LED屏幕

         创建动态分区并发送的屏幕上,如果系统需要显示实时更新的内容,建议创建动态分区,BX_6K1支持发送实时显示内容和节目(掉电不丢失)。本系统要显示的数据是实时更新的,所以就设置了动态分区并发送到屏幕上。通过设置选项里面的“字库维护”可以烧录自己想要的字体大小和样式,建议选择14*14点阵大小的汉字和14*14大小的英文。

注:LedShowSuite也是仰邦科技提供的可视化软件,二者是通用的,LedShowSuite的有点就是能创建自己想要字体的字库,其中也包括旋转字体的字库。

3.2 BX_6K1通信协议说明

        本系统使用的是系统中预留好的485接口,将BX_6K1的RS485端子上的D+连板子A口,D-连板子B口。

        BX_6K1有专门的通信协议用于控制字符卡的相关操作,在仰邦科技官网可以下载相关文档。BX_6k和BX_5K系列字符卡的相关协议是相通的,解析起来并不困难。协议的标准格式由8个字节的帧头、14个字节的包头、可变长度的数据、2个字节的包校验和一个字节的帧尾组成。标准通讯格式如图3.3所示。

        图3.3 帧标准格式

        本章节着重介绍发送显示实时信息的帧格式,注意低位在前,高位灾后:a5 a5 a5 a5 a5 a5 a5 a5 fe ff 00 80 00 00 00 00 00 00 fe 02 2c 00 a3 06 01 00 00 00 01 23 00 00 00 80 00 00 80 80 20 00 00 00 00 0a 00 00 00 00 02 01 01 00 02 0a 08 00 00 00 bb b6 d3 ad b9 e2 c1 d9 3c 49 5a

此报文是更新动态区命令,屏幕大小 128*32 ,显示内容:欢迎光临。 a5 a5 a5 a5 a5 a5 a5 a5:帧头 fe ff:屏地址 00 80:源地址 00 00 00 :保留 00:条码选项 00----不选择使用 00:校验模式 --CRC16 00:显示模式--普通模式 fe:通配符 02:协议版本号 2c 00:数据长度 a3:命令分组编号 06:命令编号 01:控制器必须回复 00: 当该字节为 0 时,收到动态信息后不再进行清区域和初始 化区域的操作 00:保留 00:要删除的区域个数      01:更新区域个数 23 00: 区域 0 数据长度 (低位在前) 00 00 80 00 00 80 80 20 00 00 00 00 0a 00 00 00 00 02 01 01 00 02 0a 08 00 00 00 bb b6 d3 ad b9 e2 c1 d9:区域0数据,里面是对屏幕显示参数的相关调整,可以按需调整

4.相关代码

        本系统使用的是控制板预留的485的1号接口,使用的是此端口的相关发送函数来实现对字符卡的控制,BX_6K1的驱动代码如下:

#include "app_bx6k1.h"

uint8_t Bx_header[8] = {0xA5,0xA5,0xA5,0xA5,0xA5,0xA5,0xA5,0xA5};//帧头
size_t array_len = 0;

/******************************************************************************
 * @函数名: BX6K1_Show_String(char *string_show,uint16_t Dstaddr)
 * @功  能: 显示指定信息  -- 要显示指定颜色的时候记得添加转义字符 
 * @输  入: string_show--要显示的字符串  Dstaddr-屏地址
 * @返  回: NULL
 * @备  注:"\C1abc\C2abc" -- 显示 红色的abc和绿色的abc
******************************************************************************/ 
void BX6K1_Show_String(char *String_show,uint16_t Dstaddr)
{
	
	uint8_t *data;
	int crc16_L,crc16_H=0;
	int len=0;
	uint8_t led_show[128] = {0};
	data = string_to_uint8_t_array(String_show,&array_len);
	memcpy(led_show,Bx_header,8);    //帧头
	len+=8;													 //偏移的长度
	//包头数据
	led_show[len++] = Dstaddr&0xff;
	led_show[len++] = Dstaddr>>8;
	led_show[len++] = header_SrcAddr&0xff;
	led_show[len++] = header_SrcAddr>>8;
	led_show[len++] = header_Reserved;
	led_show[len++] = header_Reserved;
	led_show[len++] = header_Reserved;
	led_show[len++] = header_BarCode;
	led_show[len++] = header_CheckMode;
	led_show[len++] = header_DisplayMode;
	led_show[len++] = header_DeviceType;
	led_show[len++] = header_ProtocolVersion;
	led_show[len++] = (array_len+36)&0xff;			//数据区长度
	led_show[len++] = (array_len+36)>>8;				//数据区长度
	//数据区	
	led_show[len++] = cmd_Group3;								//命令分组编号
	led_show[len++] = Num6;											//命令编号
	led_show[len++] = req_yes;									//是否要求控制器回复
	led_show[len++] = default_value;						//不清区域
	led_show[len++] = default_value;						//保留
	led_show[len++] = 0xff;						//删除区域个数
	led_show[len++] = Num1;    									//更新区域个数
	led_show[len++] = (array_len+27)&0xff;			//区域0数据长度
	led_show[len++] = (array_len+27)>>8;				//区域0数据长度
	//区域0数据
	led_show[len++] = region_type;					//区域类型
	led_show[len++] = 0x00;									//x坐标
	led_show[len++] = 0x00;
	led_show[len++] = 0x00;									//y坐标
	led_show[len++] = 0x00;			
	led_show[len++] = 128;									//区域宽度单位 80-- 像素点   0--8个像素点
	led_show[len++] = 0x80;									
	led_show[len++] = 16;										//区域高度
	led_show[len++] = 0x00;			
	led_show[len++] =	0x00;									//动态区域编号
	led_show[len++] = 0X00;									//行间距
	led_show[len++] = 0X00;									//动态区数据循环显示
	led_show[len++] = 0X0A;									//超时时间
	led_show[len++] = 0X00;									//超时时间
	led_show[len++] = 0x00;									//不使能语音模块
	led_show[len++] = 0x00;									//拓展位数
	led_show[len++] =	9;										//字体对齐方式   --上下居中 左右右对齐
	led_show[len++] =	0x02;									//是否多行显示 
	led_show[len++] = 0x01;									//不自动换行
	led_show[len++] = 0x01;									//静止显示
	led_show[len++] = 0x00;									//退出方式
	led_show[len++] = 0x02;									//显示速度
	led_show[len++] = 0x0a;									//特技显示时间
	led_show[len++] = array_len&0xff;				//显示内容长度
	led_show[len++] = array_len>>8;			
	led_show[len++] = array_len>>16;
	led_show[len++] = array_len>>24;
	for(int i = 0;i<array_len;i++)
	{
		led_show[len++] = data[i];				//显示内容
	}
	crc16_L = crc16_ibm(&led_show[8],len-8)&0xff;
	crc16_H = crc16_ibm(&led_show[8],len-8)>>8;
	led_show[len++] = crc16_L;
	led_show[len++] = crc16_H;
	led_show[len++] = data_end;
	for(int j=0;j<len;j++)
	{
		printf("led_show[%d] = %x\r\n",j,led_show[j]);
	}
	RS4851Send(led_show,len);
}
/******************************************************************************
 * @函数名: BX6K1_Power(uint8_t cmd,uint16_t Dstaddr)
 * @功  能: 指定屏的电源开关 
 * @输  入: cmd--开关命令码  Dstaddr-屏地址
 * @返  回: NULL
 * @备  注:
******************************************************************************/ 
void	BX6K1_Power(uint8_t Cmd,uint16_t Dstaddr)
{
	int crc16_L,crc16_H=0;
	int len=0;
	uint8_t led_show[128] = {0};
	
	memcpy(led_show,Bx_header,8);    //帧头
	len+=8;
	//包头数据
	led_show[len++] = Dstaddr&0xff;
	led_show[len++] = Dstaddr>>8;
	led_show[len++] = header_SrcAddr&0xff;
	led_show[len++] = header_SrcAddr>>8;
	led_show[len++] = header_Reserved;
	led_show[len++] = header_Reserved;
	led_show[len++] = header_Reserved;
	led_show[len++] = header_BarCode;
	led_show[len++] = header_CheckMode;
	led_show[len++] = header_DisplayMode;
	led_show[len++] = 0xfe;
	led_show[len++] = header_ProtocolVersion;
	led_show[len++] = power_len&0xff;			//数据区长度
	led_show[len++] = power_len>>8;			//数据区长度
	led_show[len++] = cmd_Group3;
	led_show[len++] = Num0;
	led_show[len++] = req_yes;
	led_show[len++] = default_value;
	led_show[len++] = default_value;
	led_show[len++] = Cmd;
	crc16_L = crc16_ibm(&led_show[8],len-8)&0xff;
	crc16_H = crc16_ibm(&led_show[8],len-8)>>8;
	led_show[len++] = crc16_L;
	led_show[len++] = crc16_H;
	led_show[len++] = data_end;
	for(int i=0;i<len;i++)
	{
		printf("led_show[%d] = %x\r\n",i,led_show[i]);
	}
	RS4851Send(led_show,len);
}
/******************************************************************************
 * @函数名: BX6K1_SetLight(uint8_t Light_strength,uint8_t Dstaddr,uint8_t Set_mode,uint8_t *Light_period)
 * @功  能: 设置屏幕亮度  -- 强制/定时设置 
 * @输  入: Light_strength--光强度  Dstaddr-屏地址  Set_mode--设置模式   Light_period--定时时段光照 一天分48分段
 * @返  回: NULL
 * @备  注:
******************************************************************************/ 
void	BX6K1_SetLight(uint8_t Light_strength,uint8_t Dstaddr,uint8_t Set_mode,uint8_t *Light_period)
{
	int crc16_L,crc16_H=0;
	int len=0;
	uint16_t send_length = 0;
	uint8_t led_show[128] = {0};
	
	memcpy(led_show,Bx_header,8);    //帧头
	len+=8;
	led_show[len++] = Dstaddr&0xff;
	led_show[len++] = Dstaddr>>8;
	led_show[len++] = header_SrcAddr&0xff;
	led_show[len++] = header_SrcAddr>>8;
	led_show[len++] = header_Reserved;
	led_show[len++] = header_Reserved;
	led_show[len++] = header_Reserved;
	led_show[len++] = header_BarCode;
	led_show[len++] = header_CheckMode;
	led_show[len++] = header_DisplayMode;
	led_show[len++] = 0xfe;								//通配符
	led_show[len++] = header_ProtocolVersion;
	if(Set_mode == 0x01)
		send_length = 7;
	else
		send_length = 55;
	led_show[len++] = send_length&0xff;
	led_show[len++] = send_length>>8;
	led_show[len++] = cmd_Group3;
	led_show[len++] = Num2;
	led_show[len++] = req_yes;
	led_show[len++] = default_value;
	led_show[len++] = default_value;
	led_show[len++] = Set_mode;
	switch(Set_mode)
	{
		case 0x01:
		{
			led_show[len++] = Light_strength;
			break;
		}
		case 0x02:
		{
			led_show[len++] = 0x00;
			memcmp(&led_show[len],Light_period,48);
			len+=48;
			break;
		}
		default :
			printf("input mode error!\r\n");
	}
	crc16_L = crc16_ibm(&led_show[8],len-8)&0xff;
	crc16_H = crc16_ibm(&led_show[8],len-8)>>8;
	led_show[len++] = crc16_L;
	led_show[len++] = crc16_H;
	led_show[len++] = data_end;
	
	RS4851Send(led_show,len);
//	for(int i = 0;i<len;i++)
//	{
//		printf("led_show[%d] = %x\r\n",i,led_show[i]);
//	}
}
//屏幕系统复位
/******************************************************************************
 * @函数名: void BX6K1_Reset(uint8_t Dstaddr)
 * @功  能: 屏幕系统复位  
 * @输  入: Dstaddr-屏地址 
 * @返  回: NULL
 * @备  注:
******************************************************************************/ 
void BX6K1_Reset(uint8_t Dstaddr)
{
	int crc16_L,crc16_H=0;
	int len=0;
	uint16_t send_length = 0;
	uint8_t led_show[128] = {0};
	
	memcpy(led_show,Bx_header,8);    //帧头
	len+=8;
	led_show[len++] = Dstaddr&0xff;
	led_show[len++] = Dstaddr>>8;
	led_show[len++] = header_SrcAddr&0xff;
	led_show[len++] = header_SrcAddr>>8;
	led_show[len++] = header_Reserved;
	led_show[len++] = header_Reserved;
	led_show[len++] = header_Reserved;
	led_show[len++] = header_BarCode;
	led_show[len++] = header_CheckMode;
	led_show[len++] = header_DisplayMode;
	led_show[len++] = 0xfe;								//通配符
	led_show[len++] = header_ProtocolVersion;
	led_show[len++] = Reset_len&0xff;
	led_show[len++] = Reset_len>>8;
	led_show[len++] = 0xA2;
	led_show[len++] = 0x01;
	led_show[len++] = 0x01;
	led_show[len++] = 0x00;
	led_show[len++] = 0x00;
	crc16_L = crc16_ibm(&led_show[8],len-8)&0xff;
	crc16_H = crc16_ibm(&led_show[8],len-8)>>8;
	led_show[len++] = crc16_L;
	led_show[len++] = crc16_H;
	led_show[len++] = data_end;
	RS4851Send(led_show,len);
}


//读指定屏幕地址的ID
void BX6K1_ReadID(uint16_t Dstaddr)
{
	

}



//控制卡返回的信息 -- -1--错误帧  0--无错误
uint8_t RecFrom_BX6K1(uint8_t *data)
{
//	int crc16_L,crc16_H=0;
//	int len=0;
	uint8_t CmdError = 0;						//命令处理状态
	int cmpres = memcmp(Bx_header,data,8);
	//包头数据
	if(cmpres == 0)
	{
		if(data[8]==0xA5&&data[30]==0x5A)
		{
			CmdError = data[25];	  //提取错误码
		}
		else
			CmdError = -1;
	}
	else
		CmdError = -1;
	return CmdError;
}

/******************************************************************************
 * @函数名: crc16_modbus(uint8_t *data, size_t length)
 * @功  能: 生成crc16校验位 
 * @输  入: data--要校验的数组  length-长度
 * @返  回: 校验结果
 * @备  注:
******************************************************************************/ 
uint16_t crc16_ibm(const uint8_t* data, uint16_t length) 
{
    uint16_t crc = 0x0000;
    uint16_t polynomial = 0xA001;
    for (uint16_t i = 0; i < length; i++) 
		{
				crc ^= data[i];
				for (uint8_t j = 0; j < 8; j++) {
						if (crc & 0x0001) {
								crc = (crc >> 1) ^ polynomial;
						} else {
								crc = crc >> 1;
						}
				}
    }
    return crc;
}
/******************************************************************************
 * @函数名: string_to_uint8_t_array(const char* str, size_t* length)
 * @功  能: 字符转uint8数组
 * @输  入: str -- 字符串  length--字符串的长度
 * @返  回: 转化得到的uint8_t数组
 * @备  注:
******************************************************************************/ 
uint8_t* string_to_uint8_t_array(const char* str, size_t* length) {
			
		if (str == NULL) {
        return NULL;
    }
    
    size_t str_length = strlen(str);
    uint8_t* ascii_array = (uint8_t*)malloc(str_length * sizeof(uint8_t));
    if (ascii_array == NULL) {
        return NULL;
    }
    
    for (size_t i = 0; i < str_length; ++i) {
        ascii_array[i] = (uint8_t)str[i];
    }
    
    *length = str_length;
    return ascii_array;
}

 

        在本系统中还移植了FreeRtos实时操作系统,在485发送任务中调用LED显示接口函数查看现象 ,以下是485发送任务的相关代码

void Pro485Task(void* p)
{
    int res = 0;
    BaseType_t xReturn = pdTRUE;
    p4851 = ComToUart(rs4851_port);
    p4852 = ComToUart(rs4852_port);
    Rs485Init();

    RS485BinarySem_Handle = xSemaphoreCreateBinary();
    if(NULL != RS485BinarySem_Handle)
    {
        DEBUG("RS485BinarySem_Handle create success!\r\n");
        p4851->callflag = 0;
        p4851->recvcallback = Pro4851_callback;
        p4852->callflag = 0;
        p4852->recvcallback = Pro4852_callback;
    }
    else
    {
        DEBUG("RS485BinarySem_Handle create error!\r\n");
        while(1)
        {
            vTaskDelay(1000);
        }
    }
		
		BX6K1_Show_String("\\C2深度0·01米",1);
		bsp_DelayMS(2000);
		BX6K1_SetLight(5,1,0x01,0);
//		BX6K1_Power(power_open,1);
    while(1)
    {
#if DEGUB_STACK
        printf("Stack Pro485Task:%d\n", uxTaskGetStackHighWaterMark(Pro485_Handle));
#endif

        xReturn = xSemaphoreTake(RS485BinarySem_Handle,   portMAX_DELAY);
	
        if(pdTRUE == xReturn)  //接收到信号量
        {
					  if(onceflag==0){
						onceflag=1;
            IDWG_Symbol=0xFF;
				    }

            if(p4851->callflag == 1)
            {
							
                DEBUG("4851 recv Semaphore\r\n");
                Pro485_rxlen = RS4851Recv(Pro485_rxbuf, PRO485_MAX_LEN);
                if(Pro485_rxlen)
                {
                    res = ProData(1, Pro485_rxbuf, Pro485_rxlen);
                    memset(Pro485_rxbuf, 0, PRO485_MAX_LEN);
                    p4851->callflag = 0;
                }
            }
            if(p4852->callflag == 1)
            {
                DEBUG("4852 recv Semaphore\r\n");
                Pro485_rxlen = RS4852Recv(Pro485_rxbuf, PRO485_MAX_LEN);
                if(Pro485_rxlen)
                {
                    res = ProData(2, Pro485_rxbuf, Pro485_rxlen);
                    memset(Pro485_rxbuf, 0, PRO485_MAX_LEN);
                    p4852->callflag = 0;
                }
            }
        }
				xEventGroupSetBits(xCreatedEventGroup, 0x10);
    }
}

正确显示现象应该显示 绿色 “深度0.01米” 如图4.1所示,LED屏幕显示正确。

标签:00,led,16LED,show,++,6K1,len,header,GD32F103VET6
From: https://blog.csdn.net/m0_60090007/article/details/139372689

相关文章