NXP-FRDM和串口屏通信(电力检测仪)
本帖最后由 Aaron~ 于 2018-11-20 15:35 编辑1.开发板说明
MCUFRDM-KE04Z
I/O 1路I/O IO检测:检测闸刀的导通还是断开ADC 3路AD CH1:电压采集(模拟数据采集) CH2:电流采集(模拟数据采集) Temp:温度采集(模拟数据采集)LED 工作指示灯按键 复位按键电源 USB 5V 电源输入
注:实现的功能:a.上电后发送指令屏的握手指令给串口屏,串口屏收到指令后回返回应答信息,当MCU没有收到应答信息时,串口屏显示开机界面同时MCU的LED灯为常亮。b. 当MCU收到串口屏的握手回应后,MCU通过页面转换指令进入“初始化系统”页面,显示倒计时5秒钟。c. 当倒计时页面到达5秒后便进入主界面,此时MCU LED工作指示灯以200ms间隔闪烁以示工作正常状态,主界面显示当前MCU采集ADC通道的数据值,同时显示闸刀开关的状态。d. MCU每3秒采用一次AD数据并更新到串口屏上。
需使用的工具a.硬件:FRDM-KE04Z体验板(MCU为KE04Z,串口TTL电平)。b.软件:Keil5c.原理图:详见“硬件原理图”文件夹。d.程序:串口屏工程配置文件通过SD卡下载DWIN_SET导入屏中即可。 KE04Z程序在“FRDM-KE04Z 源码”文件夹。2.评估板硬件和软件部分详细介绍硬件接口定义LED PTC5ADC1 数据模拟产生ADC2 数据模拟产生TXD2(触摸屏端子显示) PTB0RXD2(触摸屏端子显示) PTB1
硬件原理图请参照硬件原理图FRDM-KE04Z
软件程序界面工程配置文件参照DWIN_SET。KE04Z程序在“FRDM-KE04Z 源码”文件夹中。
界面工程0 开机界面:0X1000
MCU程序0)数据结构体与宏定义// 指令数据发送宏操作#define SEND_DATA(P) send_usart_data(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; // 系统程序版本号}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; // 指令参数 有效数据缓存区}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 us08p_len; //待发送的数据字节数 us08 *p_data; //指向数据缓存区的指针}DWIN_TEXT_STR;
1)main():硬件初始化,ADC数据采集,IO状态采集,接收触摸屏数据处理int main(void){float temp_v = 28.8f; // 当前温度值 float vol_v = 0.98f; // 当前采集的电压值 float cur_v = 0.58f; // 当前采集的电流值 us08sw_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灯 等待握手 LED0_On(); while(!p_sys_str->shake_ok){ // 处理迪文屏回应的数据 dwin_handle_porcess(); }
// 启动一个ID为0的软件定时器 时间间隔为3秒 soft_timer_start_auto(0, 15);
// 获取模拟采集量 和 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, 2); while(ENABLE){ // 处理迪文屏回应的数据 dwin_handle_porcess();
// 判断软定时器0 时间是否到达 if(soft_timer_check(1)){ LED0_Toggle(); }
// 判断软定时器0 时间是否到达 if(soft_timer_check(0)){
// 获取模拟采集量 和 IO状态检测 temp_v += 0.1;//get_temp_value(); vol_v+= 0.1;//get_adc_value(ADC_CH_VOL)*3.3f/4096.0f; cur_v+= 0.1;//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 = recvData; if(recvData == FRAME_TAIL1) rStatus = STAUS_O001; break;
case STAUS_O001: frameT.data = recvData; if(recvData == FRAME_TAIL2) rStatus = STAUS_O002; else rStatus = STAUS_START; break;
case STAUS_O002: frameT.data = recvData; if(recvData == FRAME_TAIL3) rStatus = STAUS_O003; else rStatus = STAUS_START; break;
case STAUS_O003: frameT.data = 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); 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); my_printf("\r\n"); } #endif if(this_hand_str == NULL) return; // 解析数据帧并进行相应处理 switch(frame->cmd1){ case NOTIFY_SHAKE: // 握手应答 if((frame->len != 2) && ((frame->data != 0x4F)&&(frame->data != 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.Count = _period; /* 实时计数器初值 */ s_tTmr.PreLoad = _period; /* 计数器自动重装值,仅自动模式起作用 */ s_tTmr.Flag = 0; /* 定时时间到标志 */ s_tTmr.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.Flag == 1 ){ s_tTmr.Flag = 0; return 1; } else{ return 0; }}7). show_temperature ():显示温度数据,文本显示void show_temperature(float data, us08 num_f){ us32 value; us08 text; 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 = value>>24; text = value>>16;; text = value>>8;; text = 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 = {0xBF, 0xAA}; us08 text0 = {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); }}
视频效果观看地址参照附件 这真是满满的干货,^_^。 飞思卡尔的片子不好采购吧 ysu_er 发表于 2018-11-23 19:21
飞思卡尔的片子不好采购吧
怎么讲? powerlabor001 发表于 2018-11-23 18:24
这真是满满的干货,^_^。
有建议也可以给出 FRDM-KE04Z淘寶上都有啊
页:
[1]