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

📄 rs485.lst

📁 RS485通信源代码
💻 LST
字号:
C51 COMPILER V6.23a  RS485                                                                 12/22/2005 21:56:39 PAGE 1   


C51 COMPILER V6.23a, COMPILATION OF MODULE RS485
OBJECT MODULE PLACED IN RS485.OBJ
COMPILER INVOKED BY: C:\Keil\C51\BIN\C51.EXE RS485.c BROWSE DEBUG OBJECTEXTEND

stmt level    source

   1          #ifndef __485_C__
   2          #define __485_C__
   3          
   4          #include <AT89X51.H>
   5          #include <string.h>
   6           
   7          #define uchar unsigned char
   8          #define uint unsigned int
   9          /* 通信命令 */
  10          #define __ACTIVE_ 0x01    // 主机询问从机是否存在
  11          #define __GETDATA_ 0x02    // 主机发送读设备请求
  12          #define __OK_ 0x03    // 从机应答
  13          #define __STATUS_ 0x04    // 从机发送设备状态信息
  14          
  15          #define __MAXSIZE 0x08    // 缓冲区长度
  16          #define __ERRLEN 12    // 任何通信帧长度超过12则表示出错
  17          uchar dbuf[__MAXSIZE];    // 该缓冲区用于保存设备状态信息
  18          uchar dev;    // 该字节用于保存本机设备号
  19          
  20          sbit M_DE = P1^0;    // 驱动器使能,1有效
  21          sbit M_RE = P1^1;    // 接收器使能,0有效
  22          
  23          void get_status();    // 调用该函数获得设备状态信息,函数代码未给出
  24          void send_data(uchar type, uchar len, uchar *buf);    // 发送数据帧
  25          bit recv_cmd(uchar *type);    // 接收主机命令,主机请求仅包含命令信息
  26          void send_byte(uchar da);    // 该函数发送一帧数据中的一个字节,由send_data()函数调用
  27          
  28          void main()
  29          {
  30   1              uchar type;
  31   1              uchar len;
  32   1              
  33   1              /* 系统初始化 */
  34   1              P1 = 0xff;    // 读取本机设备号
  35   1              dev = (P1>>2);
  36   1              TMOD = 0x20;    // 定时器T1使用工作方式2
  37   1              TH1 = 250;    // 设置初值
  38   1              TL1 = 250;
  39   1              TR1 = 1;    // 开始计时
  40   1              PCON = 0x80;    // SMOD = 1
  41   1              SCON = 0x50;    // 工作方式1,波特率9600bps,允许接收
  42   1              ES = 0;    // 关闭串口中断
  43   1              IT0 = 0;    // 外部中断0使用电平触发模式
  44   1              EX0 = 1;    // 开启外部中断0
  45   1              EA = 1;    // 开启中断
  46   1      
  47   1              /* 主程序流程 */
  48   1              while(1)    // 主循环
  49   1              {
  50   2                      if(recv_cmd(&type) == 0)    // 发生帧错误或帧地址与本机地址不符,丢弃当前帧后返回
  51   2                              continue;
  52   2                      switch(type)
  53   2                      {
  54   3                              case __ACTIVE_:    // 主机询问从机是否存在
  55   3                                      send_data(__OK_, 0, dbuf);    // 发送应答信息,这里buf的内容并未用到
C51 COMPILER V6.23a  RS485                                                                 12/22/2005 21:56:39 PAGE 2   

  56   3                                      break;
  57   3                              case __GETDATA_:
  58   3                                      len = strlen(dbuf);
  59   3                                      send_data(__STATUS_, len, dbuf);    // 发送设备状态信息
  60   3                                      break;
  61   3                              default:
  62   3                                      break;    // 命令类型错误,丢弃当前帧后返回
  63   3                      }
  64   2              }
  65   1      }
  66          
  67          void READSTATUS() interrupt 0 using 1    // 产生外部中断0时表示设备状态发生改变,该函数使用寄存器组1
  68          {
  69   1              get_status();    // 获得设备状态信息,并将其存入dbuf指向的存储区,数据最后一字节置0表示数据结束
  70   1      }
  71          
  72          /* 该函数接收一帧数据并进行检测,无论该帧是否错误,函数均会返回
  73           * 函数参数type保存接收到的命令字
  74           * 当接收到数据帧错误或其地址位不为0时(非主机发送帧),函数返回0,反之返回1
  75           */
  76          bit recv_cmd(uchar *type)
  77          {
  78   1              bit db = 0;    // 当接收到的上一个字节为0xdb时,该位置位
  79   1              bit c0 = 0;    // 当接收到的上一个字节为0xc0时,该位置位
  80   1              uchar data_buf[__ERRLEN];    // 保存接收到的帧
  81   1              uchar tmp;
  82   1              uchar ecc = 0;
  83   1              uchar i;
  84   1              
  85   1              M_DE = 0;    // 置发送禁止,接收允许
  86   1              M_RE = 0;
  87   1              
  88   1              /* 接收一帧数据 */
  89   1              i = 0;
  90   1              while(!c0)    // 循环直至帧接收完毕
  91   1              {
  92   2                      RI = 0;
  93   2                      while(!RI);
  94   2                      tmp = SBUF;
  95   2                      RI = 0;
  96   2                      if(db == 1)    // 接收到的上一个字节为0xdb
  97   2                      {
  98   3                              switch(tmp)
  99   3                              {
 100   4                                      case 0xdd:
 101   4                                              data_buf[i] = 0xdb;    // 0xdbdd表示0xdb
 102   4                                              ecc = ecc^0xdb;
 103   4                                              db = 0;
 104   4                                              break;
 105   4                                      case 0xdc:
 106   4                                              data_buf[i] = 0xc0;    // 0xdbdc表示0xc0
 107   4                                              ecc = ecc^0xc0;
 108   4                                              db = 0;
 109   4                                              break;
 110   4                                      default:
 111   4                                              return 0;    // 帧错误,返回
 112   4                              }
 113   3                              i++;
 114   3                      }
 115   2                      switch(tmp)    // 正常情况
 116   2                      {
 117   3                              case 0xc0:    // 帧结束
C51 COMPILER V6.23a  RS485                                                                 12/22/2005 21:56:39 PAGE 3   

 118   3                                      c0 = 1;
 119   3                                      break;
 120   3                              case 0xdb:    // 检测到转义字符
 121   3                                      db = 1;
 122   3                                      break;
 123   3                              default:    // 普通数据
 124   3                                      data_buf[i] = tmp;    // 保存数据
 125   3                                      ecc = ecc^tmp;    // 计算校验字节
 126   3                                      i++;
 127   3                      }
 128   2                      if(i == __ERRLEN)    // 帧超长,错误,返回
 129   2                              return 0;
 130   2              }
 131   1              /* 判断帧是否错误 */
 132   1              if(i<4)    // 帧过短,错误,返回
 133   1                      return 0;
 134   1              if(ecc != 0)    // 校验错误,返回
 135   1                      return 0;
 136   1              if(data_buf[0] != dev)    // 非访问本机命令,错误,返回
 137   1                      return 0;
 138   1              *type = data_buf[1];    // 获得命令字
 139   1              return 1;    // 函数成功返回
 140   1      }
 141          
 142          /* 该函数发送一帧数据帧,参数type为命令字、len为数据长度、buf为要发送的数据内容 */
 143          void send_data(uchar type, uchar len, uchar *buf)
 144          {
 145   1              uchar i;
 146   1              uchar ecc = 0;    // 该字节用于保存校验字节
 147   1      
 148   1              M_DE = 1;    // 置发送允许,接收禁止
 149   1              M_RE = 1;
 150   1              
 151   1              send_byte(dev);    // 发送本机地址
 152   1              ecc = dev;
 153   1              send_byte(type);    // 发送命令字
 154   1              ecc = ecc^type;
 155   1              send_byte(len);    // 发送长度
 156   1              ecc = ecc^len;
 157   1              for(i=0; i<len; i++)    // 发送数据
 158   1              {
 159   2                      send_byte(*buf);
 160   2                      ecc = ecc^(*buf);
 161   2                      buf++;
 162   2              }
 163   1              send_byte(ecc);    // 发送校验字节
 164   1              
 165   1              TI = 0;    // 发送帧结束标志
 166   1              SBUF = 0xc0;
 167   1              while(!TI);
 168   1              TI = 0;
 169   1      }
 170          
 171          /* 该函数发送一个数据字节,若该字节为0xdb,则发送0xdbdd,若该字节为0xc0则,发送0xdbdc */
 172          void send_byte(uchar da)
 173          {
 174   1              switch(da)
 175   1              {
 176   2                      case 0xdb:    // 字节为0xdb,发送0xdbdd
 177   2                              TI = 0;
 178   2                              SBUF = 0xdb;
 179   2                              while(!TI);
C51 COMPILER V6.23a  RS485                                                                 12/22/2005 21:56:39 PAGE 4   

 180   2                              TI = 0;
 181   2                              SBUF = 0xdd;
 182   2                              while(!TI)
 183   2                              TI = 0;
 184   2                              break;
 185   2                      case 0xc0:    // 字节为0xc0,发送0xdbdc
 186   2                              TI = 0;
 187   2                              SBUF = 0xdb;
 188   2                              while(!TI);
 189   2                              TI = 0;
 190   2                              SBUF = 0xdc;
 191   2                              while(!TI)
 192   2                              TI = 0;
 193   2                              break;
 194   2                      default:    // 普通数据则直接发送
 195   2                              TI = 0;
 196   2                              SBUF = da;
 197   2                              while(!TI);
 198   2                              TI = 0;
 199   2              }
 200   1      }
 201          
 202          #endif


MODULE INFORMATION:   STATIC OVERLAYABLE
   CODE SIZE        =    428    ----
   CONSTANT SIZE    =   ----    ----
   XDATA SIZE       =   ----    ----
   PDATA SIZE       =   ----    ----
   DATA SIZE        =      9      25
   IDATA SIZE       =   ----    ----
   BIT SIZE         =   ----       2
END OF MODULE INFORMATION.


C51 COMPILATION COMPLETE.  0 WARNING(S),  0 ERROR(S)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -