海思3559万能平台搭建:ini定制协议输入①校正系统时间

简介: 海思3559万能平台搭建:ini定制协议输入①校正系统时间

前言

 平台的搭建除了海思本身对于音视频的处理,难免需要串口网口之类收发指令并做出处理;每个甲方爸爸对于协议的规定肯定有所差异,以最简单的校对系统时间为例,用网口发送协议,通过ini配置文件加载协议变量的方式实现免编译,只更新ini配置文件就可移植产品功能的作用

配置文件的使用

 最关键的变量加载办法详见

 海思3559万能平台搭建:配置文件iniparser的引入

配置文件编写

 新建配置文件如protocol.ini,按照约定格式编写配置文件内容,规定包长21位 包头为0x55,0xAA,识别时间校对的功能码为0xAB


[attr]
ini_cmd_length_total = 21;
[content]
ini_cmd_head1 = 0x55;
ini_cmd_head2 = 0xAA;
[func_osd]
ini_cmd_func_osdenable = 0xA5;
ini_cmd_data_mode_osdoff = 1;
ini_cmd_data_mode_osdon = 2;
;2开1关
[func_time]
ini_cmd_func_timecorrect = 0xAB;

配置文件的加载

 按照约定的用法加载配置文件

static int ini_cmd_length_total;//协议规定的包长度
static int ini_cmd_head1;//协议规定的第一个包头B1
static int ini_cmd_head2;//协议规定的第二个包头B2
static int ini_cmd_length;//协议包内的的包长B3
// static int ini_cmd_func;//协议规定的功能码B4
// static int ini_cmd_data_mode;//协议规定的数据区工作模式B5
static int ini_cmd_func_osdenable = 0;//协议规定的OSD功能码B4
static int ini_cmd_data_mode_osdon = 0;//协议规定的OSD数据区工作模式B5
static int ini_cmd_func_timecorrect = 0;//协议规定的时间校正B4
static int ini_cmd_data_mode_timetype = 0;//协议规定的时间校正类型B5
HI_S32 protocol_ini_init()
{
    dictionary  *   ini ;
    ini = iniparser_load(PROTOCOLPATH);
    if (ini==NULL) {
        fprintf(stderr, "cannot parse file: %s\n", PROTOCOLPATH);
        return -1 ;
    }
    SAMPLE_PRT("config protocol file load success!\n");
    ini_cmd_length_total           = iniparser_getint(ini,"attr:ini_cmd_length_total",-1);
    ini_cmd_head1                  = iniparser_getint(ini,"content:ini_cmd_head1",-1);
    ini_cmd_head2                  = iniparser_getint(ini,"content:ini_cmd_head2",-1);
    ini_cmd_func_osdenable         = iniparser_getint(ini,"func_osd:ini_cmd_func_osdenable",-1);
    ini_cmd_data_mode_osdon        = iniparser_getint(ini,"func_osd:ini_cmd_data_mode_osdon",-1);
    ini_cmd_func_timecorrect       = iniparser_getint(ini,"func_time:ini_cmd_func_timecorrect",-1);
    SAMPLE_PRT("ini_cmd_head1 is 0x%x\n",ini_cmd_head1);
    SAMPLE_PRT("ini_cmd_head2 is 0x%x\n",ini_cmd_head2);
    SAMPLE_PRT("ini_cmd_func_osdenable is 0x%x\n",ini_cmd_func_osdenable);
    SAMPLE_PRT("ini_cmd_data_mode_osdon is %d\n",ini_cmd_data_mode_osdon);
    SAMPLE_PRT("ini_cmd_func_timecorrect is 0x%x\n",ini_cmd_func_timecorrect);
    iniparser_freedict(ini);//释放dictionary对象(内存)  
    return 0;
}

协议处理

 以网口为例,收到数据后进入协议解析函数

/*描述  :网口接收线程
 *参数  :arg 无参数传入
 *返回值:无
 *注意  :使用需打开网口服务器端
 */
HI_VOID * eth_client_recv_task(HI_VOID *arg)
{
  cpu_set_t mask;//cpu核的集合
    cpu_set_t get;//获取在集合中的cpu
    int num = sysconf(_SC_NPROCESSORS_CONF);
    printf("frame_check_task:system has %d processor(s)\n", num);
    CPU_ZERO(&mask);//置空
    CPU_SET(0, &mask);//设置亲和力值
    if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0)//设置线程CPU亲和力
    {
        fprintf(stderr, "set thread affinity failed\n");
    }
    if (pthread_getaffinity_np(pthread_self(), sizeof(get), &get) < 0)//获取线程CPU亲和力
    {
        fprintf(stderr, "get thread affinity failed\n");
    }
  int connect_fd = -1;
    int recv_len;
  struct sockaddr_in server;
  socklen_t saddrlen = sizeof(server);
  // uint8 data_header[] = {0x55, 0xAA};
  // unsigned char addchk=0;
  // uint8 data_header[] = {0x55, 0xAA};
  // printf("\nbeforen DataParser\n ");
  // DataParser *data_parser = parser_init(data_header, sizeof(data_header), NULL, 0, CMD_LENGTH);
  // printf("\nDataParser INIT SUCCESS\n ");
  // char* tmp_cmd=(char*)&g_trk_cmd;
  memset(&server, 0, sizeof(server));
  connect_fd = socket(AF_INET, SOCK_STREAM, 0);
  if (connect_fd < 0)
  {
  printf("socket error!\n");
  // return NULL;
  }
    printf("\nETH CLIENT RECV TEST\n");
  server.sin_family = AF_INET;
  server.sin_port = htons(SERVER_PORT);
  // server.sin_addr.s_addr = inet_addr(SERVER_IP);
  server.sin_addr.s_addr = inet_addr(server_ip);
  if (connect(connect_fd, (struct sockaddr *)&server, saddrlen) < 0)
  {
  printf("connect failed!\n");
  // return -1;
  }
  // char PLATFORM_IP_SET[64]={0};
  // char PLATFORM_IP_CMD[]="192.168.0.168";
  // sprintf(PLATFORM_IP_SET,"ifconfig eth0 %s up",PLATFORM_IP_CMD);
  // system(PLATFORM_IP_SET);
  else
  {
  char recvbuf[1024]={0};
  while (1)
  {
    recv_len = read(connect_fd, recvbuf, sizeof(recvbuf));
    if(recv_len)
    {
    // printf("\nEth:recv origin data: ");
    // recvbuf[len] = '\0';  
    for (int i = 0;i < recv_len ;i++)
    {
      printf("%02x  ",recvbuf[i]);  
    }
    printf("\n"); 
    protocol_parser(recvbuf,recv_len);
    }
  }
  close(connect_fd);
  }
  return 0;
}

 解析方法也很简单,规定一下协议

6d659ac540944e92983c9698268d546a.png

 时间类型:uint8,当前版本固定为0x00;

 年:uint8,年份-2000;

 月:uint8,月份,取值范围1-12;

 日:uint8,日期,取值范围1-31;

 毫秒:uint32,当前时间的毫秒计数。

HI_S32 protocol_parser(char* recvbuf,int recv_len)
{
    HI_S32 i;
    // HI_U8 data_header[] = {0x55, 0xAA};
    HI_U8 data_header[] = {ini_cmd_head1, ini_cmd_head2};
  HI_U8 addchk=0;
  DataParser *data_parser = parser_init(data_header, sizeof(data_header), NULL, 0, ini_cmd_length_total);
  char* tmp_cmd=(char*)&g_trk_cmd;
    /* 解析协议内容 */
    for (i = 0;i < recv_len ;i++)
    {
        // printf("%02x  ",recvbuf[i]);  
        if(parser_put_data(data_parser, recvbuf[i]) == RESULT_TRUE)
        {
            /* 赋值给临时结构体tmp_cmd */
            tmp_cmd=(char*)&g_trk_cmd;
            addchk = 0;
            for(int jj=0;jj<sizeof(g_trk_cmd)-sizeof(data_header);jj++)
            {
                tmp_cmd[jj+2]=parser_get_data(data_parser, jj);
                // printf("%x ",tmp_cmd[jj+2]);
            }
            // printf("\n");
             /* 校验尾 */
            for(int kk = 2;kk < sizeof(g_trk_cmd)-1;kk++)
            {
                // addchk += parser_get_data(data_parser, kk);
                addchk+=tmp_cmd[kk];
                // printf("%x ",tmp_cmd[kk]);
            }
            // printf("\n");
            g_trk_cmd.addchk = parser_get_data(data_parser,(ini_cmd_length_total-1-2));//第19个数,从0开始计18,故-1,又因为去头在-2
            // printf("g_trk_cmd.addchk is %x\n",g_trk_cmd.addchk);
            if(addchk != g_trk_cmd.addchk )
            {
                printf("warning:please check format :tail\n");
                printf("addchk is %x\n",addchk);
                memset_s(((uint8_t*)&g_trk_cmd)+2,
                           sizeof(g_trk_cmd)-sizeof(data_header),
                           0,
                           sizeof(g_trk_cmd)-sizeof(data_header));
                continue;
            }
            else
            {
                /* 校验成功则往结构体赋值 */
                g_trk_cmd.length  = tmp_cmd[2];
                // printf(" tmp_cmd[2]is %x\n",tmp_cmd[2]);
                g_trk_cmd.CmdType = tmp_cmd[3];
                // printf(" tmp_cmd[3]is %x\n",tmp_cmd[3]);
                for (int ii = 0; ii < (ini_cmd_length_total-1-2-2) ;ii++)//去头-2去尾-1去功能-1从0开始计数-1
                {
                    g_trk_cmd.Para[ii] = tmp_cmd[ii+4];;
                }
            }
        }
    }
    if (g_trk_cmd.CmdType == ini_cmd_func_timecorrect)
    {
        printf("time correct\n");
        unsigned char tmp_year  = g_trk_cmd.Para[1];
        unsigned char tmp_month = g_trk_cmd.Para[2];
        unsigned char tmp_day   = g_trk_cmd.Para[3];
        unsigned int  tmp_ms    = (g_trk_cmd.Para[4]<<24)|(g_trk_cmd.Para[5]<<16)|(g_trk_cmd.Para[6]<<8)|(g_trk_cmd.Para[7]);
        SetSystemTime(tmp_year,tmp_month,tmp_day,tmp_ms);
    }
    return 0;
}

 没有直接传入时分秒,直接传入ms值也可以计算时间

/* 
 *描述  :协议规定的时间校准功能
 *参数  :uint32_t tyear  要设的年
 *        uint32_t tmonth 要设的月
 *        uint32_t tday   要设的日
 *        uint32_t tmsecs 要设的毫秒,用于转成时分秒
 *返回值:成功返回0
 *注意  :无
 */
int SetSystemTime(uint32_t tyear,uint32_t tmonth,uint32_t tday,uint32_t tmsecs)
{
    struct tm t_tm;
    struct timeval tv;
    time_t timep;
    uint32_t thour=0;
    uint32_t tminutes=0;
    uint32_t tseconds=0;
    thour = tmsecs / (1000 * 60 * 60);
    tminutes = (tmsecs % (1000 * 60 * 60)) / (1000 * 60);
    tseconds = (tmsecs % (1000 * 60)) / 1000;
    t_tm.tm_sec  = tseconds;
    t_tm.tm_min  = tminutes;
    t_tm.tm_hour = thour;
    t_tm.tm_mday = tday;
    t_tm.tm_mon  = tmonth - 1;
    t_tm.tm_year = tyear +2000- 1900;
    timep=mktime(&t_tm);
    stime(&timep);
    return 0;
}
相关文章
|
2月前
|
编解码
Jetson 学习笔记(十四):降低远程操控延时-修改屏幕分辨率
这篇文章是关于如何通过修改屏幕分辨率来降低Jetson Nano在远程操控时的延时。
96 3
Jetson 学习笔记(十四):降低远程操控延时-修改屏幕分辨率
|
2月前
|
监控 算法 数据安全/隐私保护
基于三帧差算法的运动目标检测系统FPGA实现,包含testbench和MATLAB辅助验证程序
本项目展示了基于FPGA与MATLAB实现的三帧差算法运动目标检测。使用Vivado 2019.2和MATLAB 2022a开发环境,通过对比连续三帧图像的像素值变化,有效识别运动区域。项目包括完整无水印的运行效果预览、详细中文注释的代码及操作步骤视频,适合学习和研究。
|
7月前
LabVIEW编更改研华数字板卡中DIO方向 例程与相关资料
LabVIEW编更改研华数字板卡中DIO方向 例程与相关资料
37 2
2023年电赛---运动目标控制与自动追踪系统(E题)OpenART mini的代码移植到OpenMV
2023年电赛---运动目标控制与自动追踪系统(E题)OpenART mini的代码移植到OpenMV
224 0
|
存储 内存技术
从简单的文件偏移、读写进一步研究MCU程序的下载和软件升级(上)
从简单的文件偏移、读写进一步研究MCU程序的下载和软件升级(上)
63 0
|
存储 编解码 关系型数据库
案例分享:Qt激光加工焊接设备信息化软件研发(西门子PLC,mysql数据库,用户权限控制,界面设计,参数定制,播放器,二维图,rgv小车,期限控制,参数调试等)
国产大型机床中Qt上位机激光焊接系统软件案例分享,介绍了Qt在国产化机床上的各种应用案例,并附上案例的具体功能界面供大家学习
案例分享:Qt激光加工焊接设备信息化软件研发(西门子PLC,mysql数据库,用户权限控制,界面设计,参数定制,播放器,二维图,rgv小车,期限控制,参数调试等)
|
传感器 安全 API
|
存储 芯片
复习单片机:8*8点阵---->点亮数字0(内含:1.设计思路+2.数字0的编程数据+3.原始代码+4.实验现象)(注:获得编程数据工具的下载和使用放在下一篇文章)
复习单片机:8*8点阵---->点亮数字0(内含:1.设计思路+2.数字0的编程数据+3.原始代码+4.实验现象)(注:获得编程数据工具的下载和使用放在下一篇文章)
468 0
复习单片机:8*8点阵---->点亮数字0(内含:1.设计思路+2.数字0的编程数据+3.原始代码+4.实验现象)(注:获得编程数据工具的下载和使用放在下一篇文章)
触摸屏实验(触摸屏介绍+硬件设计+软件设计。注:软件部分代码过长,理解即可)
触摸屏实验(触摸屏介绍+硬件设计+软件设计。注:软件部分代码过长,理解即可)
185 0
触摸屏实验(触摸屏介绍+硬件设计+软件设计。注:软件部分代码过长,理解即可)
|
存储 编解码 关系型数据库
案例分享:Qt工程机械真空激光焊接系统软件产品定制(西门子PLC,mysql数据库,用户权限控制,界面配置,参数定制,播放器,二维图标,rgv小车,期限控制,参数调试等)
基于Qt的真空焊接系统工程机械案例分享。1.ui由本司美工承担设计,显示分辨率1280 x 1024,同时支持鼠标操作。2.权限控制:三种权限,分为管理员(可以定制模块界面,修改产品名称等定制化软件和其他权限,同时具备编程员和操作员权限),编程员(新建工件,参数,调试功能等与生产相关的权限,同时具备操作员权限),操作员(加工相关的操作权限),三个等级对所有界面进行区分使用,并可进行管理;3.专家可增删改编程员,操作员;编程员可增删改操作员;4.与西门子PLC通讯,兼容S7全系,项目使用S7-1500...
案例分享:Qt工程机械真空激光焊接系统软件产品定制(西门子PLC,mysql数据库,用户权限控制,界面配置,参数定制,播放器,二维图标,rgv小车,期限控制,参数调试等)