嵌入式系统各单元数据同步框架适用于网状,线性通信网络,适用于嵌入式操作系统以及状态机裸机开发

AF_SYNC通信架构

  • 前言

af_sync数据同步框架,旨在解决复杂通信问题;在强度稍微高一点的项目,可能有五个模块甚至更多,你可能使用modbus协议来解决各模块的通信问题,但是这只适用于主从场景,在需要双向通信的场景就没那么适用了,这是这个框架诞生的意义。

  • 应对场景

场景一:A->B;  A->C;  B->A->C; C->A->B

场景二:A->B->C->A

场景三:A->B->C; C->B->A; B->A;

主要就是这三种场景,其他的场景都是基于这三个场景组合扩展出来更复杂的通信架构,这个架构的优点在于:能规范通信代码架构,方便后期维护;减少程序员开发时间,迅速构建通信方案;只需进行简单配置即可实现复杂的通信;通过地址和字符串绑定数据,方便快速添加数据源,非常灵活。缺点:列表形式进行轮询比对,会损失一部分效率;地址只是一个标识符,不是物理地址,与modbus有本质区别,不支持一条指令写多个地址,但是一个地址可自由定义长度;容易出现通信环路;这些都是待解决优化的地方,下面也会对应进行说明。

      

  • 源码介绍

代码由三部分构成,发送,赋值,接收;发送部分主要是轮询地址列表发送数据请求至外部设备;赋值部分提供了变量名赋值和地址赋值接口;接收部分主要是负责接收外部设备的数据请求。支持线程安全,也可以裸机运行。

af_sync.c
/*
  *Copyright(C) -
  *FileName: af_sync.c
  *Author: 我不是阿沸
  *Version: 9.0.1
  *Date: 2023.08.13
  *Description:  数据同步框架,目前接口功能比较完善,如遇问题可联系作者
  *Others:  使用接口前一定调用初始化接口,仅适配rt_thread,如需其他操作系统需修改部分代码
  *History:
  	 1.Date:2023/08/03
       Author:我不是阿沸
       适配迪文屏
     2.Date:2023/08/16
       Author:我不是阿沸
       适配can
     3.Date:2023/09/18
       Author:我不是阿沸
       增加相关接口以及超时机制
     4.Date:2023/10/01
       Author:我不是阿沸
       修复无限制发送bug
	 5.Date:2023/10/31
       Author:我不是阿沸
       增加在线离线事件回调接口以及心跳处理
	 6.Date:2023/11/24
       Author:我不是阿沸
       修改心跳机制,心跳包与其他数据包处理逻辑和普通数据包一样,同步超时调用离线接口
     7.Date:2023/11/28
       Author:我不是阿沸
       合并心跳计数与更新检测处理函数
	 8.Date:2023/12/05
       Author:我不是阿沸
	   修复数据列表第一位加入心跳类型会无限重发bug
	 9.Date:2023/12/25
       Author:我不是阿沸
	   修复在未连接状态继续进行数据上传操作bug
	 10.Date:2024/01/30
       Author:我不是阿沸
	   1.)xxxx提供绑定地址接口xxxx(已撤消)
	   2.)修改相关接受逻辑
	   3.)uForm与uRow类型不再适配diwen屏
	 11.Date:2024/01/31
       Author:我不是阿沸
	   1.)增加uVoid类型
	   2.)增加无感通信接口
	   3.)修复读指令无响应问题,这里说明:读指令中的长度位在本框架中无作用,不作任何处理,
		  任何一条读指令,返回的字节数在上位协议中已经约定好,此框架无法一次读取多个地址
		  或者一次写多个地址,不同于modbus等协议
	 12.Date:2024/02/3
       Author:我不是阿沸
	   1.)更改row类型编码逻辑与void类型一致
	   2.)修复心跳机制不调用离线接口bug
	   3.)暂存问题:ustring类型目前传输为小端模式,后期将全面修改
	 13.Date:2024/02/4
       Author:我不是阿沸
	   1.)完善form类型相关代码
	   2.)加入大小端模式配置,需要注意的是,大端模式是在小端操作系统上而言的
	   3.)uString修改为大端模式
	   4.)修复强制类型转换出错宕机bug
	 14.Date:2024/03/4
       Author:我不是阿沸
	   1.)增加上电离线回调
	 15.Date:2024/04/09
       Author:我不是阿沸
	   1.)修补Button类型存在的问题:增加Button类型的无感通信,修改Button的更新策略
	   2.)增加nonind通信环路保护
	 16.Date:2024/04/10
       Author:我不是阿沸
	   1.)修改strcmp为strncmp,降低风险
	 17.Date:2024/04/25
       Author:我不是阿沸
	   1.)修改af_name_list_set接口耗时问题
	   2.)增加af_sync_reconnect_init接口代替af_name_list_set,提供跟快的刷新速率
	   3.)无感通信由原来的一个节点扩增到n个节点,定义最大元素为50
	   4.)af_error接口增加对应错误元素索引的传递
	 18.Date:2024/06/20
       Author:我不是阿沸
	   1.)修复void类型,string类型,form/row类型无感传递死机问题
	 19.Date:2024/07/03
       Author:我不是阿沸
	   1.)修复string类型无感传递死机问题
	 20.Date:2024/07/18
       Author:我不是阿沸
	   1.)修复无感传递初始化时未找到对象赋值为0, 导致在0位置的心跳包无限制发送问题
	 21.Date:2024/08/13
       Author:我不是阿沸
	   1.)大版本迭代,本次迭代移除了一些无必要的类型定义,修改了更新数据的机制解决上一版本数据蜂拥造成的拥堵问题
	   2.)删除框架中关于类型的定义,只留下其他类型,心跳类型,按键类型
	   3.)修改缓存区为静态分配,一次性分配整张表,避免了缓冲区的冗余定义
	   4.)表中增加长度字段,避免冗余的类型定义
	   5.)修改心跳的机制,以及心跳时间的初始化方式
	   6.)修改更新数据为时间片的模式,能避免数据拥堵
	   7.)删除互斥接口,不再有互斥保护,互斥极大的影响了框架的性能,所以移除,目前未发现有线程安全的bug
	   8.)每个时间片可自由设置更新数据的条数,修改.h文件中的 TICK_UPDATE_NUMBER
	   9.)其他若干修改与上一版本不再兼容,请注意版本兼容问题
	 22.Date:2024/08/19
       Author:我不是阿沸
	   1.)修复回调返回FALSE,无感通信依然传递新数据问题
	 23.Date:2024/10/31
       Author:我不是阿沸
	   1.)修复回调函数强转指针概率性丢失数据的问题
	   2.)修复无感通信主机端存在该参数,透传端不存在造成的通信死机问题
/


include "af_sync.h"



/**
  * @brief  通过名字超找单元,并返回单元索引
  * @param  变量名
  * @param  变量值
  * @retval None
  */
int af_uint_name_find(af_sync_admin af, afu8 name)
{
    AF_DATA_TYPE index = -1;
    for(int i = 0; i < af->number; i++)
    {
        if(strncmp((const char )name, (const char )(af->body_list[i].name), AF_NAME_LEN) == 0)
        {
            index = i;
            break;
        }
    }
    return index;
}


/**
  * @brief  框架必须存在写请求,写回复,读请求,读回复
  * @param  变量名
  * @param  变量值
  * @retval None
  */
static void af_sync_send_buffer(af_agree_body body, unsigned short addr, unsigned char cmd, unsigned char data, int len)
{
    int send_len = 0;
    if(body == NULL) return;
    switch(cmd)
    {
    case AF_SYNC_WRITE_REQUST:
        send_len = body->write_requst(body->send_buffer, addr, data, len);
        break;
    case AF_SYNC_WRITE_REPORT:
        send_len = body->write_report(body->send_buffer, addr);
        break;
    case AF_SYNC_READ_REQUST:
        send_len = body->read_requse(body->send_buffer, addr, len);
        break;
    case AF_SYNC_READ_REPORT:
        send_len = body->read_report(body->send_buffer, addr, data, len);
        break;
    }
    body->send(body->send_buffer, send_len);
}



/**
  * @brief  通过变量名置位向外读取数据标志
  * @param  变量名
  * @param  变量值
  * @retval None
  */
void af_uint_name_get(af_sync_admin af, afu8 name)
{
    int index = af_uint_name_find(af, name);
    if(index > -1)
    {
        af->body_list[index].rush_flag = AF_READ_FLAG;
    }

    return;
}


/**
  * @brief  通过名字同步两个同步管理机的数据
  * @param  变量名
  * @param  变量值
  * @retval None
  */
void af_struct_name_sync(af_sync_admin dec, af_sync_admin src, afu8 *name)
{
    void *buffer = 0;
    afu8 flag = 0;
    for(int i = 0; i < src->number; i++)
    {
        if(strncmp((const char )name, (const char )(src->body_list[i].name), AF_NAME_LEN) == 0)
        {
            buffer = src->body_list[i].ptr;
            flag = 1;
            break;
        }
    }
    if(flag == 0) return;

    for(int i = 0; i < dec->number; i++)
    {
        if(strncmp((const char )name, (const char )(dec->body_list[i].name), AF_NAME_LEN) == 0)
        {
            af_unit_body *body = dec->body_list + i;
            if(memcmp((void )body->ptr, (void )buffer, body->len) != 0)
            {
                memcpy((void )(body->ptr), (const void )buffer, body->len);
                body->rush_flag = AF_WRITE_FLAG;
            }
            break;
        }
    }
    return;
}


/**
  * @brief  通过变量名置位向外读取数据标志
  * @param  变量名
  * @param  变量值
  * @retval None
  */
void  af_uint_name_read(af_sync_admin af, afu8 *name)
{
    int index = af_uint_name_find(af, name);
    if(index > -1)
    {
        return af->body_list[index].ptr;
    }

    return NULL;
}


/**
  * @brief  通过地址同步两个同步管理机的数据
  * @param  变量名
  * @param  变量值
  * @retval None
  */
void af_struct_addr_sync(af_sync_admin dec, af_sync_admin src, afu16 addr)
{
    void *buffer = NULL;
    afu8 flag = 0;
    for(int i = 0; i < src->number; i++)
    {
        if(addr == src->body_list[i].addr)
        {
            buffer = src->body_list[i].ptr;
            flag = 1;
            break;
        }
    }
    if(flag == 0) return;

    for(int i = 0; i < dec->number; i++)
    {
        if(addr == dec->body_list[i].addr)
        {
            af_unit_body *body = dec->body_list + i;
            if(memcmp((void )body->ptr, (void )buffer, body->len) != 0)
            {
                memcpy((void )(body->ptr), (const void )buffer, body->len);
                body->rush_flag = AF_WRITE_FLAG;
            }
            break;
        }
    }
    return;
}


/**
  * @brief  通过变量地址置位向外写数据标志
  * @param  变量地址
  * @param  变量值
  * @retval None
  */
void af_uint_addr_set(af_sync_admin af, afu16 addr, void buffer)
{
    for(int i = 0; i < af->number; i++)
    {
        if(addr == af->body_list[i].addr)
        {
            af_unit_body *body = af->body_list + i;
            if(memcmp((void )body->ptr, (void )buffer, body->len) != 0)
            {
                memcpy((void )(body->ptr), (const void )buffer, body->len);
                body->rush_flag = AF_WRITE_FLAG;
            }
            break;
        }

    }
}


/**
  * @brief  通过变量地址置位向外写数据标志
  * @param  变量地址
  * @param  变量值
  * @retval None
  */
void af_uint_name_set_int(af_sync_admin af, void name, int buffer)
{
    for(int i = 0; i < af->number; i++)
    {
        if(strncmp((const char )name, (const char )(af->body_list[i].name), AF_NAME_LEN) == 0)
        {
            af_unit_body *body = af->body_list + i;
            if(memcmp((void )body->ptr, (void )&buffer, body->len) != 0)
            {
                memcpy((void )(body->ptr), (const void )&buffer, body->len);
                body->rush_flag = AF_WRITE_FLAG;
            }
            break;
        }

    }
}


/**
  * @brief  通过变量名置位向外写数据标志
  * @param  变量地址
  * @param  变量值
  * @retval None
  */
void af_uint_name_set(af_sync_admin af, afu8 name, void *buffer)
{
    for(int i = 0; i < af->number; i++)
    {
        if(strncmp((const char )name, (const char )(af->body_list[i].name), AF_NAME_LEN) == 0)
        {
            af_unit_body *body = af->body_list + i;
            if(memcmp((void )body->ptr, (void )buffer, body->len) != 0)
            {
                memcpy((void )(body->ptr), (const void )buffer, body->len);
                body->rush_flag = AF_WRITE_FLAG;
            }
			break;
        }
    }
}


/**
  * @brief  通过变量名置位强制向外写数据标志
  * @param  变量地址
  * @param  变量值
  * @retval None
  */
void af_uint_name_force_set(af_sync_admin af, afu8 name, void *buffer)
{
    for(int i = 0; i < af->number; i++)
    {
        if(strncmp((const char )name, (const char )(af->body_list[i].name), AF_NAME_LEN) == 0)
        {
            af_unit_body *body = af->body_list + i;
            memcpy(body->ptr, (const void *)buffer, body->len);
            body->rush_flag = AF_WRITE_FLAG;
            break;
        }

    }
}


/**
  * @brief  通过变量名置位强制向外写数据标志
  * @param  变量地址
  * @param  变量值
  * @retval None
  */
void af_uint_name_force_set_int(af_sync_admin af, afu8 name, afu32 data)
{
    for(int i = 0; i < af->number; i++)
    {
        if(strncmp((const char )name, (const char )(af->body_list[i].name), AF_NAME_LEN) == 0)
        {
            af_unit_body *body = af->body_list + i;
            memcpy(body->ptr, (const void *)&data, body->len);
            body->rush_flag = AF_WRITE_FLAG;
            break;
        }

    }
}



/**
  * @brief  断线重连更新
  * @param  需要重新刷新的数据名列表
  * @param  列表长度
  * @param  刷新标志,是读还是写
  * @retval None
  */
void af_name_list_set(af_sync_admin *af, af_clist list, afu32 len, af_sync_flag flag)
{
    for(int n = 0; n < len; n++)
    {
        for(int i = 0; i < af->number; i++)
        {
            if(strncmp((const char )list[n], (const char )(af->body_list[i].name), AF_NAME_LEN) == 0)
            {
                af_unit_body *body = af->body_list + i;
                body->rush_flag = flag;
                break;
            }

        }
    }

}




/**
  * @brief  同步管理机的消息发送
  * @param  同步管理机
  * @param  同步的地址
  * @param  同步的数据
  * @param  同步的类型
  * @param  消息的类型、模式 读回复、写回复
  * @retval None
  */
void af_sync_message_transmit(af_sync_admin af, afu16 addr, void ptr, int len, af_message_mode mode)
{
    afu8 *buffer = af->send_buffer;

    switch(mode)
    {
    case AF_SYNC_WRITE_REQUST:
    case AF_SYNC_READ_REPORT:
    {
        if(len > AF_MAX_TRBUFF) len = AF_MAX_TRBUFF;
        memcpy(buffer, (const void *)ptr, len);

        if(af->alignment == AF_ALIGNMENT_MAX)
        {
            af_agree_buffer_toggle(buffer, len);
        }

        if(AF_SYNC_WRITE_REQUST == mode) af_sync_send_buffer(af->agree, addr, AF_SYNC_WRITE_REQUST, buffer, len);
        else if(AF_SYNC_READ_REPORT == mode) af_sync_send_buffer(af->agree, addr, AF_SYNC_READ_REPORT, buffer, len);
    }
    break;
    case AF_SYNC_READ_REQUST:
        af_sync_send_buffer(af->agree, addr, AF_SYNC_READ_REQUST, NULL, 0);
        break;
    case AF_SYNC_WRITE_REPORT:
        af_sync_send_buffer(af->agree, addr, AF_SYNC_WRITE_REPORT, NULL, 0);
        break;
    default:
        break;
    }

}


/**
  * @brief  视图更新线程
  * @param  同步管理机
  * @retval None
  */
void af_bodys_updata_handle(af_sync_admin *af)
{
    af_sync_cfg *sync_cfg = NULL;
	af_unit_body *body = NULL;
	
	af->tick++;
	
	for(int i = 0; i < TICK_UPDATE_NUMBER; )
	{
		if(af->cur_index < af->number)
		{
			body =  af->body_list + af->cur_index;
			
			if(body->type == uHeart)
			{
				if(body->rush_flag == AF_NONE_FLAG)
				{
					if(af->tick > af->heart_time)
					{
						body->rush_flag = AF_WRITE_FLAG;
						af->tick = 0;
					}
				}
			}
					
			if(af->cfg_list != NULL)
			{
				sync_cfg = af->cfg_list + af->cur_index;
			}
			
			if(body->rush_flag == AF_WRITE_FLAG)
			{
				if(af->reg_flag == AF_ONLINE && body->type != uHeart)
				{
					af_sync_message_transmit(af, body->addr, body->ptr, body->len, AF_SYNC_WRITE_REQUST);
					if(sync_cfg != NULL)
					{
						sync_cfg->rush_state = AF_WRITE_FLAG;
						sync_cfg->cur_rett = 0;
						sync_cfg->cur_time = 0;
						
					}
					
				}
				else if(body->type == uHeart)
				{
					af_sync_message_transmit(af, body->addr, body->ptr, body->len, AF_SYNC_WRITE_REQUST);
					if(sync_cfg != NULL)
					{
						sync_cfg->rush_state = AF_WRITE_FLAG;
					}
				}	
				i++;
				body->rush_flag = AF_NONE_FLAG;				
			}
			else if(body->rush_flag == AF_READ_FLAG)
			{
				if(af->reg_flag == AF_ONLINE && body->type != uHeart)
				{
					af_sync_message_transmit(af, body->addr, body->ptr, body->len, AF_SYNC_READ_REQUST);
					if(sync_cfg != NULL)
					{
						sync_cfg->rush_state = AF_READ_FLAG;
						sync_cfg->cur_rett = 0;
						sync_cfg->cur_time = 0;
					}
				}
				i++;
				body->rush_flag = AF_NONE_FLAG;
			}
			af->cur_index++;
		}
		else
		{
			af->cur_index = 0;
			break;
		}
	}
	
	if(af->cfg_list == NULL) return;
	
	for(int i = 0; i < af->number; i++)
	{
		sync_cfg = af->cfg_list + i;
		body =  af->body_list + i;
		if(sync_cfg->rush_state == AF_WRITE_FLAG || sync_cfg->rush_state == AF_READ_FLAG)
		{
			sync_cfg->cur_time++;
			if(sync_cfg->cur_time >= sync_cfg->out_time)
			{
				sync_cfg->cur_rett++;
				sync_cfg->cur_time = 0;

				if(sync_cfg->rush_state == AF_WRITE_FLAG)
				{
					af_sync_message_transmit(af, body->addr, body->ptr, body->len, AF_SYNC_WRITE_REQUST);
				}
				else if(sync_cfg->rush_state == AF_READ_FLAG)
				{
					af_sync_message_transmit(af, body->addr, body->ptr, body->len, AF_SYNC_READ_REQUST);
				}
			}
			if(sync_cfg->cur_rett >= sync_cfg->retry_time)
			{
				if(body->type == uHeart && af->offline != NULL )
                {
                    if(af->reg_flag == AF_ONLINE)
                    {
                        if(af->offline != NULL)
                        {
                            af->offline();
                        }
                    }
					af->reg_flag = AF_OFFLINE;
                }
				else if(af->error != NULL && af->reg_flag == AF_ONLINE)
				{
					af->error(AF_ERROR_OUTTIME, body->name);
				}
				sync_cfg->cur_rett = 0;
				sync_cfg->cur_time = 0;
				sync_cfg->rush_state = AF_NONE_FLAG;
			}
		}
	}
}


/**
  * @brief  数据同步管理者初始化,初始化不包含重发机制的初始化,记得调用 af_sync_repeat_init
  * @param  视图列表
  * @param  视图列表条目
  * @retval None
  */
int af_sync_admin_init(
    af_sync_admin *af,
    af_unit_body *list,
    int number,
    af_agree_body *agree,
    void *buffer,
    int len,
    af_error error)
{
	int i = 0, index = 0;
	
    af->body_list = list;

    af->cfg_list = NULL;
    af->tick = 1000;
    af->agree = agree;
    af->number = number;

    af->malloc_buffer = buffer;
    af->malloc_len = len;

    for(; i < number ; i++)
    {
        list[i].ptr = (afu8*)buffer + index;
        if(list[i].len / 4 == 1) index += 4;
        else if(list[i].len / 4  == 0) index += 4;
        else if(list[i].len % 4  == 0) index += (4 * list[i].len / 4);
        else index += (4 * list[i].len / 4 + 4);
        if(index > len) return -1;
    }


    af->error = error;

    af->reg_flag = AF_ONLINE;
    af->offline = NULL;
    af->online = NULL;

    af->nonind_number = 0;
    af->alignment = AF_ALIGNMENT_MAX;

    af->reconnect_flag = AF_NONE_FLAG;
    af->reconnect_number = 0;
    af->cur_index = 0;
    return len - index;
}

/**
  * @brief  同步初始化
  * @param  视图列表
  * @param  视图列表条目
  * @retval None
  */
void af_sync_repeat_init(af_sync_admin af, af_sync_cfg cfg, afu16 out_time, afu16 retry_time)
{
    if(cfg == NULL) return;

    for(int i = 0; i < af->number; i++)
    {
        (cfg + i)->out_time = out_time;
        (cfg + i)->retry_time = retry_time;
        (cfg + i)->cur_rett = 0;
        (cfg + i)->cur_time = 0;
        (cfg + i)->rush_state = 0;
    }
    af->reg_flag = AF_OFFLINE;
    if(af->offline != NULL)
    {
        af->offline();
    }

    af->cfg_list = cfg;
    return;
}


/**
  * @brief  断线重连更新
  * @param  需要重新刷新的数据名列表
  * @param  列表长度
  * @param  刷新标志,是读还是写
  * @retval None
  */
void af_sync_reconnect_init(af_sync_admin *af, af_clist list, afu32 len, af_sync_flag flag)
{
    for(int n = 0; n < len && n < AF_MAX_VOID; n++)
    {
        for(int i = 0; i < af->number; i++)
        {
            if(strncmp((const char )list[n], (const char )(af->body_list[i].name), AF_NAME_LEN) == 0)
            {
                af_unit_body *body = af->body_list + i;
                af->reconnect_list[n] = i;
                break;
            }
            else
            {
                af->reconnect_list[n] = -1;
            }

        }
    }
    af->reconnect_flag = flag;
    af->reconnect_number = len;
}



/**
  * @brief  无感同步初始化
  * @param  视图列表
  * @param  视图列表条目
  * @retval None
  */
void af_sync_nonind_init(af_sync_admin af, af_nonind nonind, afu8 number)
{
    if(!af) return;
    if(!nonind) return;

    af->nonind = nonind;
    af->nonind_number = number;

    for(int n = 0; n < number; n++)
    {
        for(int i = 0; i < (nonind + n)->number && i < AF_MAX_VOID;i++)
        {

            for(int m = 0; m < af->number; m++)
            {
                if(strncmp((const char )((nonind + n)->list[i]), (const char )(af->body_list[m].name), AF_NAME_LEN) == 0)
                {

                    (nonind + n)->map[i].key = m;
                    break;
                }
                else
                {
                    (nonind + n)->map[i].key = -1;
                }
            }
			
            for(int m = 0; m < (nonind + n)->dec->number; m++)
            {
                if(strncmp((const char )((nonind + n)->list[i]), (const char )((nonind + n)->dec->body_list[m].name), AF_NAME_LEN) == 0)
                {
                    (nonind + n)->map[i].val = m;
                    break;
                }
                else
                {
                    (nonind + n)->map[i].val = -1;
                }
            }
			if((nonind + n)->map[i].key == -1 || (nonind + n)->map[i].val == -1)
			{
				(nonind + n)->map[i].key = -1;
				(nonind + n)->map[i].val = -1;
			}
        }
    }
    return;
}


/**
  * @brief  注册初始化,用于设备的在线和离线
  * @param  注册事件回调
  * @param  离线事件回调
  * @retval None
  */
void af_sync_register_init(af_sync_admin * af, int heart_time, af_register reg, af_register off)
{
    if(af == NULL) return;
	af->heart_time = heart_time;
	af->reg_flag = AF_OFFLINE;

    af->online = reg;
    af->offline = off;
    return;
}

/**
  * @brief  设置框架的大小端模式
  * @retval None
  */
void af_sync_aligment_init(af_sync_admin *af, af_alignment_mode mode)
{
    if(af == NULL) return;
    af->alignment = mode;
    return;
}


/**
  * @brief  用于接受外部发来的数据同步消息处理
  * @param  同步管理机
  * @param  事件
  * @param  数据,大端模式
  * @param  数据长度(字节),uString 数据类型的子类型为u8,所以u8为一个字, uRow子类型如果是u16 那u16就是一个字,以此类推
  * @retval None
  */
void af_sync_recv_handle(af_sync_admin af, af_agree_pare async)
{
    af_unit_body *body = NULL;

    af_sync_cfg *sync_cfg = NULL;

    afu16 addr = async->addr;
    afu32 len = async->len;
    afu16 cmd = async->cmd;
    
	if(async->len > AF_MAX_TRBUFF) async->len = AF_MAX_TRBUFF;
	memcpy(af->recv_buffer, async->data, async->len);
	afu8 buffer = (afu8 )af->recv_buffer;
	
    for(int i = 0; i < af->number; i++)
    {
        if(addr == af->body_list[i].addr)
        {
            body = af->body_list + i;

            if(af->cfg_list != NULL)
            {
                sync_cfg = af->cfg_list + i;
            }
            if(af->alignment == AF_ALIGNMENT_MAX)
            {
                af_agree_buffer_toggle(buffer, len);
            }
            switch(cmd)
            {
				//写请求和读回复,一个需要回复,一个不需要回复
				case AF_SYNC_WRITE_REQUST:
				case AF_SYNC_READ_REPORT:
				{
					if(len > body->len) len = body->len;
					if(body->handle != NULL)
					{
						afbool flag = body->handle(buffer, len);
						if(flag)
						{
							memcpy((void *)(body->ptr), buffer, len);
						}
					}
					else
					{
						memcpy((void *)(body->ptr), buffer, len);
					}
					if(body->type == uButton)
					{
						body->rush_flag = AF_WRITE_FLAG;
					}
					//如果存在无感通信
					for(int num = 0; num < af->nonind_number; num++)
					{
						if(af->nonind == NULL) break;
						for(int n = 0; n < af->nonind[num].number; n++)
						{
							if(af->nonind[num].map[n].key == i && af->nonind[num].map[n].val != -1)
							{
								af_sync_admin *dec_admin = af->nonind[num].dec;
								af_unit_body *dec_body = dec_admin->body_list + af->nonind[num].map[n].val;
								//强制更新
ifdef NONIND_PROTECT
								if(memcmp((const char )dec_body->data, (const char )buffer, len) != 0)
endif
								{
									memcpy((void )(dec_body->ptr), (const void )body->ptr, dec_body->len);
									dec_body->rush_flag = AF_WRITE_FLAG;
								}
								
								break;
							}
						}
					}
					
					if(cmd == AF_SYNC_WRITE_REQUST) //写请求
					{
						af_sync_send_buffer(af->agree, addr, AF_SYNC_WRITE_REPORT, NULL, 0);
					}
					else if(cmd == AF_SYNC_READ_REPORT)//读回复,需要清空标志位
					{
						if(sync_cfg != NULL)
						{
							sync_cfg->rush_state = AF_NONE_FLAG;
							sync_cfg->cur_rett = 0;
							sync_cfg->cur_time = 0;
						}
					}
				}
				break;
				//写回复,不许要回复,清空标志位就可
				case AF_SYNC_WRITE_REPORT:
				{
					if(body->type == uHeart && af->reg_flag == AF_OFFLINE)
					{
						af->reg_flag = AF_ONLINE;
						if(af->reconnect_flag != AF_NONE_FLAG)
						{
							for(int i = 0; i < af->reconnect_number; i++)
							{
								int index = af->reconnect_list[i];
								if(index > 0)
									af->body_list[index].rush_flag = af->reconnect_flag;
							}
						}
						if(af->online != NULL)
						{
							af->online();
						}
					}
					if(sync_cfg != NULL)
					{
						sync_cfg->rush_state = AF_NONE_FLAG;
						sync_cfg->cur_rett = 0;
						sync_cfg->cur_time = 0;
					}
				}
				break;
				//读请求,需要回复,与写请求的发送类似
				case AF_SYNC_READ_REQUST:
				{
					af_sync_message_transmit(af, addr, body->ptr, body->len, AF_SYNC_READ_REPORT);
				}
				break;

            }
			break;
        }
    }
}




af_sync.h
#ifndef __AF_SYNC_H
#define __AF_SYNC_H
#include "af_define.h"
#include "af_agree.h"

#define AF_DATA_TYPE afu32
#define AF_NAME_LEN 30
#define AF_MAX_TRBUFF   256
#define AF_MAX_VOID  80
#define AF_MAX_RECON_NUMBER	100
#define TICK_UPDATE_NUMBER 6

//该宏定义,只为保护在使用无感通信时造成的通信环路;
//当有出现通信环路(a->b->c->a 无限循环)开启宏可进行保护,当数据经过一轮循环返回给a时,数据会被截断不再转发,不开启则会出现环路,需要程序手动处理
//#define NONIND_PROTECT 
//#define AF_SYNC_WAIT_MODE

typedef char (*af_clist)[AF_NAME_LEN];

typedef afbool (*application)(void * ptr, int len);


	
typedef enum{
	uOther, //自定义类型
	uButton,//uButton 类型会回发写类型数据
	uHeart	//心跳类型
}af_type;


typedef struct
{
	afu8 rush_state; //刷新状态 0:刷新成功 1:刷新失败
	afu16 out_time;  //超时时间
	afu16 retry_time;//重试次数
	afu16 cur_time;  //内部计数用,无需配置
	afu16 cur_rett;  //内部计数用,无需配置
}af_sync_cfg; 		 //超时判断机制


typedef struct
{
	afu8 name[AF_NAME_LEN];     		//地址名 
	afu16 addr; 	    	//地址 
	af_type type; //数据类型 
	char len;
	void * ptr;    	//数据缓冲区,如果是数组类型,存储的就是buffer首地址,其他就是对应的具体值
	afu8 rush_flag;    		//刷新标志 
	application handle;     //外部数据同步回调,可用于处理发来的数据以及其他操作,这里特别注意,u32、u16、ubutton 与 其他类型使用方法不一样,详见附件说明
}af_unit_body;

typedef enum
{
	AF_SYNC_NONE = 0,
	AF_SYNC_WRITE_REQUST = 0x82,  //写请求
	AF_SYNC_WRITE_REPORT = 0x28,  //写回复
	AF_SYNC_READ_REQUST  = 0x83,  //读请求
	AF_SYNC_READ_REPORT  = 0x38    //读回复
}af_message_mode;

typedef enum
{
	AF_NONE,
	AF_ERROR_OUTTIME,
	AF_ERROR_MALLOC,
	
}af_error_type; //错误码


typedef enum
{
	AF_NONE_FLAG = 0,
	AF_WRITE_FLAG,
	AF_READ_FLAG,
}af_sync_flag; //同步码


enum
{
	AF_OFFLINE = 0,
	AF_ONLINE,
};

typedef enum
{
	AF_ALIGNMENT_MAX = 0,
	AF_ALIGNMENT_MIN,
}af_alignment_mode;

typedef void (* af_write_data)(afu16 addr, afu8 cmd, afu8 * buffer, int len); //外部通信接口
typedef void (* af_read_data)(afu16 addr, int len); //外部通信接口
typedef void (*af_error)(af_error_type error, afu8 * name);   //错误处理接口
typedef void (*af_register)(void);   //设备注册回调

typedef struct af_nonind_admin af_nonind;



typedef struct{
	af_unit_body * body_list;
	af_sync_cfg * cfg_list;
	af_agree_body * agree;
	
	afu32 cur_index;
	void * malloc_buffer;
	int malloc_len;
	afu16 tick;
	int number;//body_list 数量

	af_error error;//错误处理接口
	afu8 reg_flag;//注册标志
	af_register online;	
	af_register offline;
	int heart_time;//心跳时间
	af_nonind * nonind;//无感列表
	afu8 nonind_number;//无感数量
	afu8 alignment;//大小端
	
	afu16 reconnect_flag;
	int reconnect_list[AF_MAX_RECON_NUMBER];
	afu8 reconnect_number;
	afu8 send_buffer[AF_MAX_TRBUFF];
	afu32 recv_buffer[AF_MAX_TRBUFF/4];
}af_sync_admin;//管理机


struct af_nonind_admin
{
	af_sync_admin * dec;
	afumap map[AF_MAX_RECON_NUMBER];
	af_clist list;
	afu32 number;
};


int af_uint_name_find(af_sync_admin *af, afu8 *name);
void af_uint_name_get(af_sync_admin *af, afu8 *name);
void af_uint_name_force_set_int(af_sync_admin *af, afu8 *name, afu32 data);
void af_struct_name_sync(af_sync_admin *dec, af_sync_admin *src, afu8 *name);
void af_struct_addr_sync(af_sync_admin *dec, af_sync_admin *src, afu16 addr);
void af_uint_addr_set(af_sync_admin *af, afu16 addr, void * buffer);
void af_uint_name_set(af_sync_admin *af, afu8 *name, void * buffer);
void af_uint_name_set_int(af_sync_admin *af, void * name, int buffer);
void * af_uint_name_read(af_sync_admin *af, afu8 *name);
void af_uint_name_force_set(af_sync_admin *af, afu8 *name, void * buffer);
void af_name_list_set(af_sync_admin *af, af_clist list, afu32 len, af_sync_flag flag);
void af_sync_message_transmit(af_sync_admin *af, afu16 addr, void * ptr, int len, af_message_mode mode);
void af_bodys_updata_handle(af_sync_admin *af);
int af_sync_state_get(af_sync_admin *af);
int af_sync_admin_init(af_sync_admin *af,af_unit_body *list,int number,af_agree_body *agree,void * buffer,int len,af_error error);
void af_sync_repeat_init(af_sync_admin *af, af_sync_cfg *cfg, afu16 out_time, afu16 retry_time);
void af_sync_reconnect_init(af_sync_admin *af, af_clist list, afu32 len, af_sync_flag flag);
void af_sync_nonind_init(af_sync_admin *af, af_nonind *nonind, afu8 number);
void af_sync_register_init(af_sync_admin * af, int heart_time, af_register reg, af_register off);
void af_sync_aligment_init(af_sync_admin *af, af_alignment_mode mode);
void af_sync_recv_handle(af_sync_admin *af, af_agree_pare * async);
#endif







1.几个重要的宏定义

#define AF_NAME_LEN 20

#define AF_MAX_TRBUFF   100

AF_NAME_LEN:数据名最大长度。

AF_MAX_TRBUFF:数据发送最大缓冲区

  1. 支持传输的数据类型

数据类型

说明

长度

uInt16

16位无符号短整型变量

2字节

uInt32

32位无符号短整型变量

4字节

uString

8位无符号数组

自定义长度

uVoid

自定义类型

自定义长度

uButton

按键类型,16位无符号短整型变量,收到写请求,会回发写请求,可用于更新上位机操作状态。

2字节

uForm

表格类型,支持16位无符号短整型变量和32位无符号短整型变量

自定义长度

uRow

数组行类型,支持16位无符号短整型变量和32位无符号短整型变量

自定义长度

uHeart

心跳类型,16位无符号短整型变量

2字节

  1. 支持的请求

AF_SYNC_WRITE_REQUEST

写请求

0x82

AF_SYNC_WRITE_REPORT

写回复

0x28

AF_SYNC_READ_REQUEST

读请求

0x83

AF_SYNC_READ_REPORT

读回复

0x38

  1. 类型结构体说明

结构体名称

描述

成员变量

af_type_form

用于描述单元格的位置和数据类型。

- horizontal: 单元格的横坐标<br>- vertical: 单元格的纵坐标<br>- type: 自定义类型 af_type,表示单元格的数据类型

af_type_void

用于描述自定义类型的长度。

- len: 自定义类型的长度

af_type_row

用于描述行的位置和数据类型。

- horizontal: 行的横坐标<br>- type: 自定义类型 af_type,表示行的数据类型

af_type_string

用于描述字符串的长度。

- len: 字符串的长度

af_type_heart

用于描述心跳数据。

- time: 心跳时间<br>- count: 心跳次数

af_type_cfg

用于描述数据类型和相关配置。

- type: 自定义类型 af_type,表示数据的类型<br>- cfg: 指针,指向与该类型相关的配置信息

  1. 以下是对 af_sync_admin管理机 结构体的说明

成员变量

描述

成员变量

body_list

指向 af_unit_body 结构体数组的指针。

body_list

cfg_list

指向 af_sync_cfg 结构体数组的指针。

cfg_list

out_time

用于指定超时时间的 16 位无符号整数。

out_time

retry_time

用于指定重试时间的 16 位无符号整数。

retry_time

number

body_list 数组的元素数量。

number

rt_mutex_t

用于数据安全的实时线程互斥锁。

rt_mutex_t

write

外部通信接口。

write

error

错误处理接口。

error

reg_flag

注册标志,可能是 8 位无符号整数。

reg_flag

online

在线注册接口。

online

offline

离线注册接口。

offline

nonind

指向 af_nonind 结构体的指针。

nonind

alignment

对齐标志,可能是 8 位无符号整数。

alignment

af_sync_admin 结构体用于管理通信机制,它包含了各种用于数据同步和通信的配置、接口以及处理方法。

  1. 以下是对 af_sync_cfg 结构体的说明

成员变量

描述

成员变量

rush_state

刷新状态。0 表示刷新成功,1 表示刷新失败。

rush_state

out_time

超时时间,用于指定超时时长的 16 位无符号整数。

out_time

retry_time

重试次数,用于指定重试次数的 16 位无符号整数。

retry_time

cur_time

内部计数器,用于内部计数,无需配置。

cur_time

af_sync_cfg 结构体用于定义超时判断机制的配置参数,包括刷新状态、超时时间和重试次数。cur_time 和 cur_rett 是内部计数器,不需要外部配置,可能用于内部计数或其他用途

  1. 接口说明

函数名

描述

void af_sync_aligment_init(af_sync_admin * af, af_alignment_mode mode);

初始化同步管理器的对齐模式。

void af_sync_register_init(af_sync_admin * af, af_register reg, af_offline off);

初始化同步管理器的注册和离线状态。

void af_sync_repeat_init(af_sync_admin * af, af_sync_cfg * cfg, afu16 out_time, afu16 retry_time);

初始化同步管理器的重复操作配置,包括超时时间和重试次数。

void af_sync_recv_handle(af_sync_admin * af, afu8 cmd, afu16 addr, afu8 * buffer, afu16 len);

处理接收到的同步数据。

void af_sync_admin_init(af_sync_admin * af, af_unit_body * list, int number, af_write_data write, af_error error);

初始化同步管理器,包括单元体列表、数量、写入数据函数和错误处理函数。

void af_sync_nonind_init(af_sync_admin * af, af_nonind * nonind);

初始化非指示符。

void af_bodys_updata_handle(af_sync_admin * af);

处理单元体更新。

void af_uint_addr_receive(af_sync_admin * af, afu16 addr, AF_DATA_TYPE val);

接收地址类型的数据。

void af_uint_name_receive(af_sync_admin * af, afu8 * name, AF_DATA_TYPE val);

接收名称类型的数据。

void af_struct_name_sync(af_sync_admin * dec, af_sync_admin * src, afu8 * name);

同步结构体中指定名称的成员。

void af_struct_addr_sync(af_sync_admin * dec, af_sync_admin * src, afu16 addr);

同步结构体中指定地址的成员。

void af_uint_addr_set(af_sync_admin * af, afu16 addr, AF_DATA_TYPE val);

设置地址类型的数据。

void af_uint_name_set(af_sync_admin * af, afu8* name, AF_DATA_TYPE val);

设置名称类型的数据。

void af_uint_name_update(af_sync_admin * af, afu8 * name);

更新名称类型的数据。

void af_heart_handle(af_sync_admin * af);

处理心跳数据。

AF_DATA_TYPE af_uint_name_get(af_sync_admin * af, afu8 * name);

获取名称类型的数据。

void af_uint_name_force_set(af_sync_admin * af, afu8* name, AF_DATA_TYPE val);

强制设置名称类型的数据。

void af_name_list_set(af_sync_admin * af, af_clist list, afu32 len, af_sync_flag flag);

设置名称列表。

  • 使用范例

 首先注册一个需要同步的数据表:数据名,数据地址, 数据类型, 初始值,是否上电同步, 数据同步事件回调,这张表双端都是一样的,执行端如果有需要就配置相应的回调。

af_unit_body can1_list[] = 
{
	"type",		0xFFFF,  &u32_can, Rf, 		0, NULL,
	"r_im2",	0x2006,  &u32_can, 0, 		0, NULL,
	"r_im3",	0x2008,  &u32_can, 0, 		0, NULL,
	"ctr_cqm1", 0x2002,  &u32_can, 100000,  0, NULL,
	"ctr_cqm2", 0x2004,  &u32_can, 100000,  0, NULL,
	"ad_cqm1",	0x4012,  &u32_can, 0, 		0, NULL,
	"ad_cqm2", 	0x4014,  &u32_can, 0, 		0, NULL,
	"cqm_en", 	0x4018,  &u32_can, 0, 		0, NULL,
	"gnd_en", 	0x4016,  &u32_can, 0, 		0, NULL,
	"temp", 	0x1010,  &u32_can, 0, 		0, NULL,
	"outv",		0x4000,  &u32_can, 0, 		0, NULL,
	"outi",		0x4002,  &u32_can, 0, 		0, NULL,
	"m_outr",	0x4004,  &u32_can, 0, 		0, NULL,
	"outw",		0x4006,  &u32_can, 0, 		0, NULL,
	"ini", 		0x4008,  &u32_can, 0, 		0, NULL,
	"inv", 		0x400a,  &u32_can, 0, 		0, NULL,
	"inw", 		0x400e,  &u32_can, 0, 		0, NULL,
	"vm3", 		0x400c,  &u32_can, 0, 		0, NULL,
	"vm4", 		0x401e,  &u32_can, 0, 		0, NULL,
};
#include "sync.h"
#include "after.h"
#include "serial.h"
#include "gather.h"
#include "serial.h"
#include "handle.h"

typedef enum
{
	Measure,
	Rf,
	PowerSupply,
	HandShank
}Module_Type;


typedef struct
{
	unsigned short id;
	Module_Type type;
}af_module;

#define MASTER_ID 0x56
af_module af_module_pool[20];

void af_data_send(uint8_t * data, int len)
{
	can1_transmit(data, len);
}


/**
  * @brief  封装32位变量数据
  * @param  需要发送的ID,如果需要发送至多个ID,这个ID为板载类型ID,每种类型的板子都会有一个独特的ID,设置为0xff
  * @param	变量值
  * @retval None
  */
void af_write_reg_requst(unsigned short addr, unsigned int data)
{
	uint8_t buffer[20]; 
	buffer[0] = AF_SYNC_WRITE_REQUST;
	buffer[1] = MASTER_ID;
	buffer[2] = addr / 256;
	buffer[3] = addr % 256;
	
	buffer[4] = data >> 24;
	buffer[5] = data >> 16;
	buffer[6] = data >> 8;
	buffer[7] = data & 0xff;
	
	af_data_send(buffer, 8);
}

/**
  * @brief  封装32位变量数据
  * @param  变量地址
  * @param	变量值
  * @retval None
  */
void af_write_reg_reply(unsigned short addr)
{
	uint8_t buffer[20]; 
	buffer[0] = AF_SYNC_WRITE_REPORT;
	buffer[1] = MASTER_ID;
	buffer[2] = addr / 256;
	buffer[3] = addr % 256;
	
	buffer[4] = 0;
	buffer[5] = 0;
	buffer[6] = 0;
	buffer[7] = 0;
	
	af_data_send(buffer, 8);
}

/**
  * @brief  封装32位变量数据
  * @param  需要发送的ID,如果需要发送至多个ID,这个ID为板载类型ID,每种类型的板子都会有一个独特的ID,设置为0xff
  * @param	变量值
  * @retval None
  */
void af_read_reg_requst(unsigned short addr)
{
	uint8_t buffer[20]; 
	buffer[0] = AF_SYNC_READ_REQUST;
	buffer[1] = MASTER_ID;
	buffer[2] = addr / 256;
	buffer[3] = addr % 256;
	
	buffer[4] = 0xff;
	buffer[5] = 0xff;
	buffer[6] = 0xff;
	buffer[7] = 0xff;
	
	af_data_send(buffer, 8);
}

/**
  * @brief  封装32位变量数据
  * @param  变量地址
  * @param	变量值
  * @retval None
  */
void af_read_reg_reply(unsigned char id, unsigned short addr, unsigned int data)
{
	uint8_t buffer[20]; 
	buffer[0] = AF_SYNC_READ_REPORT;
	buffer[1] = id;
	buffer[2] = addr / 256;
	buffer[3] = addr % 256;
	
	buffer[4] = data >> 24;
	buffer[5] = data >> 16;
	buffer[6] = data >> 8;
	buffer[7] = data & 0xff;
	af_data_send(buffer, 8);
}

void can1_tran_buffer(unsigned short addr, unsigned char cmd, unsigned char * data, int len)
{
	switch(cmd)
	{
		case AF_SYNC_WRITE_REQUST: 
		{
			afu32 val = afu32_buffer_max(data);
			af_write_reg_requst(addr, val);
		}
			break;
		case AF_SYNC_WRITE_REPORT:
			af_write_reg_reply(addr);
			break;
	}
}



af_type_cfg u16_can = {uInt16, NULL};
AfScny afCan = {0, 0, 100, 3, 0, 0};
af_type_cfg u32_can = {uInt32, NULL};



af_unit_body can1_list[] = 
{
	"type",		0xFFFF,  &u32_can, Rf, 		0, NULL,
	"r_im2",	0x2006,  &u32_can, 0, 		0, NULL,
	"r_im3",	0x2008,  &u32_can, 0, 		0, NULL,
	"ctr_cqm1", 0x2002,  &u32_can, 100000,  0, NULL,
	"ctr_cqm2", 0x2004,  &u32_can, 100000,  0, NULL,
	"ad_cqm1",	0x4012,  &u32_can, 0, 		0, NULL,
	"ad_cqm2", 	0x4014,  &u32_can, 0, 		0, NULL,
	"cqm_en", 	0x4018,  &u32_can, 0, 		0, NULL,
	"gnd_en", 	0x4016,  &u32_can, 0, 		0, NULL,
	"temp", 	0x1010,  &u32_can, 0, 		0, NULL,
	"outv",		0x4000,  &u32_can, 0, 		0, NULL,
	"outi",		0x4002,  &u32_can, 0, 		0, NULL,
	"m_outr",	0x4004,  &u32_can, 0, 		0, NULL,
	"outw",		0x4006,  &u32_can, 0, 		0, NULL,
	"ini", 		0x4008,  &u32_can, 0, 		0, NULL,
	"inv", 		0x400a,  &u32_can, 0, 		0, NULL,
	"inw", 		0x400e,  &u32_can, 0, 		0, NULL,
	"vm3", 		0x400c,  &u32_can, 0, 		0, NULL,
	"vm4", 		0x401e,  &u32_can, 0, 		0, NULL,
};




af_sync_admin can1_admin;
af_sync_cfg can1_sync_cfgs[sizeof(can1_list) / sizeof(af_unit_body)];



void can1_error(af_error_type error)
{
	rt_kprintf("can out time\n");
}


void can1_sync_init(void)
{
	///初始化数据同步管理者
	af_sync_admin_init(&can1_admin, can1_list, sizeof(can1_list) / sizeof(af_unit_body), can1_tran_buffer, can1_error);
	///初始化重发机制
	af_sync_repeat_init(&can1_admin, can1_sync_cfgs, 600, 3);
}


void af_updata_task(void * p)
{
	SYSTEMDELAY(3000);
	while(1)
	{
		af_bodys_updata_handle(&can1_admin);
		SYSTEMDELAY(1);
	}
}


extern af_sync_admin dw_admin;



void af_logic_task(void * p)
{
	
	while(1)
	{
		Electrical ele;
		get_electrical(&ele);
		ele.outi = af_uint_name_get(&can1_admin, (afu8*)"outi");
		ele.outv = af_uint_name_get(&can1_admin, (afu8*)"outv");
		
		ele.ini = af_uint_name_get(&can1_admin, (afu8*)"ini");
		ele.inv = af_uint_name_get(&can1_admin, (afu8*)"inv");			   
		ele.vm3 = af_uint_name_get(&can1_admin, (afu8*)"vm3");
		ele.vm4  = af_uint_name_get(&can1_admin, (afu8*)"vm4");
		
		af_struct_name_sync(&can1_admin, &dw_admin, (afu8*)"ctr_cqm1");
		af_struct_name_sync(&can1_admin, &dw_admin, (afu8*)"ctr_cqm2");
		af_struct_name_sync(&can1_admin, &dw_admin, (afu8*)"cqm_en");
		af_struct_name_sync(&can1_admin, &dw_admin, (afu8*)"gnd_en");

		
		af_uint_name_set(&dw_admin, (afu8*)"m_outi", (int)(ele.outi));
		af_uint_name_set(&dw_admin, (afu8*)"m_outv",(int)(ele.outv));
		af_uint_name_set(&dw_admin, (afu8*)"m_outw", (int)(ele.outi/1000*ele.outv));
		af_struct_name_sync(&dw_admin, &can1_admin, (afu8*)"m_outr");
		af_struct_name_sync(&dw_admin, &can1_admin, (afu8*)"ad_cqm1");
		af_struct_name_sync(&dw_admin, &can1_admin, (afu8*)"ad_cqm2");
		
		SYSTEMDELAY(50);
	};
}


/**
  * @brief  封装32位变量数据
  * @param  变量地址
  * @param	变量值
  * @retval None
  */
void after_sync_rx(void  * p)
{
	uint16_t addr = 0;	//地址缓存
	uint32_t data = 0;	//数据缓存
	uint16_t CRC_U16=0;
	uint8_t R_Crc_h,R_Crc_l;
	
	uint8_t buffer[50];
	
	int len = 0;
	for(;;)
	{
		if(can1_receive(buffer, &len))
		{
			uint8_t cmd = buffer[0];
			uint8_t id = buffer[1];
			uint32_t addr = afu16_buffer_max((buffer+2));
			uint32_t data = afu32_buffer_max((buffer+4));
			
//			for(int i = 0; i < len; i++)
//			{
//				rt_kprintf("%02X ", buffer[i]);
//			};
//			rt_kprintf("\n");
			switch(cmd)
			{
				case AF_SYNC_WRITE_REQUST:
					//rt_kprintf("addr:%04X, data:%d\n", addr, data);
					af_sync_recv_handle(&can1_admin, AF_SYNC_WRITE_REQUST, addr, buffer+4, 4);
					break;
				case AF_SYNC_WRITE_REPORT:
					
					//rt_kprintf("AF_SYNC_WRITE_REPORT\n");
					af_sync_recv_handle(&can1_admin, AF_SYNC_WRITE_REPORT, addr,NULL, 0);
					break;
				case AF_SYNC_READ_REQUST:
					af_sync_recv_handle(&can1_admin, AF_SYNC_READ_REQUST, addr, NULL, 0);
					break;
				case AF_SYNC_READ_REPORT:
					af_sync_recv_handle(&can1_admin, AF_SYNC_READ_REPORT, addr, buffer+4, 4);
					break;
			}
		}
		else
		{
			//rt_kprintf("error\n");
		}
		SYSTEMDELAY(1);
	}
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值