| 大纲
内存操作函数介绍:
1.memcpy (memory copy)
2.memcmp(memory compare)
3.memset(memory set)
4.malloc(memory allocation)
1.memcpy
void* memcpy(void* destiny,void*source,unsigned length);
\brief:拷贝source中前 length的字节到destiny中。
\para:destiny:复制的对象。
source:被复制的对象。
length:字节的长度
\retval: 返回 destiny 的地址
应用:常常用于通讯中数据的收发,如在CAN总线中收发报文,接收和发送都使用同一个数组
把数据拷贝到相应的变量中实现内存块的复制,为什么要复制,因为接受到消息接受的是一个局
部变量,我们想要实现收发,就要把变量发到公共的全局变量之中。
2.memset
extern void *memset(void *buffer, int c, int count);
常常用于结构体或数组的初始化,如在嵌入式行业中,对GPIO等外设参数进行初始化操作
fg1:
struct vary
{
uint8_t a;
uint16_t b;
uint32_t c;
}vary1;
memset(&vary1 , 0l, sizeof(vary1)); // 表示对结构体vary1的所有内存块进行清零操作。
3.memcmp
int memcmp (void* desiny , void*source, unsigned char length);
\brief:比较数据是否相同
\para:destiny 和source 都是比较对象, length表示比较的字节的长度
\retval: 相同返回0,destiny>source ,不同:大于0的数; destiny<source 小于0的数
实际应用:在进行CAN总线通讯时候,CANopen协议层角度,当然节点工作在工作模式heartbeat.buf[0]=0x05,
从机PDO工作在事件触发模式下(event trigger),配合禁止时间(inhibit time),如果数据发生变化就会发送
TPDO报文到上位机,从机如何知道自己数据变化,就是比较原先的数据和现在的数据是否变化。
首先上机节点工作在工作模式(0x05),对TPDO进行初始化拷贝赋值,这个时候记录时间和事件的时间戳。
直接判断时间模式中时间是否到,和事件模式中时间有没有到。一个轮回后,第二次进行模式时候首先判断
数据是否产生变化,然后再判断时间有没有变化。以及考虑时间模式触发下后,需要将所有模式的时间戳重新
更新,并将事件模式的禁止时间重新更新。
以上谈到多变量问题,这个在设计TPDO结构体的时候就需要考虑到。
4.malloc
void* malloc(size_t size);
\brief:为指定变量分配内存空间,并返回一个指向它的指针。
\para:size是内存块大小,以字节为单位。
\retval: 返回一个指针,指向已经分配大小的内存。如果请求失败,则返回NULL.
fg1:
int *a = malloc(10); //指针指向一个内存为10个字节的地址。
应用: CANopen协议栈的建立
//伪代码
CANOPEN_processstack
{
if(启动标志)
{
if(心跳节点.buff[0]==0x00)
{
//1.记录心跳时间戳=心跳时间+设备地址偏移+系统滴答;
//2.发送心跳包
成功继续
不成功return 1;
}
3、选择启动模式
3.1启动
心跳节点.buff[0]=0x05;
TPDO初始化,配置相应的时间戳,状态标志位,以及要发送的信息到buf中
3.2预先启动
心跳节点.buff[0]=0x7f;
}
//TPDO有两种工作模式
//1.inhibit mode 事件触发方式,数据发生变化,并且发送的时间间隔有限制
//2.event time 时间触发,时间到就发送消息
//1.event time mode
1.判断时间到没到
2.到了就发送消息,并且将所有模式的时间置位,并设置标志位,防止禁止时间限制
//2.inhibit time mode
1.第一次的时候判断时间到没到,到了就发送(第一次数据是新的)
2.以后每次都判断数据是否变化,
//这里用到memcmp进行数据块的比较
3.如果发生变化,就拷贝数据给TPDO.buf中,然后发送报文
//心跳模式
1.判断心跳是否工作在0x05状态
2.判断心跳时间是否超出
3.发送报文
4.更新心跳报文的时间戳
return 1;
}
}
}
时间:2021-11-05 20:55:56