📄 hart_slave.c
字号:
#include <msp430x16x.h>
#include <string.h>
#include "resp_data.h"
#define byte unsigned char
extern void uart0_init(); //串口初始化 波特率9600
extern void clock_init(); //时钟初始化
extern void timer_A_init(); //定时器A初始化 增模式 定时时间30ms
extern byte Checksum(byte *s , byte nbytes);//计算校验和
extern void com_send(byte *send,byte send_bytes);//通过串口发送数据
extern void hart_resp( byte *resp_data, byte resp_num, byte *addr ,byte cmd_num);//按HART协议的格式生成待发送的数据帧send[]
byte x1; //用于区别长结构和短结构的变量,x1=1 短,x1=2时长
byte receive[100]; //用于存放接收的数据
byte send[100]; //用于存放发送的数据
byte cmd_data[25]; //命令数据区
byte byte_count; //数据长度
byte start_short[3]={0xFF,0xFF,0x02}; //用于寻找短结构起始字节
byte start_long[3]={0xFF,0xFF,0x82}; //用于寻找长结构起始字节
byte rec_ptr; //用于给接收到的数据编号
byte received; //recived=1时表示已接收到一帧数据,对数据帧解析完recived被置为0
byte rec_bytes; //接收的字节数
byte error,comm_error,command_error,old_device,needs_burn;
byte polling_addr; //轮询地址,初始值为0
byte *p_polling_addr=&polling_addr;//指向轮询地址的指针
byte short_addr = 0x80 ; //本机短结构地址,初始值为0x80
byte long_addr[5]={0x81,0x02,0x08,0x09,0x10}; //本机长结构地址
byte cmd_num; //命令号
byte pre_num; //前导符的个数
byte status1,status2; //状态位
byte send_bytes; //发送数据的字节数
byte not_resp; //表示从机不需要响应的标志,该变量为1时表示不响应
/*主程序运行后,程序一直在等待.当串口接收到一个完整的数据帧之后,received置1,主程序对接收到
的数据帧进行解析,若解析正确,则根据数据帧中的命令号执行相应的操作.*/
void main(void)
{
byte i,j,t;
byte cs_start;
byte *r,*p;
float pv_range_span,f1; //主变量量程跨度
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
uart0_init();
clock_init();
timer_A_init();
_EINT(); // Enable interrupts
received = 0;
error = 0;
status1 = 0;
status2 = 0;
for (;;)
{
while(received==1) //当接收到数据时进行以下的处理,否则一直在这里等待
{
not_resp=0;
r=receive;
for(j=1;j<=rec_bytes;++j)
{
if (strncmp((const char*)r,(const char*)start_short,3)==0)
{
x1=1; break;
}
if (strncmp((const char*)r,(const char*)start_long,3)==0)
{
x1=2; break;
}
r++;
}
if(j>rec_bytes) //当程序未找到0x02或0x82时
{
++error; break;
}
pre_num = j+1;
j +=2 ; r +=2; //此时j,r 都指向起始字节
cs_start = j;
++j; ++r; //指向地址首字节
if(rec_bytes-j<2) //当剩余数据数少于3时
{
++error; break;
}
if (x1==1) //地址为短结构
{
if(*r != short_addr) //短结构地址与本从机短地址不同时
{
++error; break;
}
else
{
++j; ++r; //指向命令号
}
}
if(x1==2) //地址为长结构
{
if(strncmp((const char*)r,(const char*)long_addr,5)!=0) //短结构地址与本从机短地址不同时
{
++error; break;
}
else
{
j += 5; r +=5; //指向命令号
}
}
cmd_num = *r;
j++; r++; //指向数据长度字节
byte_count = *r;
if (byte_count==0)
{
j++; r++; //指向校验位
}
else
{
r++; //指向命令数据的第一个字节
j += byte_count + 1;
for(int i=0;i<byte_count;i++)
cmd_data[i]=*r++;
}
r = &receive[cs_start-1];
if ((Checksum(r, j-cs_start+1)) != 0) ++error;
if (error==0)
{
p_pv_value = (unsigned char *)&pv_value;
p_pv_current = (unsigned char *)&pv_current;
p_pv_upper = (unsigned char *)&pv_upper_value;
p_pv_lower = (unsigned char *)&pv_lower_value;
p_v2_value = (unsigned char *)&v2_value;
p_v3_value = (unsigned char *)&v3_value;
p_v4_value = (unsigned char *)&v4_value;
p_pv_sensor_upper = (unsigned char *)&pv_sensor_upper;
p_pv_sensor_lower = (unsigned char *)&pv_sensor_lower;
p_pv_min_span = (unsigned char *)&pv_min_span;
p_pv_damping = (unsigned char *)&pv_damping_value; //将指针和对应的数据值一一对应
switch(cmd_num)
{
case 0: hart_resp(resp_data_0, resp_num_0,long_addr,cmd_num); //生成待发送的数据帧send[]
break;
case 1: /*将主变量单位代码和主变量值IEEE754形式填充到1号命令响应数据中中*/
resp_data_1[0] = pv_unit_code;
for(i=0;i<4;i++)
resp_data_1[i+1] = pv_754[i] = *p_pv_value++;
hart_resp(resp_data_1, resp_num_1,long_addr,cmd_num);
break;
case 2: hart_resp(resp_data_2, resp_num_2,long_addr,cmd_num);
break;
case 3: /*按命令3响应数据的格式填充相关数据*/
for(i=0;i<4;i++)
{
resp_data_3[i] = pv_current_754[i] = *p_pv_current++;
resp_data_3[i+5] = pv_754[i] = *p_pv_value++;
resp_data_3[i+10] = v2_754[i] = *p_v2_value++;
resp_data_3[i+15] = v3_754[i] = *p_v3_value++;
resp_data_3[i+20] = v4_754[i] = *p_v4_value++;
}
resp_data_3[4] = pv_unit_code;
resp_data_3[9] = v2_unit_code;
resp_data_3[14] = v3_unit_code;
resp_data_3[19] = v4_unit_code;
hart_resp(resp_data_3, resp_num_3,long_addr,cmd_num);
break;
case 6: polling_addr = cmd_data[0];
short_addr = (0x80|polling_addr);
hart_resp(p_polling_addr, 1,long_addr,cmd_num);
break;
case 11: if(strncmp((const char*)cmd_data,(const char*)tag,6)==0)//当主机发来的设备标签和设备本身标签相同时
hart_resp(resp_data_0, resp_num_0,long_addr,cmd_num);
else
not_resp=1; //当主机发来的设备标签和设备本身标签不相同时,不响应主机的命令
break;
case 12: hart_resp(message, 24,long_addr,cmd_num);
break;
case 13: /*将标签,描述符和日期填充到13号命令响应数据中中*/
for(i=0;i<6;i++)
resp_data_13[i]=tag[i];
for(i=6;i<18;i++)
resp_data_13[i]=descriptor[i-6];
for(i=18;i<21;i++)
resp_data_13[i]=date[i-18];
hart_resp(resp_data_13,resp_num_13,long_addr,cmd_num);
break;
/*将传感器序列号等内容填充到14号命令响应数据数组中*/
case 14: for(i=0;i<3;i++)
resp_data_14[i] = pv_sensor_sn[i]; //填充主变量传感器序列号
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -