下面我的心得,有不对的地方,还请纠正,谢谢:
----
30岁之前,一直闷头写单片机程序,对高级语言的设计模式(经典的23种),数据结构等等都缺乏学习。现在我决心补上这一课。
使用8位单片机时没想过用封装,从面向过程转向面向对象,而在32位机时,考虑到容量大了,速度快了,利用结构体、联合体、函数指针(乃至以后再链表插入删除),将一些事务封装起来,从而达到更方便的调用。
下面是接收到消息并执行:
主机单独写35H设备的地址0002H(DO2)这个继电器为闭合ON。 串口数据为0x35,0x05,0x00,0x02,0xFF,0x00,0x29,0x8E(其中CRC16=0x8E29)
(1)测试一,不带函数指针的操作 在头文件里简单的封装 typedef struct _strModbusRtuAio { uint8 num; //隐性地址(0,1,2,3,4,5) uint16 addr; //显性地址(0-99或0-999) uint16 value;//数据 }strModbusRtuAio,*pstrModbusRtuAio; //ModbusRTU格式寄存器联合体 typedef union _unModbusRtuAio { strModbusRtuAio smra; uint8 buff[5]; //buff[0]=smra.num; //buff[1]=smra.addr_h; //buff[2]=smra.addr_l; //buff[3]=smra.value_h; //buff[4]=smra.value_l; }unModbusRtuAio,*punModbusRtuAio;
然后在源文件里做了如下处理:
strModbusRtuDio m_jdq[4];
void strModbusRtuDio_set(strModbusRtuDio* pdio,uint8 num,uint16 addr,uint16 status)
{
pdio->num=num;
pdio->addr=addr;
pdio->status=status;
}
void jdq_init(void)
{
//初始化里假设继电器jdq02的显性地址0x0002,初始化状态为关0x0000
strModbusRtuDio_set(&m_jdq[0],0,0x0000,0x0000);
strModbusRtuDio_set(&m_jdq[1],0,0x0001,0x0000);
strModbusRtuDio_set(&m_jdq[2],0,0x0002,0x0000);
strModbusRtuDio_set(&m_jdq[3],0,0x0003,0x0000);
}
void test(void)
{
//假设下面这个数据包符合本规约,其中[2]-[5]是要解析的数据
uint8 recv_buff[8]={0x35,0x05,0x00,0x02,0xFF,0x00,0x29,0x8E};
//假设一个联合体,用于变量间数据类型转换
unModbusRtuDio un1;
uint8 i;
jdq_init();
//将收到的串口数据recv_buff传递到联合体中
//recv_buff[2,3,4,5]---->un1.buuf[1,2,3,4],同时也就传给了un1.smrd.addr,un1.smrd.status.
for(i=1;i<5;i++)
{
un1.buff=recv_buff[i+1];
}
//判断联合体中的地址是否与jdq02地址相同
//相同则将状态FF00(吸合)赋给jdq02
for(i=0;i<4;i++)
{
if(m_jdq.addr==un1.smrd.addr)
{
m_jdq.status=un1.smrd.status;
}
}
}
执行结果:m_jdq[2].status=0xFF00;继电器将吸合。
下面来封装函数,面向对象。
|