Chinaunix首页 | 论坛 | 博客
  • 博客访问: 7681428
  • 博文数量: 961
  • 博客积分: 15795
  • 博客等级: 上将
  • 技术积分: 16612
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-07 14:23
文章分类

全部博文(961)

文章存档

2016年(1)

2015年(61)

2014年(41)

2013年(51)

2012年(235)

2011年(391)

2010年(181)

分类: 嵌入式

2012-01-13 09:33:49

#include

#include

#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[MAXSIZE] ; //该缓冲区用于保存设备状态信息

uchar dev;               //该字节用于保存本机设备号

sbit M_DE = P1^0;        //驱动器使能,1有效

sbit M_RE = P1^1;        //接收器使能,0 有效

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;

   /*系统初始化*/

   P1 = 0xff ;   //读取本机设备号

   dev = (P1>>2);  

   TMOD = 0x20;  //定时器T1使用方式2

   TH1 = 250;

   TL1 = 250; 

   TR1 = 1;  //开始计时

   PCON = 0x80;   //SMOD = 1;

   SCON = 0x50;   //工作方式1,波特优选法9600bps,允许接收

   ES = 0;    // 关闭串品中断

   IT0 = 0;       //外部中断0使有电平触发模式

   EX0 = 1;       // 开启外部中断0

   EA = 0;        //开启总中断

   /*主程序流程*/

   while(1)       

    {

      if(recv_cmd(&type) ==0)    //发送帧错误或帧地址与本机地址不符,丢弃当前帧后返回

   continue;

 switch(type)

  {

    case _ACTIVE_:    //主机询问从机是否存在

      send_data(_OK_,0,dbuf);   // 发送应答信息,这里的buf 的内容并未用到

 break;

    case _GETDATA_:     //主机发送读设备请求

      len = strlen(dbuf);

 snd_data(_STATUS_,len,dbuf) ;   // 发送设备信息

 break;

    default:

      break; //命令类型错误,丢弃当前帧返回

    }

  

    } 

      }

}

void READSTATUS() interrput 0 using 1    //产生外部中断0时表示设备状态发生改变,该函数使用寄存器组1

{

   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;

  /*接收一帧数据*/

  i =0;

  while(!c0)  //循环直至帧接收完毕

  {

    RI = 0;

    while(RI);

    tmp = SBUF;

    RI = 0;

    if(db ==1)  //接收到的上一个字节为0xdb

     {

  swithc(tmp)

 {

   case 0xdd: 

     data_buf[i] = 0xdb; //0xdbdd 表示0xdb

     ecc = ecc^0xdb;

     db = 0;

     break;

   case 0xdc:

     data_buf[i] = 0xc0;  //0xdbdc 表示0xc0

     ecc = 0;

     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(==_ERRLEN)  //帧超长,错误,返回

      return 0;

   }

   /*判断帧是否错误*/

 if(i<4)   //帧过短,错误,返回

  return 0;

 if(ecc!=0)   //校验错误,返回

  return 0;

 if(data_buf[i!= 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;

  send_byte(dev);  //发送本机地址

  ecc = dev; 

  send_byte(type);  //发送命令字

  ecc = ecc^type;

  send_byte(len);   // 发送长度

  ecc = ecc^len;

  for(=0;i<len;i++)

  { 

    send_byte(*buf);

    ecc = ecc^(*buf);

    buff++;

   }

   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;

    }

 

 }


源码: 485通信程序(51单片机).rar   

阅读(3175) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~