• 通过modbus与串口屏通讯控制


    串口屏作为modbus主机,下位机主板作为从机,在从机中建立一张数据表与串口屏作为数据交换缓冲,从机移植freemodbus协议栈,定时响应串口屏的轮询

    如下,在一个项目中建立的数据表

    //上报给屏的槽状态
    typedef struct _db_slot_status{
        uint16_t            header_cnt_before_renewing; //换油前烹饪头数
        uint16_t            header_cnt_total;           //总计头数
        uint16_t            cooking_cnt_total;          //烹饪计数
        db_time_t           recvy_time;                 //槽回温时间
        db_time_t           cooking_time;               //烹饪时间
        uint16_t            temp;                       //槽温度
        uint16_t            target_temp;                //设定目标温度
        uint16_t            cooking_mode;               //关机模式,融油模式,节能模式,预热模式,烹饪模式,滤油模式
        uint16_t            cooking_seg;                //当前段号
        uint16_t            cooking_status;             //烹饪状态,1工作或0停止
        db_time_t           total_time;                 //烹饪的总时间
        uint16_t            preheat_highlight;          //预热位,一个位对应一个菜单,置1高亮
    }db_slot_status_t;
    
    //主板上报给屏的状态
    typedef union _db_status{
        uint16_t            zone[DB_STATUS_SIZE];
        struct{
            uint16_t            second;                     //主板时间秒
            uint16_t            minute;                     //主板时间分
            uint16_t            hour;                       //主板时间时
            uint16_t            day;                        //主板时间日
            uint16_t            month;                      //主板时间月
            uint16_t            year;                       //主板时间年
            uint16_t            week;                       //主板时间星期
    //        uint16_t            firmware_ver;               //固件版本
    //        uint16_t            hardware_ver;               //对应的硬件版本
    //        uint16_t            serial_number[4];           //序列号
    //        uint16_t            compile_date[12];           //编译日期
            uint16_t            cooking_cnt[DB_MENU_MAX];   //产品烹饪计数
            uint16_t            wifi_status;                //0-连接断开,1-连接WFI,2-连接服务器
            db_slot_status_t    slot_l_status;              //左槽状态
            db_slot_status_t    slot_r_status;              //右槽状态
        }data;
    }db_status_t;
    
    //自检数据
    typedef union _db_selftest{
        uint16_t        zone[DB_SELFTEST_SIZE];
        struct{
            uint16_t    input1;
            uint16_t    input2;
            uint16_t    input3;
            uint16_t    input4;
            uint16_t    input5;
            uint16_t    input6;
            uint16_t    left_temp;
            uint16_t    right_temp;
            uint16_t    cpu_temp;
            uint16_t    voltage;
            uint16_t    current;
        }data;
    }db_selftest_t;
    
    typedef struct _db_para{
        
        //这两组参数是用户操作的即时控制及上报,不需保存
        db_ctrl_t           ctrl;                           //控制参数
        db_status_t         status;                         //状态参数
    //    db_selftest_t       selftest;                       //自检状态
        //这两组参数需要保存到主板
        db_function_t       function;                       //功能参数
        db_cooking_menu_t   cooking_menu[DB_MENU_MAX];      //菜单参数
        
    }db_para_t;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    modbus初始化将modbus指针指向建立的数据表

     db_para_ptr = (db_para_t*)usSRegHoldBuf;
    
    • 1

    以下为modbus任务线程,检查数据是否有被用户修改,如被修改进行用户操作处理

    void mlcd_check_variation(void)
    {
        static uint8_t  crc=0,crc_new,user_update=0;
        static time_t  last_time;
        if( crc==0 ){
            //计算除去状态后的参数校验码
            crc = crc8_cal((uint8_t*)db_para_ptr+DB_START_ADDR, DB_SAVE_LEN);
        }
        
        //数据被用户通过屏幕修改
        crc_new = crc8_cal((uint8_t*)db_para_ptr+DB_START_ADDR, DB_SAVE_LEN);
        if( crc != crc_new ){
            crc = crc_new;
            last_time = time(RT_NULL);
            user_update = 1;
        }
        //用户更新10秒后保存数据
        else if( user_update ){
            if( time(RT_NULL)-last_time > 10 ){
                save_flag = 1;
                user_update = 0;
            }
        }
    }
    
    static void mlcd_task(void *parameter)
    {
        eMBInit( MB_RTU, 0x01, 2, 115200, MB_PAR_NONE );
        eMBEnable();
        rt_tick_t tick =  rt_tick_get();
        while(1){
            eMBPoll();
            
            mlcd_check_variation();
            
            tick_invent = rt_tick_get()-tick;
            if( tick_invent>200 )
                tick_cnt++;
            tick =  rt_tick_get();
            
            rt_thread_delay(10);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    由于串口屏是以地址方式定位数据单元,以下两个宏用于获取数据表中相应单元的地址比较简便的方法

    /** 计算结构体成员偏移地址 */  
    #define offsetof(TYPE, MEMBER) ((int)(&((TYPE *)0)->MEMBER))
    
    /** 根据成员地址获取结构首指针 */  
    #define container_of(ptr, type, member) ({   \
            const typeof( ((type *)0)->member ) *__mptr = (ptr); \
            (type *)( (char *)__mptr - offsetof(type,member) );})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这种方式驱动串口屏不用关心modbus通讯,只需关注数据是否被修改,如要显示显示,将数据表相应单元的填充数据即可

  • 相关阅读:
    java线程状态
    拿捏大厂面试,2022最新版的Java面试突击班手册
    【官方标准】- 交通运输领域元数据标准规范
    java参数传值
    为什么选择C/C++内存检测工具AddressSanitizer?如何使用AddressSanitizer?
    第10届蓝桥杯Scratch国赛真题集锦
    简单聊聊G1垃圾回收算法整个流程 --- 理论篇 -- 下
    天翼云铸牢国云安全,护航千行百业
    Oracle.xs.dll‘ for module DBD::Oracle: load_file:找不到指定的模块
    Go实现栈与队列基本操作
  • 原文地址:https://blog.csdn.net/dmjkun/article/details/133796051