微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 怎样改下面的程序使52单片机通过485发送一组自己设置的数据

怎样改下面的程序使52单片机通过485发送一组自己设置的数据

时间:10-02 整理:3721RD 点击:
#ifndef __485_C__
#define __485_C__
#include <reg51.h>
#include <string.h>
#define uchar unsigned char
#define uint unsigned int
/* 通信命令 */
#define __ACTIVE_ 0x01 // 主机询问从机是否存在
#define __GETDATA_ 0x02 // 主机发送读设备请求
#define __OK_ 0x03 // 从机应答
#define __STATUS_ 0x04 // 从机发送设备状态信息
#define __MAXSIZE 0x08 // 缓冲区长度
#define __ERRLEN 12 // 任何通信帧长度超过12则表示出错
uchar dbuf[55]; // 该缓冲区用于保存设备状态信息
uchar dev; // 该字节用于保存本机设备号
//sbit M_DE = P1^0; // 驱动器使能,1有效
//sbit M_RE = P1^1; // 接收器使能,0有效
  sbit re=P3^5;
void get_status(); // 调用该函数获得设备状态信息,函数代码未给出
void send_data(uchar type, uchar len, uchar *buf); // 发送数据帧
bit recv_cmd(uchar *type); // 接收主机命令,主机请求仅包含命令信息
void send_byte(uchar da); // 该函数发送一帧数据中的一个字节,由send_data()函数调用
void main()
{uchar type;
uchar len;/* 系统初始化 */
P3 = 0xff; // 读取本机设备号
dev = (P3>>2);
TMOD = 0x20; // 定时器T1使用工作方式2
TH1 = 244; // 设置初值 X=256-f*(SMOD+1)/(384*波特率)
TL1 = 244;
TR1 = 1; // 开始计时
PCON = 0x00; // SMOD = 0
SCON = 0x50; // 工作方式1,波特率2400bps,允许接收
ES = 0; // 关闭串口中断
IT0 = 0; // 外部中断0使用电平触发模式
EX0 = 1; // 开启外部中断0
EA = 1; // 开启中断
/* 主程序流程 */
while(1) // 主循环
{ if(recv_cmd(&type) == 0) // 发生帧错误或帧地址与本机地址不符,丢弃当前帧后返回
continue;
switch(type)
{ case __ACTIVE_: // 主机询问从机是否存在
  send_data(__OK_, 0, dbuf); // 发送应答信息,这里buf的内容并未用到
  break;
  case __GETDATA_:
  len = strlen(dbuf);
   send_data(__STATUS_, len, dbuf); // 发送设备状态信息
    break;
        default:
         break; // 命令类型错误,丢弃当前帧后返回
         }}}
void READSTATUS() interrupt 0 using 1 // 产生外部中断0时表示设备状态发生改变,
{
get_status(); // 获得设备状态信息,并将其存入dbuf指向的存储区,数据最后一字节置0表示数据结束
}
/* 该函数接收一帧数据并进行检测,无论该帧是否错误,函数均会返回* 函数参数type保存接收到的命令字* 当接收到数据帧错误或其地址位不为0时(非主机发送帧),函数返回0,反之返回1*/
bit recv_cmd(uchar *type)
{bit db = 0; // 当接收到的上一个字节为0xdb时,该位置位
bit c0 = 0; // 当接收到的上一个字节为0xc0时,该位置位
uchar data_buf[__ERRLEN]; // 保存接收到的帧
uchar tmp;
uchar ecc = 0;
uchar i;
//M_DE = 0; // 置发送禁止,接收允许
//M_RE = 0;/* 接收一帧数据 */
re=0;
i = 0;
while(!c0) // 循环直至帧接收完毕
{ RI = 0;
while(!RI);
tmp = SBUF;
  RI = 0;
  if(db == 1) // 接收到的上一个字节为0xdb
  { switch(tmp)
  { case 0xdd:
  data_buf[i] = 0xdb; // 0xdbdd表示0xdb
   ecc = ecc^0xdb;
    db = 0;
        break;
        case 0xdc:
        data_buf[i] = 0xc0; // 0xdbdc表示0xc0
        ecc = ecc^0xc0;
        db = 0;
        break;
        default:
        return 0; // 帧错误,返回
         }
         i++;
    }
           switch(tmp) // 正常情况
            { case 0xc0: // 帧结束
                 c0 = 1;
                  break;
                  case 0xdb: // 检测到转义字符
                   db = 1;
                   break;
                    default: // 普通数据
                         data_buf[i] = tmp; // 保存数据
                          ecc = ecc^tmp; // 计算校验字节
                           i++; }
                           if(i == __ERRLEN) // 帧超长,错误,返回
                           return 0;
                           }/* 判断帧是否错误 */
                           if(i<4) // 帧过短,错误,返回
                           return 0;
                           if(ecc != 0) // 校验错误,返
                           return 0;
                           if(data_buf[0] != dev) // 非访问本机命令,错误,返回
                            return 0;
                                *type = data_buf[1]; // 获得命令字
                                return 1; // 函数成功返回
                                }
/* 该函数发送一帧数据帧,参数type为命令字、len为数据长度、buf为要发送的数据内容 */
void send_data(uchar type, uchar len, uchar *buf)
{uchar i;
uchar ecc = 0; // 该字节用于保存校验字节
//M_DE = 1; // 置发送允许,接收禁止
//M_RE = 1;
re=1;
send_byte(dev); // 发送本机地址
ecc = dev;
send_byte(type); // 发送命令字
ecc = ecc^type;
send_byte(len); // 发送长度
ecc = ecc^len;
for(i=0; i<len; i++) // 发送数据
{ send_byte(*buf);
ecc = ecc^(*buf);
buf++;
}
send_byte(ecc); // 发送校验字节
TI = 0; // 发送帧结束标志
SBUF = 0xc0;
while(!TI);
TI = 0;
}
/* 该函数发送一个数据字节,若该字节为0xdb,则发送0xdbdd,若该字节为0xc0则,发送0xdbdc */
void send_byte(uchar da)
{switch(da)
{ case 0xdb: // 字节为0xdb,发送0xdbdd
TI = 0;
SBUF = 0xdb;
while(!TI);
TI = 0;
SBUF = 0xdd;
while(!TI)
TI = 0;
  break;
  case 0xc0: // 字节为0xc0,发送0xdbdc
  TI = 0;
  SBUF = 0xdb;
  while(!TI);
   TI = 0;
   SBUF = 0xdc;
   while(!TI)
   TI = 0;
   break;
   default: // 普通数据则直接发送
    TI = 0;
        SBUF = da;
        while(!TI);
        TI = 0;
        }}
#endif

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top