线圈代表位操作(bit),表示一个布尔变量,寄存器代表字操作(word),表示一个整型变量或其他复合数据结构。
1.通信协议,写单个线圈(05)
从机地址 | 功能码 | 线圈地址高字节 | 线圈地址低字节 | 写入bit值高字节,线圈电平高低 | 写入bit值低字节,还未知 | CRC校验高字节 | CRC校验低字节 |
01 | 05 | 00 | 00 | 00/FF | 00 | CRC | CRC |
00是广播 | 写单个线圈 | 0xFF00-0xFFFF | 0x00-0xFF | 对应线圈低/高 | 有的是低字节在前 | 高字节在后 |
例:01 05 00 01 ff 00 dd fA
2.通信协议,写多个线圈(0F)
从机地址 | 功能码 | 线圈起始地址高字节 | 线圈起始地址低字节 | 写的线圈的个数,高字节 | 写的线圈的个数,低字节 | 写的线圈占的总字节数 | 字节1 | 字节2 | …… | CRC校验低字节 | CRC校验高字节 |
01 | 0F | 00 | 00 | 00 | 00 | 00 | 00 | 00 | …… | CRC | CRC |
建一个数组array,
array[] = { 01 , 0F , 00,00 , 00,00 , 00 , 00 , 00 , …… , CRC,CRC }
00,00 从机的存储线圈的空间,从地址0x0000开始算起;
00,00 从机的存储线圈的空间,从地址0x0000开始算起,写了0x0000个线圈;
00 0x0000 除以8 ,有余数就再加1 ,就是0x00;
字节1,字节2,……,每8个线圈对应一个字节,不足的按一个字节算;
比如,从地址0开始,写8个线圈,线圈的电平是0,0,1,0,0,0,0,0,对应字节1的值是4;
字节1:4 | |||||||
0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
线圈0 | 线圈1 | 线圈2 | 线圈3 | 线圈4 | 线圈5 | 线圈6 | 线圈7 |
数组就是 01 0F 00 00 00 08 01 04 FF 56
计算的校验值是0x56FF,但要低字节在前,高字节在后。
3.CRC的计算
uint16_t CRC_16( uint8_t *Array , uint8_t ArrayLength )
{
uint16_t CRC_16 = 0xffff ;
uint8_t TEMP;
while( ArrayLength-- )
{
CRC_16 = CRC_16 ^ (*Array);
for(int x=0;x<8;x++)
{
TEMP = CRC_16 & 0x0001;
CRC_16 = CRC_16 >> 1;
if( TEMP==1 )
{
CRC_16 = CRC_16^0xA001;
}
}
Array++;
}
return CRC_16;
}
.