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

📄 485.c

📁 单片机的485串口通讯程序
💻 C
字号:
#include<reg51.h>
#include"string.h"
/*4种帧的宏定义*/
#define  ACTIVE    0x11
#define  GETDATA   0x22
#define  READY     0x33
#define  SENDDATA  0x44
//数据帧的数据字节最多为10,帧起始字节、地址、类型、数据长度、校验和
//帧结束字节共6个字节,最短帧长为6个字节的指令帧
#define RECFRMMAXLEN  16   //接收帧的最大长度,超过此值 认为帧超长错误
#define STATUSMAXLEN  10   //设备状态信息最大长度
unsigned DevNo;            //设备号
xdata unsigned StatusBuf[STATUSMAXLEN];  //设备状态信息缓冲区
sbit DE=P1^6;
/*初始化*/
void init(void)
{
 P1=0xff;
 DevNo=(P1&0x00111111);  //读取本机设备号
 TMOD=0x20;
 SCON=0x50;
 TH1=0xfd;
 TL1=0xfd;
 TR1=1;
 PCON=0x00;
 EA=0;
}
/*接收数据帧函数,实际上接收的是主机的指令*/
bit Recv_Data(unsigned char *type)
{
  unsigned char tmp,rCount,i;
  unsigned char r_buf[RECFRMMAXLEN];  //保存接收到的帧
  unsigned char Flag_RecvOver;  //一帧接受结束标志
  unsigned char Flag_StartRec;  //一帧接开始接收标志
  unsigned char CheckSum;       //校验和
  unsigned char DataLen;        //数据字节长度变量
  DE=0;  //禁止发送,允许接收
  rCount=0;
  Flag_StartRec=0;
  Flag_RecvOver=0;
  while(!Flag_RecvOver)
  {
    RI=0;
    while(!RI);
    tmp=SBUF;
    RI=0;
    /*判断是否收到字符"$",其数值为0x24*/
    if((!Flag_StartRec)&&(tmp==0x24))
    {
      Flag_StartRec=1;
    }
    if(Flag_StartRec)
    {
      r_buf[rCount]=tmp;
      rCount++;
      if(tmp==0x2A)
        Flag_RecvOver=1;
    }
    if(rCount==RECFRMMAXLEN)  //帧超长错误,返回0
      return 0;
  }
  /*计算校验和字节*/
  CheckSum=0;
  DataLen=r_buf[3];
  for(i=0;i++;i<3+DataLen)
    {
      CheckSum=CheckSum+r_buf[i+1];
    }
  /*判断帧是否错误*/
  if(rCount<6)   //帧过短错误,返回0,最短的指令帧为6个字节
      return 0;
  if(r_buf[1]!=DevNo)  //地址不符合,错误,返回0
      return 0;
  if(r_buf[rCount-2]!=CheckSum)  //校验错误,返回0
      return 0;
  *type=r_buf[2];    //获取指令类型
      return 1;      //成功,返回1                
}
/*发送单字节数据函数*/
void Send(unsigned m)
{
  TI=0;
  SBUF=m;
  while(!TI);
  TI=0;
}
/*发送数据函数,包括发送指令和发送设备状态信息*/
void Send_Data(unsigned type,unsigned len,unsigned *buf)
{
  unsigned i,tmp;
  unsigned CheckSum=0;
  DE=1;
  /*发送帧起始字节*/
  tmp=0x24;
  Send(tmp);
  Send(DevNo);
  CheckSum=CheckSum+DevNo;
  Send(type);
  CheckSum=CheckSum+type;
  Send(len);
  CheckSum=CheckSum+len;
  /*发送数据*/
  for(i=0;i<len;i++)
  {
    Send(*buf);
    CheckSum=CheckSum+*buf;
    buf++;
  }
  Send(CheckSum);
  tmp=0x2A;
  Send(tmp);
}
/* 清除设备状态信息缓冲区函数*/
void Clr_StatusBuf(void)
{
 unsigned char i;
 for (i=0;i<STATUSMAXLEN;i++)
  StatusBuf[i] = 0; 
}

/*主程序*/
void main()
{
  unsigned char type;  //数据帧类型字节的变量定义
  init();
  while(1)
  {
   if(Recv_Data(&type)==0)  //接收帧错误或者地址不符合,丢弃
      continue;
   switch(type)
   {
     case ACTIVE:  //主机询问从机是否在位
       Send_Data(READY,0,StatusBuf);  //发送READY指令
       break;
     case GETDATA: //主机读设备请求
       Clr_StatusBuf();      //设备状态信息缓冲区初始化
       //Get_Stat();  //数据采集函数 
       Send_Data(SENDDATA,strlen(StatusBuf),StatusBuf);
       break;
     default:
       break;  //指令类型错误,丢弃当前帧  
   }   
  }
}

⌨️ 快捷键说明

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