本文主要以迪文T5UIC1平台的指令屏作为试用对象,其他平台需进行改动后再使用。
一、开发板使用说明 1. 功能
注:实现的功能: a.上电后发送指令屏的握手指令给T5UIC1屏,T5UIC1屏收到指令后回返回应答信息,当MCU没有收到应答信息时,T5UIC1屏显示开机界面同时MCU的LED灯为常亮。 b. 当MCU收到T5UIC1屏的握手回应后,MCU通过页面转换指令进入“初始化系统”页面,显示倒计时5秒钟。 c. 当倒计时页面到达5秒后便进入主界面,此时MCU LED工作指示灯以200ms间隔闪烁以示工作正常状态,主界面显示当前MCU采集ADC通道的数据值,同时显示闸刀开关的状态。 d. MCU每3秒采用一次AD数据并更新到T5UIC1屏上。
2. 需使用的工具 a.硬件:硬石 STM32开发板(MCU为STM32F103ZET6,串口TTL电平)。 b. 软件: KEIL MDK5。 c.原理图:详见“硬件原理图”文件夹。 d.程序:T5UIC1屏工程配置文件在“T5UIC1屏 配置文件与图片”文件夹中,通过SD卡下载DWIN_SET导入屏中即可。 STM32程序在“STM32F103xx 源码”文件夹。
二、评估板硬件和软件部分详细介绍 1. 硬件原理图:详见“硬件原理图”文件夹 (1)硬件接口定义
功能
| 对应STM32F103的IO
|
| LED
| PB0 |
| ADC1
| PC1 |
| ADC2
| PC2 |
| TXD2(触摸屏端子显示)
| PA10 |
| RXD2(触摸屏端子显示)
| PA9 |
|
(2)硬件原理图
2. 软件程序
界面工程配置文件在“T5UIC1屏 配置文件与图片”文件夹中。
STM32程序在“STM32F103xx 源码”文件夹中。
(1)界面工程
0 开机界面:0X1000
(2)MCU程序
- [font=微软雅黑][size=3]<font size="4">0)数据结构体与宏定义
- // 指令数据发送宏操作
- #define SEND_DATA(P) comSendChar(TRANS_COM, P)
- #define TX_8(P1) SEND_DATA((P1)&0xFF) // send one byte
- #define TX_16(P1) TX_8((P1)>>8);TX_8(P1) // send two byte
- #define TX_32(P1) TX_16((P1)>>16);TX_16((P1)&0xFFFF) // send four byte
- #define BEGIN_CMD() TX_8(FRAME_HRAD)
- #define END_CMD() TX_32(FRAME_TAIL)
- // 系统结构体
- typedef struct{
- us08 shake_ok; // 握手成功标志位
- char version[16]; // 系统程序版本号
- }SYSTEM_STR;
- extern SYSTEM_STR g_sys_str, *p_sys_str;
- // 软定时结构体
- typedef struct{
- volatile us08 Mode; /* 计数器模式,1次性 */
- volatile us08 Flag; /* 定时到达标志 */
- volatile us32 Count; /* 计数器 */
- volatile us32 PreLoad; /* 计数器预装值 */
- }SOFT_TMR;
- // 应答处理回调函数结构体
- typedef struct{
- void (*handle_shake)(void); //应答处理
- }DWIN_HANDLE_STR;
- // 帧数据结构体
- typedef struct{
- us08 len; // 参数长度
- us08 cmd1; // 指令1
- us08 cmd2; // 指令2(预留)
- us08 data[MAX_DWIN_RX_LEN]; // 指令参数 有效数据缓存区
- }DWIN_DATA_STR;
- // 队列结构体
- typedef struct{
- DWIN_DATA_STR *Out; //指向数据输出位置
- DWIN_DATA_STR *In; //指向数据输入位置
- DWIN_DATA_STR *End; //指向Buf的结束位置
- DWIN_DATA_STR *Buf; //存储数据的空间
- us16 NData; //队列中数据个数
- us16 MaxData; //队列中允许存储的数据个数
- }DWIN_QUEUE_STR;
- // 文本属性结构体
- typedef struct{
- us08 mode; // 显示模式
- us16 sx, sy; // 字符串显示的左上角坐标
- us16 f_color, b_color; // 字符显示颜色 && 字符背景显示颜色
- us08 num_i; // 显示的整数位数,0x01-0x14
- us08 num_f; // 显示的小数位数,0x00-0x14,Num_I+Num_F 之和不能超过20
- us08 p_len; // 待发送的数据字节数
- us08 *p_data; // 指向数据缓存区的指针
- }DWIN_TEXT_STR;
- 1)main():硬件初始化,ADC数据采集,IO状态采集,接收触摸屏数据处理
- int main(void)
- {
- float temp_v = 9.8f; // 当前温度值
- float vol_v = 0.98f; // 当前采集的电压值
- float cur_v = 0.58f; // 当前采集的电流值
- us08 sw_v = 1; // 闸刀状态值
- // 清空系统结构体
- memset(&g_sys_str, 0, sizeof(SYSTEM_STR));
- p_sys_str = &g_sys_str;
- // 获取软件版本号
- date_formatting(p_sys_str->version);
- // 板级初始化(接口驱动初始化)
- init_bsp();
- // 初始化迪文屏 主要是初始化使用到的应用函数
- init_dwin();
- // 点亮LED灯 等待握手
- LED_ON;
- while(!p_sys_str->shake_ok){
- // 处理迪文屏回应的数据
- dwin_handle_porcess();
- }
- // 启动一个ID为0的软件定时器 时间间隔为3秒
- soft_timer_start_auto(0, 3000);
- // 获取模拟采集量 和 IO状态检测
- // 显示温度 电压 电流 闸刀状态
- temp_v = get_temp_value();
- vol_v = get_adc_value(ADC_CH_VOL)*3.3f/4096.0f;
- cur_v = get_adc_value(ADC_CH_CUR)*3.3f/4096.0f;
- sw_v = get_io_status();
- show_temperature(temp_v, 1);
- show_voltage(vol_v, 2);
- show_currents(cur_v, 2);
- show_gate_switch(sw_v);
- // 启动一个ID为1的软件定时器 时间间隔为500ms
- soft_timer_start_auto(1, 200);
- while(ENABLE){
- // 处理迪文屏回应的数据
- dwin_handle_porcess();
- // 判断软定时器0 时间是否到达
- if(soft_timer_check(1)){
- LED_TOGGLE;
- }
- // 判断软定时器0 时间是否到达
- if(soft_timer_check(0)){
- // 获取模拟采集量 和 IO状态检测
- temp_v = get_temp_value();
- vol_v = get_adc_value(ADC_CH_VOL)*3.3f/4096.0f;
- cur_v = get_adc_value(ADC_CH_CUR)*3.3f/4096.0f;
- sw_v = get_io_status();
- // 将获取到的数据量呈现到液晶屏
- show_temperature(temp_v, 1);
- show_voltage(vol_v, 2);
- show_currents(cur_v, 2);
- show_gate_switch(sw_v);
- }
- }
- 2). dwin_frame_pack ():从接口缓存区获取数据并组包
- void dwin_frame_pack(void)
- {
- us08 recvData;
- static us08 recvOffset = 0;
- static us08 rStatus = STAUS_IDLE;
-
- static DWIN_DATA_STR frameT;
- if(comGetChar(TRANS_COM, &recvData)){
- //my_printf("%02X ", recvData);
-
- switch(rStatus){
- case STAUS_IDLE:
- if(recvData == FRAME_HRAD)
- rStatus = STAUS_CMD1;
- break;
- case STAUS_CMD1:
- frameT.cmd1 = recvData;
- frameT.cmd2 = 0x00;
- frameT.len = 0;
- recvOffset = 0;
- rStatus = STAUS_START;
- break;
- case STAUS_CMD2:
- frameT.cmd2 = recvData;
- rStatus = STAUS_START;
- break;
- case STAUS_START:
- frameT.data[recvOffset++] = recvData;
- if(recvData == FRAME_TAIL1)
- rStatus = STAUS_O001;
- break;
- case STAUS_O001:
- frameT.data[recvOffset++] = recvData;
- if(recvData == FRAME_TAIL2)
- rStatus = STAUS_O002;
- else
- rStatus = STAUS_START;
- break;
- case STAUS_O002:
- frameT.data[recvOffset++] = recvData;
- if(recvData == FRAME_TAIL3)
- rStatus = STAUS_O003;
- else
- rStatus = STAUS_START;
- break;
- case STAUS_O003:
- frameT.data[recvOffset++] = recvData;
- if(recvData == FRAME_TAIL4)
- rStatus = STAUS_OVER;
- else
- rStatus = STAUS_START;
- break;
- }
- }
- if(rStatus == STAUS_OVER){
- #if 0 //for debug
- my_printf("%02X %02X %02X ", FRAME_HH, FRAME_HL, DGUSRecvLen);
- for(i = 0; i < DGUSRecvLen; i++)
- my_printf("%02X ", DGUSRecvBuff[i]);
- my_printf("\r\n\r\n");
- #endif
-
- frameT.len = recvOffset-4;
- queueAdd(&frameT);
- rStatus = STAUS_IDLE;
- }
- }
- 3). dwin_handle_porcess ():处理迪文屏回应的数据
- void dwin_handle_porcess(void)
- {
- us08 i = 6;
- DWIN_DATA_STR rFrame;
- DWIN_DATA_STR *frame = &rFrame;
- // 从迪文屏的串口缓存区中获取数据 并判断是否符合 迪文通信协议的帧结构
- while(i--){
- dwin_frame_pack();
- }
- // 从队列中获取数据帧
- if(dwin_frame_read(&rFrame)){
- return;
- }
- #if 0//SHOW_RECV_MSG
- {
- my_printf("\r\n");
- my_printf("> Recv: \r\n");
- my_printf(" cmd_type(cmd1): %02X\r\n", frame->cmd1);
- my_printf(" ctr_type(cmd2): %02X\r\n", frame->cmd2);
- my_printf(" data_len( ): %d\r\n", frame->len);
- my_printf(" data_msg( ): ");
- for(i = 0; i < frame->len; i++)
- my_printf("%02X ", frame->data[i]);
- my_printf("\r\n");
- }
- #endif
- if(this_hand_str == NULL) return;
- // 解析数据帧并进行相应处理
- switch(frame->cmd1){
- case NOTIFY_SHAKE: // 握手应答
- if((frame->len != 2) && ((frame->data[0] != 0x4F)&&(frame->data[1] != 0x4B)))
- return;
-
- if(this_hand_str->handle_shake != NULL)
- this_hand_str->handle_shake();
- break;
- }
- }
- 4). comSendBuf ():数据发送函数
- void comSendBuf(COM_PORT_E _ucPort, us08 *_ucaBuf, us16 _usLen){
- UART_T *pUart;
- pUart = ComToUart( _ucPort );
- if( pUart == 0 ){
- return;
- }
- if( pUart->SendBefor != 0 ){
- pUart->SendBefor( ); /* 如果是RS485通信,可以在这个函数中将RS485设置为发送模式 */
- }
- UartSend( pUart, _ucaBuf, _usLen );
- }
- 5). soft_timer_start_auto ():启动一个自动定时器,并设置定时周期
- void soft_timer_start_auto(uint8_t _id, uint32_t _period){
- if( _id >= TMR_COUNT ){
- /* 打印出错的源代码文件名、函数名称 */
- //BSP_Printf( "Error: file %s, function %s()\r\n", __FILE__, __FUNCTION__ );
- while( 1 ){
- ; /* 参数异常,死机等待看门狗复位 */
- }
- }
- DISABLE_INT( ); /* 关中断 */
- s_tTmr[_id].Count = _period; /* 实时计数器初值 */
- s_tTmr[_id].PreLoad = _period; /* 计数器自动重装值,仅自动模式起作用 */
- s_tTmr[_id].Flag = 0; /* 定时时间到标志 */
- s_tTmr[_id].Mode = TMR_AUTO_MODE; /* 自动工作模式 */
- ENABLE_INT( ); /* 开中断 */
- }
- 6). soft_timer_check ():检测定时器是否超时
- us08 soft_timer_check(uint8_t _id){
- if( _id >= TMR_COUNT ){
- return 0;
- }
- if( s_tTmr[_id].Flag == 1 ){
- s_tTmr[_id].Flag = 0;
- return 1;
- }
- else{
- return 0;
- }
- }
- 7). show_temperature ():显示温度数据,文本显示
- void show_temperature(float data, us08 num_f){
- us32 value;
- us08 text[4];
- DWIN_TEXT_STR textStr;
-
- switch(num_f){
- case 1:
- value = data*10;
- break;
-
- case 2:
- value = data*100;
- break;
-
- case 3:
- value = data*1000;
- break;
- default: return;
- }
- text[0] = value>>24;
- text[1] = value>>16;;
- text[2] = value>>8;;
- text[3] = value;
- textStr.sx = 130; textStr.sy = 50;
- dwin_fill_rect(textStr.sx, textStr.sy, textStr.sx+80, textStr.sy+50, ASSEMBLE_RGB(31, 33, 33));
- textStr.mode = 0;
- textStr.mode = FONT1632|DISABLE_NUM_BCOLOR|ENABLE_SIGNED_NUM|DISABLE_NUM_ZERO|DISABLE_NUM_ZERO_S;
- textStr.f_color = ASSEMBLE_RGB(0, 0, 255);
- textStr.p_len = 4;
- textStr.p_data = text;
- textStr.num_i = 8;
- textStr.num_f = num_f;
-
- dwin_disp_num(&textStr);
- }
- 8). show_gate_switch ():显示闸刀状态量,2D画图形式
- void show_gate_switch(us08 sw)
- {
- us08 text1[2] = {0xBF, 0xAA};
- us08 text0[2] = {0xB9, 0xD8};
- DWIN_TEXT_STR textStr;
-
- dwin_fill_rect(150, 199, 250, 231, ASSEMBLE_RGB(251, 146, 0));
- dwin_fill_rect(151, 200, 249, 230, ASSEMBLE_RGB(31, 33, 33));
- if(sw == 1){
- dwin_fill_rect(199, 201, 248, 229, ASSEMBLE_RGB(0, 255, 0));
-
- textStr.mode = 0;
- textStr.mode = DISABLE_TEXT_RESIZE|DISABLE_TEXT_BCOLOR|FONT1224;
- textStr.f_color = ASSEMBLE_RGB(0, 0, 0);
- textStr.p_len = 2;
- textStr.p_data = text1;
- textStr.sx = 215; textStr.sy = 203;
- dwin_disp_string(&textStr);
- }
- else{
- dwin_fill_rect(152, 201, 200, 229, ASSEMBLE_RGB(255, 0, 0));
- textStr.mode = 0;
- textStr.mode = DISABLE_TEXT_RESIZE|DISABLE_TEXT_BCOLOR|FONT1224;
- textStr.f_color = ASSEMBLE_RGB(0, 0, 0);
- textStr.p_len = 2;
- textStr.p_data = text0;
- textStr.sx = 165; textStr.sy = 203;
- dwin_disp_string(&textStr);
- }
-
- }</font>[/size][/font]
复制代码
|