⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hart_slave.c

📁 本人上载的几个.c文件为自己所写的代码,是关于自动化设备广泛使用的HART协议的主机与从机之间的通信过程(通过串口) hart_slave.c-----HART从机主程序(采用MSP430F149单
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 + -