下面我的心得,有不对的地方,还请纠正,谢谢:
----
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;继电器将吸合。
下面来封装函数,面向对象。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
//////////////////////////////////////////////////////////////////////////////////////////
//----port.h----//
sbit JDQ00=P1^0;
sbit JDQ01=P1^1;
sbit JDQ02=P1^2;
sbit JDQ03=P1^3;
typedef void (*jdq_fun)(uint8);
//ModbusRTU格式开关量结构体
typedef struct _strModbusRtuDio
{
uint8 num; //隐性地址(0,1,2,3,4,5)
uint16 addr; //显性地址(0-99或0-999)
uint16 status;//各位的状态或数据
void (*jdq_fun)(uint8); //操作函数
}strModbusRtuDio,*pstrModbusRtuDio;
//ModbusRTU格式开关量联合体
typedef union _unModbusRtuDio
{
strModbusRtuDio smrd;
uint8 buff[6]; //buff[0]=smrd.num;
//buff[1]=smrd.addr_h;
//buff[2]=smrd.addr_l;
//buff[3]=smrd.status_h;
//buff[4]=smrd.status_l;
//buff[5]=smrd.control_fun(uint8);
//8位CPU时1个指针1字节,16位CPU时1个指针2字节,32位CPU时1个指针4字节
//8位CPU时寄存器是8位,因此指针的参数只能是uint8的
}unModbusRtuDio,*punModbusRtuDio;
//////////////////////////////////////////////////////////////////////////////////////////
//----port.c----//
void jdq00_fun(uint8 sta)
{
if(0==sta){JDQ00=0;}
else{JDQ00=1;}
}
void jdq01_fun(uint8 sta)
{
if(0==sta){JDQ01=0;}
else{JDQ01=1;}
}
void jdq02_fun(uint8 sta)
{
if(0==sta){JDQ02=0;}
else{JDQ02=1;}
}
void jdq03_fun(uint8 sta)
{
if(0==sta){JDQ03=0;}
else{JDQ03=1;}
}
//////////////////////////////////////////////////////////////////////////////////////////
//----bsp.c----//
void strModbusRtuDio_set(strModbusRtuDio* pdio,uint8 num,uint16 addr,uint16 status,jdq_fun fun)
{
pdio->num=num;
pdio->addr=addr;
pdio->status=status;
pdio->jdq_fun=fun;
}
void jdq_init(void)
{
strModbusRtuDio_set(&m_jdq[0],0,0x0000,0x0000,jdq00_fun);
strModbusRtuDio_set(&m_jdq[1],0,0x0001,0x0000,jdq01_fun);
strModbusRtuDio_set(&m_jdq[2],0,0x0002,0x0000,jdq02_fun);
strModbusRtuDio_set(&m_jdq[3],0,0x0003,0x0000,jdq03_fun);
}
//////////////////////////////////////////////////////////////////////////////////////////
//----app.c----//
strModbusRtuDio m_jdq[4];
void test(void)
{
uint8 recv_buff[8]={0x35,0x05,0x00,0x02,0xFF,0x00,0x29,0x8E};
unModbusRtuDio un1;
uint8 i;
jdq_init();
for(i=1;i<5;i++)
{
un1.buff[i]=recv_buff[i+1];
}
for(i=0;i<4;i++)
{
if(m_jdq[i].addr==un1.smrd.addr)
{
m_jdq[i].status=un1.smrd.status;
if(0xFF00==m_jdq[i].status){m_jdq[i].jdq_fun(1);}
else{m_jdq[i].jdq_fun(0);}
}
}
}
执行结果:跳转到jdq02_fun函数里,执行了JDQ02=1;
一周热门 更多>