📄 modbus.c
字号:
alert_value_mid=alert_value_mid<<1;
if(uart1_aa[148]==0x31) alert_value_mid=alert_value_mid+1;
alert_value_mid=alert_value_mid<<1;
if(uart1_aa[143]==0x31) alert_value_mid=alert_value_mid+1;
alert_value_mid=alert_value_mid<<1;
if(uart1_aa[138]==0x31) alert_value_mid=alert_value_mid+1;
alert_value_mid=alert_value_mid<<1;
if(uart1_aa[133]==0x31) alert_value_mid=alert_value_mid+1;
alert_value_mid=alert_value_mid<<1;
if(uart1_aa[128]==0x31) alert_value_mid=alert_value_mid+1;
alert_value_mid=alert_value_mid<<1;
if(uart1_aa[123]==0x31) alert_value_mid=alert_value_mid+1;
alert_value_mid=alert_value_mid<<1;
if(uart1_aa[118]==0x31) alert_value_mid=alert_value_mid+1;
alert_value_mid=alert_value_mid<<1;
}
//CRC校验子函数,入口:数据指针+数据段长度
unsigned short crc(unsigned char *puchMsg , unsigned short usDataLen)
{
unsigned char uchCRCHi = 0xFF ; /* 高CRC初始化*/
unsigned char uchCRCLo = 0xFF ; /* 低CRC初始化*/
unsigned uIndex ; /* 用来查表 */
while (usDataLen--) /* 整个数据缓冲区,不带数据的CRC两个字节 */
{
uIndex = uchCRCHi ^ *puchMsg++ ; /* calculate the CRC */
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];
uchCRCLo = auchCRCLo[uIndex] ;
}
return (uchCRCHi << 8 | uchCRCLo) ;
}
//RTU格式化输出
//入口:本地址缓冲区+原来数据地址缓冲区+数据段长度
void construct_rtu_frm ( unsigned char *dst_buf,unsigned char *src_buf,unsigned char lenth)
{
unsigned short crc_tmp;
crc_tmp = crc(src_buf, lenth); //原地址加数据段做CRC计算
*(src_buf+lenth) = crc_tmp >> 8 ; //把CRC高位防置在随后的地址
*(src_buf+lenth+1) = crc_tmp & 0xff; //放CRC低位
lenth++; //把数据指针指向最后
lenth++;
while ( lenth--) //搬动整个缓冲区到发送缓冲区
{
*dst_buf = *src_buf;
dst_buf++;
src_buf++;
}
}
//读继电器状态响应
//读的格式为:板本机地址 读功能码 读的高位地址 读的低位地址 字节长度高 字节长度低 CRC校验,共8个字节
//响应格式为:本机地址 功能码 有效数据长度 开关位8位数据 CRC校验码
int rtu_read_coil_status ( unsigned char board_adr,int start_address,int lenth)
{
unsigned char tmp[100], tmp_lenth;
unsigned int temp_start;
unsigned char temp1,temp2;
tmp_lenth = lenth;
temp_start = start_address;
if(tmp_lenth<=8)
{
tmp[2]=1;
}
else
{
tmp[2]=2;
}
alert_value_mid=alert_value_mid>>temp_start;
tmp[0] = board_adr;
tmp[1] = READ_COIL;
temp1= alert_value_mid/256;
temp2= alert_value_mid;
if(tmp[2]==1)
{
tmp[3] = temp2; //给出实际的数据1个字节,可代表8个继电器
tmp_lenth = 4;
}
else
{
tmp[3] = temp1; //给出实际的数据1个字节,可代表8个继电器
tmp[4] = temp2;
tmp_lenth = 5;
}
construct_rtu_frm (com_out_aa, tmp, tmp_lenth);
return (tmp_lenth+2);
}
//读取数据输入状态状态
int rtu_read_input_status ( unsigned char board_adr,int start_address,int lenth)
{
unsigned char tmp[100], tmp_lenth;
unsigned int temp_start;
unsigned char temp1,temp2;
tmp_lenth = lenth;
temp_start = start_address;
if(tmp_lenth<=8)
{
tmp[2]=1;
}
else
{
tmp[2]=2;
}
alert_value_mid=alert_value_mid>>temp_start;
tmp[0] = board_adr;
tmp[1] = READ_COIL;
temp1= alert_value_mid/256;
temp2= alert_value_mid;
if(tmp[2]==1)
{
tmp[3] = temp2; //给出实际的数据1个字节,可代表8个继电器
tmp_lenth = 4;
}
else
{
tmp[3] = temp1; //给出实际的数据1个字节,可代表8个继电器
tmp[4] = temp2;
tmp_lenth = 5;
}
construct_rtu_frm (com_out_aa, tmp, tmp_lenth);
return (tmp_lenth+2);
}
//读取采样保持器
//读格式:本机地址+功能码+读高位地址+读地位地址+数据段长度高位+数据段长度低位+CRC校验码
//返回格式:本机地址+功能码+有效数据长度 +数据1+数据2+++++++
int rtu_read_hldreg ( unsigned char board_adr,int start_address,int lenth)
{
unsigned char tmp[100], tmp_lenth;
unsigned char i,j,k;
unsigned int temp;
tmp_lenth=lenth;
tmp[0] = board_adr;
tmp[1] = READ_HLD_REG;
tmp[2] = tmp_lenth;
j=start_address;
k=2;
for(i=j;i<tmp_lenth;i++)
{
temp=uart1_value[i];
k++;
tmp[k] = temp >> 8 ;
k++;
tmp[k] = uart1_value[i];
}
tmp_lenth = k+1;
construct_rtu_frm (com_out_aa, tmp, tmp_lenth);
return (tmp_lenth+2);
}
//读取采样保持器
//读格式:本机地址+功能码+读高位地址+读地位地址+数据段长度高位+数据段长度低位+CRC校验码
//返回格式:本机地址+功能码++有效数据长度+数据1+数据2+++++++
int rtu_read_anloginput( unsigned char board_adr,int start_address,int lenth)
{
unsigned char tmp[100], tmp_lenth;
unsigned char i,j,k;
unsigned int temp;
tmp_lenth=lenth;
tmp[0] = board_adr;
tmp[1] = READ_HLD_REG;
tmp[2] = tmp_lenth;
j=start_address;
k=2;
for(i=j;i<tmp_lenth;i++)
{
temp=uart1_value[i];
k++;
tmp[k] = temp >> 8 ;
k++;
tmp[k] = uart1_value[i];
}
tmp_lenth = k+1;
construct_rtu_frm (com_out_aa, tmp, tmp_lenth);
return (tmp_lenth+2);
}
//RTU数据分析
//入口,接收缓冲区的大小,长度
int rtu_data_anlys(unsigned char fr_lenth)
{
unsigned short crc_result, crc_tmp;
unsigned char tmp1;
unsigned int tmp2,tmp3,tmp4;
unsigned char *source_p;
unsigned char temp;
source_p = uart0_bb;
temp = *source_p;
if(board_address!=temp) return;
crc_tmp = *(source_p + rtu_number_long-2); // 由接收缓冲区计算出 crc 第一字节
crc_tmp = crc_tmp * 256 + *( source_p+rtu_number_long-1); // 得到实际 CRC 值
crc_result = crc(source_p, fr_lenth-2); // 计算 CRC 值
if ( crc_tmp != crc_result ) // 对比 CRC 校验正确
{
return -1;
}
source_p=uart1_aa;
tmp1=*source_p;
tmp3=(*(source_p+2)*256)+*(source_p+3);
tmp4=(*(source_p+4)*256)+*(source_p+5);
switch ( *(source_p+1) ) // 功能码
{
case READ_COIL: /*读取继电器状态 */
tmp2=rtu_read_coil_status (tmp1,tmp3,tmp4);
rtu_out_active(tmp2);
break;
case READ_DI: /*读取开关量输入*/
tmp2=rtu_read_input_status(tmp1,tmp3,tmp4);
rtu_out_active(tmp2);
break;
case READ_HLD_REG: /*读取保持寄存器*/
tmp2=rtu_read_hldreg(tmp1,tmp3,tmp4);
rtu_out_active(tmp2);
break ;
case READ_AI: /*读取模拟量输入*/
tmp2=rtu_read_anloginput (tmp1,tmp3,tmp4);
rtu_out_active(tmp2);
break;
case PROTOCOL_EXCEPTION:
return -1*PROTOCOL_ERR;
default:
return -1*PROTOCOL_ERR;
}
return 0;
}
void rtu_out_active(unsigned char number)
{
unsigned char i;
P1OUT = 0; // P1.0 与自身异或
for(i=0;i<number;i++)
{
TXBUF0 = com_out_aa[i];
while((UTCTL0&0x01)==0);
}
P1OUT = 0xff; // P1.0 与自身异或
}
void timer_Init(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
BCSCTL1 |= BIT6; //XTS=1 高速模式
TACTL = TASSEL0 + TACLR; // SMCLK, clear TAR
CCTL0 = CCIE; // CCR0 interrupt enabled
CCR0 = modbus_delay;
P1DIR |= 0xff; // P1.0 output
TACTL |= MC0; // Start Timer_A in continuous mode
_EINT(); // Enable interrupts
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -