当前位置:文档之家› 51单片机实现的485通讯程序

51单片机实现的485通讯程序

51单片机实现的485通讯程序#ifndef __485_C__#define __485_C__#include <reg51.h>#include <string.h>#define unsigned char uchar#define unsigned int uint/* 通信命令*/#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使用工作方式2TH1 = 250; // 设置初值TL1 = 250;TR1 = 1; // 开始计时PCON = 0x80; // SMOD = 1SCON = 0x50; // 工作方式1,波特率9600bps,允许接收ES = 0; // 关闭串口中断IT0 = 0; // 外部中断0使用电平触发模式EX0 = 1; // 开启外部中断0EA = 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时表示设备状态发生改变,该函数使用寄存器组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 {switch(tmp){case 0xdd:data_buf[i] = 0xdb; // 0xdbdd表示0xdb ecc = ecc^0xdb;db = 0;break;case 0xdcdata_buf[i] = 0xc0; // 0xdbdc表示0xc0ecc = ecc^0xc0;db = 0;break;defaultreturn 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;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;}}#endifRS-232接口实现计算机和单片机通信程序作者:佚名来源:本站原创点击数:…更新时间:2008年07月10日【字体:大中小】//此程序通过RS-232接口来完成计算机和单片机通信(程序已用p1 8f458试验板上调试通过)//程序的调试可以用"串口调试助手V2.1"辅助完成,此程序可在htt p:// 下载//此程序首先发送测试数据55H,再通过中断实现数据的接收和发送#include "p18f458.h"void InterruptHandlerHigh(void);//初始化程序void initial(){SPBRG=0X19; //选择传输波特率为9600bpsTXSTA=0X04; //选择异步高速方式传输8位数据RCSTA=0X80; //允许同步串行口工作TRISC=0X80; //将RC7,RC6设置为输入,断绝与外接电路的连接 TXSTAbits.TXEN=1; //发送允许RCSTAbits.CREN=1; //接受数据允许PIE1bits.RCIE=1; //接收中断使能INTCON=0XC0; //总中断和外围中断允许}//高优先级中断向量#pragma code InterruptVectorHigh=0x08void InterruptVectorHigh (void){_asmgoto InterruptHandlerHigh //跳到中断程_endasm}//高优先级中断服务程序#pragma code#pragma interrupt InterruptHandlerHighvoid InterruptHandlerHigh (){while(PIR1bits.RCIF==1) //若接收中断标志不为1,则为误操作,返回{TXREG=RCREG; //将接收到的数据放入发送寄存器,并启动发送 }}//主程序main(){initial(); //系统初始化TXREG=0X55; //发送数据55H进行测试for(;;);}------------------------------------------汇编语言版本的RS-232接口实现计算机和单片机通信程序------------;此程序通过RS-232接口来完成计算机和单片机通讯(程序以在p18 f458试验板上调通);本单片机程序由提供;此程序首先发送测试数据55H,再通过中断实现数据的接收和发送;程序的调试可以用"串口调试助手V2.1"辅助完成LIST P=18f458INCLUDE "P18f458.INC"ORG 0x00GOTO MAINORG 0x08GOTO INTSERVEORG 0X30;**************中断服务子程序***************INTSERVEBTFSS PIR1,RCIF ;接收中断标志为1?GOTO ERR_RE ;误操作,返回MOVF RCREG,0 ;否则,将接收到的数据通过W寄存器MOVWF TXREG ;放入发送寄存器,并启动发送ERR_RE NOPRETFIE;****************初始化程序***************INITIAL NOPMOVLW 0X19 ;选择传输波特率为9600bpsMOVWF SPBRGMOVLW 0X04 ;选择异步高速方式传输8位数据MOVWF TXSTAMOVLW 0X80 ;允许同步串行口工作MOVWF RCSTAMOVLW 0X80 ;将RC7,RC6设置为输入,断绝与外接电路的连接MOVWF TRISCBSF TXSTA,TXEN ;发送允许BSF RCSTA,CREN ;接受数据允许BSF PIE1,RCIE ;接收中断使能MOVLW 0XC0 ;总中断和外围中断允许MOVWF INTCONRETURN;**********************主程序********************* MAIN NOPCLRWDTCALL INITIALMOVLW 0X55 ;发送数据55H进行测试MOVWF TXREGLOOPGOTO LOOPEND两片51单片机互相通信的串行通信程序(一个发送程序,一个接收程序)2007-05-27 08:27;系统晶振是 11.0592 MHz;51单片机发送单片机程序;此程序用Proteus仿真通过;此程序在硬件上测试通过;2007-05-27;附有简化电路图;为了使初学者能看懂,程序与图尽可能的简单扼要;实验现象为,发送端的P1口的哪个键被接下,接收端的哪个灯对应着亮;如果把两个单片机的T和R通过无线模块(如基于MCP2120芯片的模块)来扩充,便可做成无线通信ORG 0000HAJMP STARTORG 0040HSTART:MOV SP,#60HMOV SCON,#50H ;串口方式 1MOV TMOD,#20H ;T1 方式2MOV TL1,#0FDH ;波特率 9600 的常数MOV TH1,#0FDHSETB TR1mov r5,#00hWAIT:mov p1,#0ffhmov a ,p1mov r5,alcall delay ;读键盘,这里去抖动,还要加几句话mov a ,p1nopCJNE A,5,WAIT ;是否有键输入MOV SBUF,a ;串口输出键盘输入的值NOPSS: JBC TI,WAIT ;是否发送完毕SJMP SSDELAY: ;延时子程序PUSH 0 ;保存现场PUSH 1MOV 0,#06HDELAY1: MOV 1,#0HDJNZ 1,$DJNZ 0,DELAY1POP 1 ;恢复现场POP 0RETEND;系统晶振是 11.0592 MHz;51单片机接收单片机程序;此程序用Proteus仿真通过;此程序在硬件上测试通过;2007-05-27;附有简化电路图;为了使初学者能看懂,程序与图尽可能的简单扼要;实验现象为,发送端的P1口的哪个键被接下,接收端的哪个灯对应着亮;如果把两个单片机的T和R通过无线模块(如基于MCP2120芯片的模块)来扩充,便可做成无线通信ORG 0000HAJMP STARTORG 0040HSTART:MOV SCON,#50H ;串口方式 1MOV TMOD,#20H ;T1 方式 2MOV TL1,#0FDH ;波特率 9600 的常数MOV TH1,#0FDHSETB TR1WAIT:JBC RI,DIS_REC ;是否接收到数据sjmp waitDIS_REC:MOV A,SBUF ;读串口接收到的数据mov p1,aSJMP waitend51单片机串行口通信程序设计例子时间:2009-03-06 17:13来源:未知作者:牛牛点击: 768次串行口方式0应用编程 8051单片机串行口方式0为移位寄存器方式,外接一个串入并出的移位寄存器,就能扩展一个并行口。

相关主题