485通信程序(51单片机)

发布者:太和清音最新更新时间:2016-07-30 来源: eefocus关键字:485通信程序  51单片机 手机看文章 扫描二维码
随时随地手机看文章
#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(i ==_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(i =0;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单片机 引用地址:485通信程序(51单片机)

上一篇:STC-ISP下载过程
下一篇:C51算术运算符练习

推荐阅读最新更新时间:2024-03-16 15:02

nRF24L01+51单片机无线语音点滴报警系统
使用的51单片机作为主控芯片,两个51单片机通过24L01通信,一个检测吊瓶滴液的速度,如果太快太慢或者不滴液都会报警,并发送到主机,输液者也可以主动通过按键呼叫主机,丛机用1602显示,主机用12864显示。 Altium Designer画的原理图和PCB图如下: 单片机源程序如下: #include reg52.h #include intrins.h #include keys.h #include 24L01.h #include LCD1602.h #define uint unsigned int #define uchar unsigned char sbit YeDi=P2^0;//红外信号
[单片机]
nRF24L01+<font color='red'>51单片机</font>无线语音点滴报警系统
51单片机数据传送指令列表
操作码 目标操作数 可选择的源操作数 说 明 MOV A Rn direct @Ri DPTR Rn;direct;@Ri;# data A;direct;# data A;Rn;direct;@Ri;# data A;direct;# data # data16 内部传送 内部传送 内部传送 内部传送 数据指针赋值 PUSH POP 隐含(SP) direct direct 隐含(SP) 压栈,只能用直接寻址 退栈,只能用直接寻址 XCH A Rn; direct; @Ri 内部交换 XCHD
[单片机]
89c51单片机最小系统,89c51最小系统原理图的功能详解
  单片机的最小系统是由组成单片机系统必需的一些元件构成的,除了单片机之外,还需要包括电源供电电路、时钟电路、复位电路。单片机最小系统电路原理图。    89c51最小系统原理图的功能详解   1:电源电路   电源电路就是单片机的供电电路,一般是3.3V或者5V,具体多少要参考各种型号的单片机的工作电压,通常情况下是5V,这里是指通常情况下。   2:时钟电路   时钟电路就是晶振电路,一般选择12Mhz的晶振,方便使用定时器、计数器的功能。AT 89C51中有高增益的反相放大器,它是是构成内部振荡器的主要单元,XTAL2和引脚XTAL1分别是该放大器的输出端和输入端。   片外石英晶体或陶瓷谐振器和放大器共同构成
[单片机]
89c<font color='red'>51单片机</font>最小系统,89c51最小系统原理图的功能详解
51单片机:定时器与中断系统的运用
#include regx52.h void Delay(int time) { while(time--) //while循环一次需要10us { } } void Timer0Init(void) //1毫秒@11.0592MHz { TMOD &= 0xF0; //设置定时器模式 TMOD |= 0x01; //设置定时器模式 TL0 = 0x66; //设置定时初值 TH0 = 0xFC; //设置定时初值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 ET0 = 1; EA = 1;
[单片机]
<font color='red'>51单片机</font>:定时器与中断系统的运用
基于AT89C2051单片机制作的厨房定时器
该制作以5分钟为一个计时单位,最多计时1小时,3V电池做电源,有蜂鸣器报警,工作时功耗为6mA左右(使用AT89C2051),可以使用3V钮扣电池,具有自动关机功能,不运行时耗电量可以忽略不计,单键操作,简单方便。   电路图   VT1为PNP的9012,当电路不工作时VT1的B极由R4得到高电平,VT1截止,AT89C2051无法从VT1的E极得到电源。当SW1按下时,VT1的B极通过VD2和SB1接地,由高电平转为低电平,VT1导通。此时AT89C2051得电,同时通过C1,R4复位。复位成功后P3.7升为高电平,使得VT2导通,从而使VT1的B极保持低电平状态,这时就算松开SB1,VT1也不会截止而导致MCU失
[工业控制]
基于AT89C20<font color='red'>51单片机</font>制作的厨房定时器
80C51单片机定时计数器的功能详解
单片机结构是什么样的,由什么模块组成 单片机(Micro Control Unit)全称微型控制单元,简称单片机(MCU),从字面意思可以了解到它其实就是一个微型的计算机系统,51单片机包含CPU(8051内核),SRAM(内存)惨不忍睹的1K,闪存(硬盘)也只有可怜的几十K,然后外围的模块基本就是下载代码用的ISP,中断模块,基本输入输出I/O模块,复位模块,串口模块,EEPROM,看门狗。单片机种类比较多,51是我们常用的单片机型号,主要应用的场合有数码家电(洗衣机,电饭锅,电磁炉,微波炉),工业现场数据采集与传输等。 80C51定时计数器有两个功能,定时功能和计数功能,定时计数器实质是一个加一计数器,无论做定时还是做
[单片机]
80C<font color='red'>51单片机</font>定时计数器的功能详解
51单片机洗衣机控制板及C语言程序
51单片机洗衣机控制板及C语言程序,该控制板单片机采用AT89C51单片机,所设计全自动洗衣机功能有:标准洗衣、经济洗衣、单独洗衣以及排水四种洗衣等四种方式,有强洗、弱洗及运行/暂停、显示及报警功能,程序利用利用Protues仿真软件观察洗衣机的运行状态和过程。整个设计能达到预想的设计效果。 #include 'reg51.h' #define uchar unsigned char #define uint unsigned int #define Enable(); EA=1; #define Disable(); EA=0
[单片机]
<font color='red'>51单片机</font>洗衣机控制板及C语言<font color='red'>程序</font>
【自学51单片机】12 --- 1602液晶初步认识
1、1602液晶硬件接口介绍 1602液晶技术参数 说明:(1) 工作电流:在5v工作电压下液晶的工作电流为2mA,仅仅指液晶,不包括背光。 1602液晶接口原理图及引脚功能 说明:(1) 引脚3:液晶显示偏压信号。用来调整显示黑点与不显示黑点的对比度。(2) 4引脚:数据命令选择引脚。置高电平1,为读写数据,置低电平0,为读写命令。(3) 5引脚:读写选择引脚。置高电平1,为读数据或命令,置低电平0,为写数据或命令。(4) 6引脚:使能信号引脚。高电平有效,低电平无效。(5) 7~14引脚:8个数据引脚。因为总电流不大,直接接到PO口上,不用通过74HC245。 2、1602的读写时序介绍 液晶内部自带80
[单片机]
【自学<font color='red'>51单片机</font>】12 --- 1602液晶初步认识
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved