搜索
bottom↓
回复: 6

NXP-FRDM和串口屏通信(电力检测仪)

[复制链接]

出0入0汤圆

发表于 2018-11-20 15:19:26 | 显示全部楼层 |阅读模式
本帖最后由 Aaron~ 于 2018-11-20 15:35 编辑

1.开发板说明
MCU  FRDM-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.软件:Keil5
c.原理图:详见“硬件原理图”文件夹。
d.程序:串口屏工程配置文件通过SD卡下载DWIN_SET导入屏中即可。 KE04Z程序在“FRDM-KE04Z 源码”文件夹。
2.评估板硬件和软件部分详细介绍
硬件接口定义
LED    PTC5
ADC1    数据模拟产生
ADC2    数据模拟产生
TXD2(触摸屏端子显示)    PTB0
RXD2(触摸屏端子显示)    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[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 = 28.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灯 等待握手
        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[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);
        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[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);
    }
}




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2018-11-23 15:25:55 | 显示全部楼层
视频效果观看地址参照附件

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2018-11-23 18:24:24 | 显示全部楼层
这真是满满的干货,^_^。

出0入0汤圆

发表于 2018-11-23 19:21:19 来自手机 | 显示全部楼层
飞思卡尔的片子不好采购吧

出0入0汤圆

 楼主| 发表于 2018-11-28 17:12:06 | 显示全部楼层
ysu_er 发表于 2018-11-23 19:21
飞思卡尔的片子不好采购吧

怎么讲?

出0入0汤圆

 楼主| 发表于 2018-11-29 17:09:28 | 显示全部楼层
powerlabor001 发表于 2018-11-23 18:24
这真是满满的干货,^_^。

有建议也可以给出

出0入0汤圆

发表于 2018-12-7 08:16:29 | 显示全部楼层
FRDM-KE04Z淘寶上都有啊
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-29 22:22

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表