通过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;

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

 db_para_ptr = (db_para_t*)usSRegHoldBuf;

以下为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);
    }
}

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

/** 计算结构体成员偏移地址 */  
#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) );})

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在昆仑通态触摸屏连接 USB 扫码枪的程序案例中,首先我们需要确保触摸屏和扫码枪的硬件设备已经正确连接好。 接下来,我们需要编写一个能够读取扫码枪数据的程序。可以利用常见的编程语言如C++、Python等来完成。首先,我们需要调用操作系统提供的 USB 接口来与扫码枪进行通信。 然后,通过编程语言提供的方法,注册一个回调函数来接受扫码枪传输过来的数据。当用户使用扫码枪扫描条码时,我们的程序就会调用这个回调函数来处理接受到的数据。 在回调函数中,我们可以对接收到的数据进行解析和处理。根据条码的格式,可以选择不同的方法来解析数据。例如,如果是一维条码,可以通过扫码枪的说明文档来获取相关解析算法,从而提取条码的信息。 接着,我们可以根据解析出来的条码信息进行后续的操作。例如,可以将条码信息保存到数据库中,或者将其展示到触摸屏上供用户查看。 最后,为了实现触摸屏和扫码枪的交互,我们可以根据需求设计触摸屏界面,提供相关的操作按钮和提示信息给用户。用户可以通过触摸屏界面来触发扫码枪的扫描功能,并且可以看到扫码结果实时展示在触摸屏上。 总之,昆仑通态触摸屏连接 USB 扫码枪的程序案例中,主要包含了与扫码枪进行通信、数据解析和处理、以及触摸屏界面设计等几个关键步骤,通过合理编写程序,能够实现扫码枪的功能并与触摸屏实现交互。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

纵向深耕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值