C51单片机双机通信程序
51单片机实现双机通信
左侧 1 号机,右侧 2 号机,,功能实现1号机程序#include<reg51.h>#define uint unsigned int#define uchar unsigned charsbit p10=P1^0;uchar a,b,kk;//uchar code d_c[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; void delay_ms(uchar y){uchar i;while(y--)for(i=0;i<120;i++);}void put(uchar x) // 发送函数{SBUF=x;//SBUF:串行口数据缓冲器while(TI==0);// 等候发送结束TI=0;}void main(){uchar j;SCON=0x40;// 串行口工作方式1,8位通用异步发送器TMOD=0x20;// 准时器 1 工作方式2 PCON=0x00;// 波特率不倍增TH1=0xf4;TL1=0xf4; TR1=1;// 波特率 2400// 准时器 1 开始计时P2=0xc0;while(1){if(p10==0&&j==0){delay_ms(15);while(p10==0);kk=1;P2=0xf9;j=1;}if(p10==0&&j==1){delay_ms(15);while(p10==0);kk=2;P2=0xa4;j=2;}if(p10==0&&j==2){delay_ms(15);while(p10==0);kk=3;P2=0xb0;j=0;}if(kk==1)put('A');if(kk==2)put('B');if(kk==3)put('C');delay_ms(10);}}/*********************************************************************** if(p10==0&&j==0){delay_ms(15);while(p10==0);kk=0;P2=~0xf9;j=1;}if(p10==0&&j==1){delay_ms(15);while(p10==0);kk=1;P2=~0xa4;j=2;}if(p10==0&&j==2){delay_ms(15);while(p10==0);kk=2;P2=~0xc0;j=0;}if(kk==0)put('A');if(kk==1)put('B');if(kk==2)put('C');delay_ms(100);*********************************************************** if(p10==0){delay_ms(15);while(p10==0);number=(number+1)%4;}switch(oper){case 0:break;case 1:put('A');P2=~0xf9;break;case 2:put('B');P2=~0xa4;break;case 3:put('C');P2=~0xc0;break;}delay_ms(10);********************************************************************if(p10==0){delay_ms(15);while(p10==0);j=(j+1)%3;}switch(j){case 0:put('A');P2=~0xf9;break;case 1:put('B');P2=~0xa4;break;case 2:put('C');P2=~0xc0;break;}delay_ms(10);*/2号机程序。
C51单片机技术应用与实践课件3-4 设计单片机双机通信
串行通信的分类
1
理论认知
按照串行数据的时钟控制方式,串行通信可分为同步通信 和异步通信两类。
异步通信(Asynchronous Communication)
在异步通信中,接收端是依靠字符帧格式来判断发送端 是何时开始发送,何时结束发送的。字符帧格式是异步通 信的一个重要指标。
1
理论认知
异步通信的字符帧格式·
CRC2
同步通信的字符帧格式
1
理论认知
MCS-51串行口结构
MCS-51内部有两个独立的接收、发送缓冲器SBUF。 SBUF属于特殊功能寄存器。发送缓冲器只能写入不能读 出,接收缓冲器只能读出不能写入,二者共用一个字节 地址(99H)。
1
理论认知
串行口结构示意图
单片机与MAX232的接口原理图
1
同步通信(Synchronous Communication)
同步通信是一种连续串行传送数据的通信方式,一 次通信只传输一帧信息。
同步 数据 数据 数据 字符1 字符1 字符2 字符3
(a)
同步 同步 数据 数据 字符1 字符2 字符1 字符2
(b)
数据 字符n
CRC1
CRC2
数据 字符n
CRC1
任务实施
1.硬件设计 (1)单片机双机通件编程
(1) 端口分配 系统中有甲、乙两个单片机系统,在每个单片机的
P1.0和P1.1口均有两个按键,其中P1.0为增加控制键, P1.1为减少控制键,甲单片机的TXD引脚和乙单片机的 RXD相连同时乙单片机的TXD引脚和甲单片机的RXD相接。
2
实践训练
2
实践训练
任务分析:
甲乙两个单片机系统均具有接收和发送功能,可 通过查询的方式知道各自单片机系统的按钮按下的是 “计数增加”还是“计数减少”的按钮,用中断方式 接收对方单片机发过来的数据并显示。
51单片机双机串行通信设计
51单片机双机串行通信设计51单片机是一款广泛应用于嵌入式系统中的微控制器,具有高性能和低功耗的特点。
在一些场景中,需要使用51单片机之间进行双机串行通信,以实现数据传输和协同工作。
本文将介绍51单片机双机串行通信的设计,包括硬件连接和软件编程。
一、硬件连接1.串行通信口选择:51单片机具有多个串行通信口,如UART、SPI 和I2C等。
在双机串行通信中,可以选择其中一个串行通信口作为数据传输的接口。
一般来说,UART是最常用的串行通信口之一,因为它的硬件接口简单且易于使用。
2.引脚连接:选定UART口作为串行通信口后,需要将两个单片机之间的TX(发送)和RX(接收)引脚相连。
具体的引脚连接方式取决于所使用的单片机和外设,但一般原则上是将两个单片机的TX和RX引脚交叉连接。
二、软件编程1.串行通信初始化:首先需要通过软件编程来初始化串行通信口。
在51单片机中,可以通过设置相应的寄存器来配置波特率和其他参数。
具体的初始化代码可以使用C语言编写,并根据所使用的开发工具进行相应的配置。
2.发送数据:发送数据时,可以通过写入相应的寄存器来传输数据。
在51单片机中,通过将数据写入UART的发送寄存器,即可将数据发送出去。
发送数据的代码通常包括以下几个步骤:(1)设置发送寄存器;(2)等待数据发送完成;(3)清除数据发送完成标志位。
3.接收数据:接收数据时,需要通过读取相应的寄存器来获取接收到的数据。
在51单片机中,可以通过读取UART的接收寄存器,即可获取到接收到的数据。
接收数据的代码通常包括以下几个步骤:(1)等待数据接收完成;(2)读取接收寄存器中的数据;(3)清除数据接收完成标志位。
4.数据处理:接收到数据后,可以进行相应的数据处理。
根据具体的应用场景,可以对接收到的数据进行解析、计算或其他操作。
数据处理的代码可以根据具体的需求进行编写。
5.中断服务程序:在双机串行通信中,使用中断可以提高通信的效率。
单片机双机通信(C51程序)
单片机双机通信(C51程序)/*发送程序连线:两个单片机用3 根线连起来,要共地,rxd,txd 要交叉连接程序效果:通过主机发送,从机接收在主机中通过记下按键按下的次数,主机中显示最后按下的六个数值,并发送给从机,从机也显示这六个数值*/#includereg52.h //头文件#includeintrins.h //循环移位文件#define uchar unsigned char//宏定义#define uint unsigned intsbit key1=P3 ; //位声明uchar code table[] ={0X00,0x3f,0x06,0x5b,//数码管显示的数值0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; uchar table_tr[6];//暂存最后按下的六个数值uchar count,cnt;//延时子函数,用于数码管显示void delay(uchar i){ uchar x,y; for(x=i;x0;x--) for(y=110;y0;y--);}//初始化子函数void init(){ TMOD=0x20;//T1 工作在方式2 TH1=0XF4;//波特率为4.8kbit/s TL1=0XF4; TR1=1;//启动定时器1 SCON=0X50;//串口工作在方式1,允许接收}//显示子函数void display(){ uchar i,j;//定义局部变量j=0x7f; //赋初值for(i=0;i6;i++) { P2=j; //点亮最右边的数码管P0=table[table_tr[i]]; //显示该数值delay(10); //延时,便于眼睛看清j=_cror_(j,1);//循环右移一位}}//按键扫描子函数void key_scan(){ if(key1==0) //判断是否有按键按下{ while(!key1) //等待按键松手{ display();//防止掉显} cnt++; //加1,用于显示SBUF=cnt;//送给缓冲区,发送while(!TI); //等待发送完TI=0; //发送完了,标志位清零for(count=0;count5;count++) //用于保存最后按下的六个按键数值{ table_tr[count] =table_tr[count+1]; } table_tr[5]=cnt; //把最后按下的按键数值赋给table_tr【5】if(cnt==10) //按键按下的次数有没有等于10 cnt=0;//等于,则清零}}void main() { init(); //调用初始化子函数P0=0x00; while(1) { key_scan(); //调用键盘扫描子函数display();//调用显示子函数} }tips:感谢大家的阅读,本文由我司收集整编。
单片机双机通信实验程序
P0|=0xe0; if((P0&0xe0)!=0xe0)
{ P3|=0xc0; P3&=0x7f; switch(P0&0xe0) {
case 0xe0: break; case 0x60: k=6;break; case 0xa0: k=5;break; case 0xc0: k=4;break; }
}
void ser() interrupt 4
{ RI=0;
//软件清零
a=SBUF; a=a-0x30;
//ASCII 码值转换
//W1=0;
flag=1;
}
unsigned char key() { unsigned char k=0; P0|=0xe0; P3&=0x3f; if((P0&0xe0)!=0xe0) { DelayMS(100);
while(!TI);
TI=0;
//软件清零
ES=1;
}
void main()
{
a=0; init(); while(1) {
Display1(); kk=key(); switch(kk) {
case 1: sendchar('1'); break; case 2: sendchar('2'); break; case 3: sendchar('3'); break; case 4: sendchar('4'); break; case 5: sendchar('5'); break; case 6: sendchar('6'); break; default:Display1(); break; } }
MCS-51系列单片机双机串行通信
RS232是应用最早,最广泛的双机异步串行通信总线标准。是美国电 子工业协会的推荐标准 RS = recommended standard
标准规定了数据终端设备(DTE)和数据通信设备(DCE)间串行通信接 口的物理(电平)、信号和机械连接标准
RS232C
DTE
DCE
电话线
RS232C
DCE
DTE
计算机
8
5
CTS DCE 控制
9
22
RI DCE 控制
描述
载波信号检测 接收数据 发送数据 终端准备好 信号地
数据机准备好 请求发送
清除以便发送 振铃信号
计算机间RS232C通信的常用连接方法
TXD 计算机 RXD
GND
TxD RxD RTS CTS DTR DSR
CD RI GND
无握手 全握手
TXD RXD 计算机 GND
在方式 1 处于接收时,若 SM2=1,则只有收到有效的停止位后,RI =1。
在方式 0 中,SM2 应为 0。
REN: 允许接收。 REN=0 时,禁止接收。由软件置位或清零。 TB8: 发送数据的第 9 位。
在方式 2 和方式 3 中,由软件设置,可做奇偶校验位。 在多机通信中,可作为区别地址帧或数据帧的标识位。一般约定地址 帧时,TB8 为 1,数据帧时,TB8 为 0。 RB8: 接收数据的第 9 位。功能同 TB8。 TI: 发送中断标志位。发送完一帧数据的标志,由硬件置位, 软件清除, 可触发CPU中断。 RI: 接收中断标志位。接收完一帧数据的标志,由硬件置位, 软件清除, 可触发CPU中断。
6. 串行通讯及其接口
6-1 串行通讯的一般概念
6-1-1 并行通信和串行通信
基于51单片机的双机串行通信设计组单片机课程设计
基于51单片机的双机串行通信设计一、设计任务设计要求:两个AT89C51单片机使用串口进行通信。
1)1机发送,二机接收时。
使用1机发送一个数字0xAA给2机。
2)如果2机收到数据后要给1机回复,回复0xBB。
3)1机收到回复后要下发数据,下发的同时要将数据显示出来,下发的数据通过4*4的矩阵键盘产生,可以由用户进行控制。
4)2机收到后将这些数值显示出来,一次传输完毕要回复0x00。
可以使用点阵显示或者数码管显示或者 LCD显示。
二、硬件设计1、单片机串行通信功能AT89C51计算机与外界的信息交换称为通信,常用的通信方式有两种:并行通信和串行通信。
51单片机用4个接口与外界进行数据输入与数据输出就是并行通信,并行通信的特点是传输信号的速度快,但所用的信号线较多,成本高,传输的距离较近。
串行通信的特点是只用两条信号线(一条信号线,再加一条地线作为信号回路)即可完成通信,成本低,传输的距离较远。
51单片机的串行接口是一个全双工的接口,它可以作为UART(通用异步接受和发送器)用,也可以作为同步移位寄存器用。
51单片机串行接口的结构如下:(1)数据缓冲器(SBUF)接受或发送的数据都要先送到SBUF缓存。
有两个,一个缓存,另一个接受,用同一直接地址99H,发送时用指令将数据送到SBUF即可启动发送;接收时用指令将SBUF中接收到的数据取出。
(2)串行控制寄存器(PCON)SCON用于串行通信方式的选择,收发控制及状态指示,各位含义如下:SM0,SM1:串行接口工作方式选择位,这两位组合成00,01,10, 11对应于工作方式0、1、2、3。
串行接口工作方式特点见下表SM2:多机通信控制位。
REN:接收允许控制位。
软件置1允许接收;软件置0禁止接收。
TB8:方式2或3时,TB8为要发送的第9位数据,根据需要由软件置1或清0。
RB9:在方式2或3时,RB8位接收到的第9位数据,实际为主机发送的第9位数据TB8,使从机根据这一位来判断主机发送的时呼叫地址还是要传送的数据。
51单片机多机通信程序
51单片机多机通信程序(主机部分) /* multi_m.c *//* 多机通信的主机部分*/#ifndef __MULTI_M_C__#define __MULTI_M_C__#include <AT89X51.H>#include <STRING.H>#define __MAX_LEN_ 64 // 数据最大长度#define _MHZ_ 11 // 设置单片机使用的晶振频率(11.0592MHz) /* 以下为程序协议中使用的握手信号*/#define __SUCC_ 0x0f // 数据传送成功#define __ERR_ 0xf0 // 数据传送错误void init_serial(); // 串口初始化void send_data(unsigned char *buf); // 发送数据void delay10ms(unsigned int count); // 延时子程序(10ms) void main(){char buf[__MAX_LEN_];unsigned char i = 0;unsigned char tmp;unsigned char addr; // 该字节用于保存要通信的从机地址/* 为缓冲区赋初值*/P0 = 0xff;while(P1 != 0) // 每隔100ms从P0口读取,若读取到0则表明数据采集结束{*(buf+i) = P0;delay10ms(10); // 延时100msP0 = 0xff;i++;}*(buf+i) = 0; // 缓冲区最后一个字节为0表示数据结束/* 读要访问的分机地址*/P0 = 0xff;addr = P0;/* 串口初始化*/init_serial(); // 初始化串口EA = 0; // 关闭所有中断/* 发送地址帧并接收应答信息,如果接收的信号与发送的地址信息不同,则重新发送地址帧*/tmp = addr-1;while(tmp != addr){/* 发送从机地址*/TB8 = 1; // 发送地址帧SBUF = addr;while(!TI);TI = 0;/* 接收从机应答*/RI = 0;while(!RI);tmp = SBUF;RI = 0;}/* 发送数据并接收校验信息,如果接收的信号为0FH,表示从机接收成功,否则将重新发送该组数据*/tmp = __ERR_;while(tmp != __SUCC_){send_data(buf); // 发送数据RI = 0;while(!RI);tmp = SBUF;RI = 0;}while(1); // 程序结束,进入死循环}/* 初始化串口*/void init_serial(){TMOD = 0x20; //定时器T1使用工作方式2TH1 = 250; // 设置初值TL1 = 250;TR1 = 1; // 开始计时PCON = 0x80; // SMOD = 1SCON = 0xd0; //工作方式3,9位数据位,波特率9600bps,允许接收}/* 发送数据*/void send_data(unsigned char *buf){unsigned char len; // 保存数据长度unsigned char ecc; // 保存校验字节len = strlen(buf); // 计算要发送数据的长度ecc = len; // 开始进行校验字节计算/* 发送数据长度*/TB8 = 0; // 发送数据帧SBUF = len; // 发送长度while(!TI);TI = 0;/* 发送数据*/for(i=0; i<len; i++){ecc = ecc^(*buf); // 计算校验字节TB8 = 0; // 发送数据帧SBUF = *buf; // 发送数据buf++;while(!TI);TI = 0;}/* 发送校验字节*/TB8 = 0; // 发送数据帧SBUF = ecc; // 发送校验字节while(!TI);TI = 0;}/* 延时10ms,精度较低,参数count为延时时间*/ void delay10ms(unsigned int count){unsigned int i, k;unsigned char j;unsigned int tmp;tmp = (int)((100*_MHZ_)/12);for(i=0; i<count; i++)for(j=0; j<100; j++)for(k=0; k<tmp; k++);}#endif51单片机多机通信程序(从机部分)/* multi_s.c *//* 多机通信的从机部分*/#ifndef __MULTI_S_C__#define __MULTI_S_C__#include <AT89X51.H>#include <STRING.H>#define __MAX_LEN_ 64 // 数据最大长度#define _MHZ_ 11 // 设置单片机使用的晶振频率(11.0592MHz)/* 以下为程序协议中使用的握手信号*/#define __SUCC_ 0x0f // 数据传送成功#define __ERR_ 0xf0 // 数据传送错误void init_serial(); // 串口初始化unsigned char recv_data(unsigned char *buf); // 接收数据void Beep_ok(); // 蜂鸣表示数据接收ok,该函数代码未给出void main() {char buf[__MAX_LEN_];unsigned char i = 0;unsigned char tmp = 0xff;unsigned char addr; // 保存本机地址/* 从P1口读取本机地址*/P1 = 0xff;addr = P1;/* 串口初始化*/init_serial(); // 初始化串口EA = 0; // 关闭所有中断/* 进入设备应答阶段*/while(1){SM2 = 1; // 只接收地址帧/* 如果接收到的地址帧不是本机地址,则继续等待*/ tmp = addr-1;while(tmp != addr){RI = 0;while(!RI);tmp = SBUF;RI = 0;}/* 发送应答信号,并做好接收数据的准备*/TI = 0;TB8 = 0; // 主机不检测该位SBUF = addr;while(!TI);TI = 0;SM2 = 0; // 允许接收数据信息/* 数据接收*/tmp = 0xff;while(tmp == 0xff) // 如果数据校验失败则重新接收数据{tmp = recv_data(buf); // 校验失败返回0xff,检测到地址帧则返回0xfe,接收成功则返回0}if(tmp == 0xfe) // 在数据接收过程中,如果发现地址帧,则重新开始整个接收过程continue;Beep_ok(); // 蜂鸣表示数据接收成功}}/* 初始化串口*/void init_serial(){TMOD = 0x20; //定时器T1使用工作方式2TH1 = 250; // 设置初值TL1 = 250;TR1 = 1; // 开始计时PCON = 0x80; // SMOD = 1SCON = 0xd0; //工作方式3,9位数据位,波特率9600bps,允许接收}/* 接收数据,注意该函数使用buf指向的缓冲区保存数据,在数据末尾使用’\0’表示数据结束* 返回值为0,数据校验成功,返回值为0xfe,接受过程中接收到地址帧,返回值为0xff,数据校验失败*/unsigned char recv_data(unsigned char *buf){unsigned char len; // 该字节用于保存数据长度unsigned char ecc; // 该字节用于保存校验字节unsigned char i,tmp;/* 接收数据长度*/RI = 0;while(!RI);if(RB8 == 1) // 若当前接收为地址帧则返回0xfereturn 0xfe;len = SBUF;RI = 0;/* 使用len的值为校验字节ecc赋初值*/ecc = len;/* 接收数据*/for(i=0; i<len; i++){while(!RI);if(RB8 == 1) // 若当前接收为地址帧则返回0xfe return 0xfe; *buf = SBUF; // 接收数据ecc = ecc^(*buf); // 进行字节校验RI = 0;buf++;}*buf = 0; // 表示数据结束/* 接收校验字节*/while(!RI);if(RB8 == 1) // 若当前接收为地址帧则返回0xfe return 0xfe; tmp = SBUF;RI = 0;/* 进行数据校验*/ecc = tmp^ecc;if(ecc != 0) // 校验失败{*(buf-len) = 0; // 清空数据缓冲区TI = 0; // 发送校验失败信号TB8 = 0;SBUF = __ERR_;while(!TI);TI = 0;return 0xff; // 返回0xff表示校验错误} TI = 0; // 校验成功TB8 = 0;SBUF = __SUCC_;while(!TI);TI = 0;return 0; // 校验成功,返回0}#endif。
单片机双机通信(C51程序
单片机双机通信(C51程序)/*发送程序连线:两个单片机用3根线连起来,要共地,rxd,txd要交叉连接程序效果:通过主机发送,从机接收在主机中通过记下按键按下的次数,主机中显示最后按下的六个数值,并发送给从机,从机也显示这六个数值*/#include; //头文件#include; //循环移位文件#define uchar unsigned char//宏定义#define uint unsigned intsbit key1=P3^5;//位声明uchar code table[]={0X00,0x3f,0x06,0x5b,//数码管显示的数值0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};uchar table_tr[6];//暂存最后按下的六个数值uchar count,cnt;//延时子函数,用于数码管显示void delay(uchar i){uchar x,y;for(x=i;x>;0;x--)for(y=110;y>;0;y--);}//初始化子函数void init(){TMOD=0x20;//T1工作在方式2TH1=0XF4;//波特率为4.8kbit/s TL1=0XF4;TR1=1;//启动定时器1SCON=0X50;//串口工作在方式1,允许接收}//显示子函数void display(){uchar i,j;//定义局部变量j=0x7f; //赋初值for(i=0;i; //头文件#include; //循环文件#define uchar unsigned char//宏定义#define uint unsigned intuchar code table[]={0X00,0x3f,0x06,0x5b,//数码管显示的数值0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};uchar table_tr[6];//暂存最后按下的六个数值uchar count,cnt;//定义全局变量//延时子函数,用于数码管显示void delay(uchar i){uchar x,y;for(x=i;x>;0;x--)for(y=110;y>;0;y--);}//初始化子函数void init(){TMOD=0x20;//T1工作在方式2TH1=0XF4; //波特率为:4.8kbit/s,发送与接收的波特率要相等TL1=0XF4;TR1=1; //启动定时器1SCON=0X50;//串口中断工作在方式1,允许接收}//显示子函数void display(){uchar i,j;//定义局部变量j=0x7f; //赋值for(i=0;i<6;i++) //显示六个数值 {P2=j;P0=table[table_tr[i]];delay(10);j=_cror_(j,1);//循环右移一位}}//主函数void main(){uchar i;//定义局部变量init(); //调用初始化子函数while(1){while(RI) //判断是否接受完{RI=0;//接受完了,标志位清零for(i=0;i<5;i++) //把数组的数值都往前移一位,腾出table_tr【5】table_tr[i]=table_tr[i+1];table_tr[5]=SBUF;//装入接收的数值 }display();//调用显示子函数}}。
51单片机双机串行通信设计
51单⽚机双机串⾏通信设计******************实践教学*******************XXXXX⼤学计算机与通信学院2013年秋季学期通信系统综合训练课程设计题⽬:51单⽚机双机串⾏通信设计专业班级:通信⼯程x班姓名:xx学号:xx指导教师:xx成绩:摘要双机通信的实质就是解决两单⽚机串⾏通信问题。
针对于89C51单⽚机全双⼯异步串⾏通信⼝,我们采⽤单⽚机直接交叉互连的串⾏通信⽅式。
考虑到本设计应⽤于短距离传输、两单⽚机具有相同的数据格式及电平且为使设计简单,我们最终决定本系统采⽤⽅式⼀单⽚机直接交叉连接的串⾏通信⽅式,上位机发送的数据由串⾏⼝TXD端输出,直接由下位机的串⾏⼝数据接收端RXD接收。
本设计的硬件电路分为数码管显⽰模块、单⽚机⼯作的基本复位电路以及晶振模块。
编程采⽤C语⾔加以实现。
通信的结果使⽤数码管进⾏显⽰,数码管采⽤查表⽅式显⽰,两个单⽚机之间采⽤RS-232进⾏双向通信。
关键字:51单⽚机串⾏通信 RS-232接⼝标准前⾔ (1)1 基本原理 (2)1.1 串⾏通信概述 (2)1.2 串⾏通信的分类 (2)1.3 串⾏通信技术标准 (2)1.4串⾏通信协议 (3)1.5串⾏通信与并⾏通信区别 (4)1.6MCS-51串⾏接⼝的基本特点 (5)1.7波特率选择 (7)1.8通信协议的使⽤ (7)1.951单⽚机的结构和作⽤ (7)1.10双机通信 (8)2 系统分析 (9)2.1汇编语⾔和C语⾔的特点及选择 (9)2.2并⾏通信与串⾏通信的⽐较 (9)2.3串⾏通信程序设计的⽐较 (9)2.4同步通信与异步通信的区别 (9)3 系统设计 (11)3.1设计要求 (11)3.2设计⽅案 (11)3.3硬件设计 (11)3.4软件设计 (14)4 系统调试 (20)总结 (21)参考⽂献 (22)致谢 (26)随着电⼦技术的飞速发展,单⽚机也步如⼀个新的时代,越来越多的功能各异的单⽚机为我们的设计提供了许多新的⽅法与思路。
51单片机多机通信过程
51单片机多机通信过程51单片机具有多机通信的功能,可实现一台主机于多台从机的通信。
多机通信充分利用了单片机内部的多机通信控制位SM2。
当从机SM2,1时,从机只接收主机发出的地址帧(第九位为1),对数据帧(第九位为0)不予理睬;而当SM2=0时,可接收主机发送过来的所有信息。
多机通信的过程如下:(1)所有从机SM2均置1,处于只接收地址帧状态。
(2)主机先发送一个地址帧,其中前8位数据表示地址,第9位为1表示该帧为地址帧。
(3)所有从机接收到地址帧后,进行中断处理,把接收到的地址与自身地址相比较。
地址相符时将SM2清成0,脱离多机状态,地址不相符的从机不作任何处理,即保持SM2,1。
(4)地址相符的从机SM2=0,可以接收到主机随后发来的信息,即主机发送的所有信息。
收到信息TB8=0,则表示是数据帧,而对于地址不符的从机SM2=1,收到信息TB8=0,则不予理睬,这样就实现了主机与地址相符的从机之间的双机通信。
(5)被寻址的从机通信结束后置SM2=1,恢复多机通信系统原有的状态。
主机:设置为SM2=0。
这是双机通信的形式,可以任意的发送和接收发送:以TB8=1发送,将发送到所有SM2=1的分机。
这是呼叫某个从机。
以TB8=0发送,将发送到SM2=0的分机。
这是双机通信的形式。
------从机:先设置为SM2=1。
这是多机通信的形式,只能收到RB8=1的。
接收:仅能收到RB8=1的数据,确认是呼叫本机时,令SM2=0。
设置为SM2=0后,是双机通信的形式。
追问那从机的RB8要怎么设,是需要软件设置还是单片机自己识别,在编程的时候要怎么写, 回答从机的RB8,不需要编程。
从机的RB8,是接收到的,它是主机发送出来的TB8。
想要对TB8进行控制,需要在主机中编程。
单片机多机通讯说明:该程序为多机通讯程序,最多可以挂255个从机。
该程序主机发送端与多个从机的接收端相接,主机的接收端与多个从机的发送端相接。
最新-MCS51系列单片机双机并行互连的实现方法 精品
MCS51系列单片机双机并行互连的实现方法摘要介绍了在同一系统内,51系列两单片机之间采用单向并行通信接口、主从双向并行通信接口、无主从双向并行通信操作实现双机互连的方法,分析了在每一种通信接口工作方式下数据传送的特点。
在三种并行通信接口为单片机应用系统扩充硬件资源的设计提供了新的途径。
关键词单片机并行通信接口数据传送由于51系列单片机具有性能稳定、工作可靠、价格低廉等特点,因此其应用相当广泛。
一个51系列的单片机如89内部包含有、、两个或者三个16位的定时器计数器、一个通用异步串行通信控制器等多种资源。
但即便如此,在一些相对复杂的单片机应用系统中,仅仅一个单片机资源还是不够的,因此而常常需要扩充接口、定时器计数器、串行通信接口、、等。
采用通用的标准器件进行扩充是通常的做法,但将单片机本身作为一个通用的扩充器件来使用,也不失为一个好的方法。
在这种情况下,一个系统中就使用了两个或两个以上的单片机,而单片机之间就要通过互连来进行数据通信。
51系列的单片机以下简称单片机都带有串口,利用串口进行互连通信极为方便,其各种连接方式在许多书籍和资料上都有介绍,在此不再重述。
但如果系统要求扩充的资源是对外连接的串口,或对相互之间的数据传送有一定的速度要求,则单片机的串口就不能用作系统内两单片机的通信接口了。
所幸的是,单片机的并行端口也能相互连接来进行数据通信。
根据单片机端口内部结构的特点,这些端口的端口线可以直接相连,从而使两单片机之间并行通信接口的实现不用另外的硬件电路设备。
基于这种情况,设计时,可根据不同的使用要求,来采用不同的并行连接方法。
下面介绍在两个单片机之间进行三种并行通信接口的实现方法。
1单向并行通信接口的实现在应用中,如果只需一个单片机向另一个单片机传送数据,则可以采用单向并行通信接口方式,这种方式较为简单。
图1所示为单向并行通信接口的组成方法。
MCS51系列单片机双机并行互连_职教论文
摘要:介绍了在同一个系统内,MCS51系列两单片机之间采用单向并行通信接口、主从双向并行通信接口、无主从双向并行通信操作实现双机互连的方法,分析了在每一种通信接口工作方式下数据传送的特点。
在三种并行通信接口为单片机应用系统扩充硬件资源的设计提供了新前途。
关键词:单片机并行通信接口数据传送由于MCS51系列单片机具有性能稳定、工作可靠、价格低廉等特点,因此其应用相当广泛。
一个MCS51系列的单片机内部包含有RAM、FLASH、两个或者三个16位的定时器/计数器、一个通用异步串行通信控制器等多种资源。
但即便如此,在一些相对复杂的单片机应用系统中,仅仅一个单片机资源还是不够的,因此而常常需要扩充I/O接口、定时器/计数器、串行通信接口、RAM、ROM等。
采用通用的标准器件进行扩充是通常的做法,但将单片机本身作为一个通用的扩充器件来使用,也不失为一个好方法。
在这种情况下,一个系统中就使用了两个或两个以上的单片机,而单片机之间就要通过互连来进行数据通信。
MCS51系列的单片机都带有串口,利用串口进行互连通信极为方便,其各种连接方式在许多书籍和资料上都有介绍,在此不再重述。
但如果系统要求扩充的资源是对外连接的串口,或对相互之间的数据传送有一定的速度要求,则单片机的串口就不能用作系统内两单片机的通信接口了。
所幸的是,单片机的并行端口也能相互连接来进行数据通信。
根据单片机端口内部结构的特点,这些端口的端口线可以直接相连,从而使两单片机之间并行通信接口的实现不用另外的硬件电路设备。
基于这种情况,设计时,可根据不同的使用要求,来采用不同的并行连接方法。
下面介绍在两个单片机之间进行三种并行通信接口的实现方法。
1、单向并行通信接口的实现在应用中,如果只需一个单片机向另一个单片机传送数据,则可以采用单向行通信接口方式,这种方式比较简单。
图1所示为单向并行通信接口的组成方法。
图中,单片机A为数据发送方,单片机B为数据接收方,8位端口可以是P0~3的任何一个。
MCS51系列单片机双机并行互连的实现方法
MCS51系列单片机双机并行互连的实现方法介绍了在同一系统内,MCS51系列两单片机之间采用单向并行通信接口、主从双向并行通信接口、无主从双向并行通信操作实现双机互连的方法,分析了在每一种通信接口工作方式下数据传送的特点。
在三种并行通信接口为单片机应用系统扩充硬件资源的设计提供了新的途径。
由于MCS51系列单片机具有性能稳定、工作可*、价格低廉等特点,因此其应用相当广泛。
一个MCS51系列的单片机(如Atmel89cxx)内部包含有RAM、FLASH ROM、两个或者三个16位的定时器/计数器、一个通用异步串行通信控制器(UART)等多种资源。
但即便如此,在一些相对复杂的单片机应用系统中,仅仅一个单片机资源还是不够的,因此而常常需要扩充I/O接口、定时器/计数器、串行通信接口、RAM、ROM等。
采用通用的标准器件进行扩充是通常的做法,但将单片机本身作为一个通用的扩充器件来使用,也不失为一个好的方法。
在这种情况下,一个系统中就使用了两个或两个以上的单片机,而单片机之间就要通过互连来进行数据通信。
MCS51系列的单片机(以下简称单片机)都带有串口,利用串口进行互连通信极为方便,其各种连接方式在许多书籍和资料上都有介绍,在此不再重述。
但如果系统要求扩充的资源是对外连接的串口,或对相互之间的数据传送有一定的速度要求,则单片机的串口就不能用作系统内两单片机的通信接口了。
所幸的是,单片机的并行端口也能相互连接来进行数据通信。
根据单片机端口内部结构的特点,这些端口的端口线可以直接相连,从而使两单片机之间并行通信接口的实现不用另外的硬件电路设备。
基于这种情况,设计时,可根据不同的使用要求,来采用不同的并行连接方法。
下面介绍在两个单片机之间进行三种并行通信接口的实现方法。
1 单向并行通信接口的实现在应用中,如果只需一个单片机向另一个单片机传送数据,则可以采用单向并行通信接口方式,这种方式较为简单。
图1所示为单向并行通信接口的组成方法。
无线模块NRF24L01基于C51单片机-双向通讯C语言程序(中文详解)
#include <reg52.h>#include <intrins.h>/******************************************************************************** *******//* NRF24L01 的管脚定义,以及在本程序中的应用,VCC接3.3V电源,可以通过5V用电压转换芯片/*得到,NC 管脚可以接可以不接,暂时没用途。
本程序应用于51或者52单片机,是两个模块进行通讯/*成功的简单指示,现象是:模块1的 KEY1 对应模块1的LED1 和模块2的LED3 ,模块1的 KEY2 对应模/*块1的LED2 和模块2的LED4,发过来也对应。
/******************************************************************************** *******/typedef unsigned char uchar;typedef unsigned char uint;/************************************NRF24L01端口定义***********************************/sbit NC =P2^0; //没用,不接也可sbit MISO =P2^5; //数字输出(从 SPI 数据输出脚)sbit MOSI =P2^4; //数字输入(从 SPI 数据输入脚)sbit SCK =P1^7; //数字输入(SPI 时钟)sbit CE =P2^1; //数字输入(RX 或 TX 模式选择)sbit CSN =P2^2; //数字输入(SPI片选信号)sbit IRQ =P2^6; //数字输入(可屏蔽中断)/************************************按键***********************************************/sbit KEY1=P3^3;//按键S1sbit KEY2=P3^2;//按键S2/************************************数码管位选******************************************/sbit led1=P1^0; //LED0sbit led2=P1^1; //LED1sbit led3 =P1^2; //LED2sbit led4 =P1^3; //LED3sbit led5 =P1^4; //LED4/*********************************************NRF24L01*************************** ********/#define TX_ADR_WIDTH 5 // 5 uints TX address width 发送地址宽度#define RX_ADR_WIDTH 5 // 5 uints RX address width 接收地址宽度#define TX_PLOAD_WIDTH 20 // 20 uints TX payload 有效载荷装载货物#define RX_PLOAD_WIDTH 20 // 20 uints TX payloaduint const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址uint const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址/***************************************NRF24L01寄存器指令*******************************/#define READ_REG 0x00 // 读寄存器指令#define WRITE_REG 0x20 // 写寄存器指令#define RD_RX_PLOAD 0x61 // 读取接收数据指令#define WR_TX_PLOAD 0xA0 // 写待发数据指令#define FLUSH_TX 0xE1 // 冲洗发送 FIFO指令#define FLUSH_RX 0xE2 // 冲洗接收 FIFO指令#define REUSE_TX_PL 0xE3 // 定义重复装载数据指令#define NOP 0xFF // 保留/*************************************SPI(nRF24L01)寄存器地址***********************/#define CONFIG 0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式#define EN_AA 0x01 // 自动应答功能设置#define EN_RXADDR 0x02 // 可用信道设置#define SETUP_AW 0x03 // 收发地址宽度设置#define SETUP_RETR 0x04 // 自动重发功能设置#define RF_CH 0x05 // 工作频率设置#define RF_SETUP 0x06 // 发射速率、功耗功能设置#define STATUS 0x07 // 状态寄存器#define OBSERVE_TX 0x08 // 发送监测功能#define CD 0x09 // 地址检测#define RX_ADDR_P0 0x0A // 频道0接收数据地址#define RX_ADDR_P1 0x0B // 频道1接收数据地址#define RX_ADDR_P2 0x0C // 频道2接收数据地址#define RX_ADDR_P3 0x0D // 频道3接收数据地址#define RX_ADDR_P4 0x0E // 频道4接收数据地址#define RX_ADDR_P5 0x0F // 频道5接收数据地址#define TX_ADDR 0x10 // 发送地址寄存器#define RX_PW_P0 0x11 // 接收频道0接收数据长度#define RX_PW_P1 0x12 // 接收频道0接收数据长度#define RX_PW_P2 0x13 // 接收频道0接收数据长度#define RX_PW_P3 0x14 // 接收频道0接收数据长度#define RX_PW_P4 0x15 // 接收频道0接收数据长度#define RX_PW_P5 0x16 // 接收频道0接收数据长度#define FIFO_STATUS 0x17 // FIFO栈入栈出状态寄存器设置/*************************************函数声明****************************************/void Delay(unsigned int s); //大延时void inerDelay_us(unsigned char n); //小延时void init_NRF24L01(void); //NRF24L01 初始化uint SPI_RW(uint dat); //根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01读出一字节uchar SPI_Read(uchar reg); //从reg寄存器读一字节void SetRX_Mode(void); //数据接收配置uint SPI_RW_Reg(uchar reg, uchar value); //写数据value到reg寄存器uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars); //从reg寄存器读出bytes 个字节,通常用来读取接收通道数据或接收/发送地址uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars); //把pBuf缓存中的数据写入到nRF24L01,通常用来写入发射通道数据或接收/发送地址unsigned char nRF24L01_RxPacket(unsigned char* rx_buf); //数据读取后放入rx_buf接收缓冲区中void nRF24L01_TxPacket(unsigned char * tx_buf); //发送 tx_buf中数据/*****************************************长延时*****************************************/void Delay(unsigned int s){unsigned int i;for(i=0; i<s; i++);for(i=0; i<s; i++);}/******************************************************************************** **********/uint bdata sta; //状态标志sbit RX_DR =sta^6; //RX_DR 为 sta 的第六位sbit TX_DS =sta^5; //TX_DS 为 sta 的第五位sbit MAX_RT =sta^4; //MAX_RT 为 sta 的第四位/******************************************************************************** **********//*延时函数/******************************************************************************** **********/void inerDelay_us(unsigned char n) //延时,us 级{for(;n>0;n--)_nop_();}/******************************************************************************** ********//*NRF24L01初始化/******************************************************************************** *******/void init_NRF24L01(void){inerDelay_us(100);CE=0; // 芯片使能CSN=1; // 禁止 SPISCK=0; // SPI时钟置低SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写本地地址SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); // 写接收端地址SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // 频道0自动ACK应答允许SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01); // 允许接收地址只有频道0,如果需要多频道可以参考Page21SPI_RW_Reg(WRITE_REG + RF_CH, 0); // 设置信道工作为2.4GHZ,收发必须一致SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); //设置发射速率为1MHZ,发射功率为最大值0dB}/******************************************************************************** ********************//*函数:uint SPI_RW(uint uchar)/*功能:NRF24L01的SPI写时序-----根据SPI协议,写一字节数据到nRF24L01,同时从nRF24L01 读出一字节/******************************************************************************** ********************/uint SPI_RW(uint dat){uint i;for(i=0;i<8;i++) // 循环8次{MOSI = (dat & 0x80); // dat的最高位输出到MOSI MSB to MOSIdat = (dat << 1); // 从右向左进一位shift next bit into MSB..SCK = 1; // 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据Set SCK high..dat |= MISO; //读MISO到 dat 最低位 capture current MISO bitSCK = 0; // SCK置低..then set SCK low again}return(dat); //返回读出的一字节 return read dat}/******************************************************************************** ********************/*函数:uchar SPI_Read(uchar reg)/*功能:NRF24L01的SPI时序-----------从reg寄存器读一字节/******************************************************************************** ********************/uchar SPI_Read(uchar reg){uchar reg_val;CSN = 0; //CSN置低,开始传输数据CSN low, initialize SPI communication...SPI_RW(reg); //选择寄存器 Select register to read from..reg_val = SPI_RW(0); //然后从该寄存器读数据 ..then read registervalueCSN = 1; //CSN拉高,结束数据传输CSN high, terminate SPI communicationreturn(reg_val); //返回寄存器数据 return register value}/******************************************************************************** ********************//*功能:NRF24L01读写寄存器函数/*描述:写数据value到reg寄存器/******************************************************************************** ********************/uint SPI_RW_Reg(uchar reg, uchar value){uchar status;CSN = 0; // CSN置低,开始传输数据CSN low, init SPI transactionstatus = SPI_RW(reg); // 选择寄存器,同时返回状态字 select registerSPI_RW(value); // 然后写数据到该寄存器 ..and write value to it..CSN = 1; // CSN拉高,结束数据传输CSN high againreturn(status); // 返回状态寄存器 returnnRF24L01 status uchar}/******************************************************************************** ********************//*函数:uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于读数据,reg:为寄存器地址,pBuf:为待读出数据地址,uchars:读出数据的个数/*描述: 从reg寄存器读出bytes个字节,通常用来读取接收通道数据或接收/发送地址/******************************************************************************** ********************/uint SPI_Read_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,i;CSN = 0; //CSN置低,开始传输数据 Set CSN low, init SPI tranactionstatus = SPI_RW(reg); //选择寄存器,同时返回状态字 Select register to write to and read status ucharfor(i=0;i<uchars;i++)pBuf[i] = SPI_RW(0); //逐个字节从nRF24L01读出CSN = 1; //CSN拉高,结束数据传输return(status); //返回状态寄存器return nRF24L01 status uchar}/******************************************************************************** *************************/*函数:uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars)/*功能: 用于写数据:为寄存器地址,pBuf:为待写入数据地址,uchars:写入数据的个数/*描述:把pBuf缓存中的数据写入到nRF24L01,通常用来写入发射通道数据或接收/发送地址/******************************************************************************** *************************/uint SPI_Write_Buf(uchar reg, uchar *pBuf, uchar uchars){uint status,i;CSN = 0; //CSN置低,开始传输数据status = SPI_RW(reg); //选择寄存器,同时返回状态字inerDelay_us(10);for(i=0; i<uchars; i++)SPI_RW(*pBuf++); //逐个字节写入nRF24L01CSN = 1; //CSN拉高,结束数据传输return(status); //返回状态寄存器}/******************************************************************************** ********************//*函数:void SetRX_Mode(void)/*功能:数据接收配置/******************************************************************************** ********************/void SetRX_Mode(void){CE=0;SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);//CRC使能,16位CRC校验,上电,接收模式CE = 1; // 拉高CE启动接收设备inerDelay_us(130);}/******************************************************************************** **********************//*函数:unsigned char nRF24L01_RxPacket(unsigned char* rx_buf)/*功能:数据读取后放入rx_buf接收缓冲区中/******************************************************************************** **********************/unsigned char nRF24L01_RxPacket(unsigned char* rx_buf){unsigned char revale=0;sta=SPI_Read(STATUS); // 读取状态寄存其来判断数据接收状况if(RX_DR) // 判断是否接收到数据{CE = 0; //SPI使能SPI_Read_Buf(RD_RX_PLOAD,rx_buf,TX_PLOAD_WIDTH);// read receive payload from RX_FIFO bufferrevale =1; //读取数据完成标志}SPI_RW_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志return revale;}/******************************************************************************** ***************************/*函数:void nRF24L01_TxPacket(unsigned char * tx_buf)/*功能:发送 tx_buf中数据/******************************************************************************** **************************/void nRF24L01_TxPacket(unsigned char * tx_buf){CE=0; //StandBy I模式SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // 装载接收端地址SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 装载数据SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // IRQ收发完成中断响应,16位CRC,主发送CE=1; //置高CE,激发数据发送inerDelay_us(10);}/************************************主函数************************************************************/void main(void){unsigned char tf =0;unsigned char TxBuf[20]={0}; // 要发送的数组unsigned char RxBuf[20]={0}; // 接收的数据数组init_NRF24L01() ; //模块初始化led1=1;led2=1;led3 =1;led4 =1; //led 灯关闭Delay(1000);while(1){if(KEY1 ==0 ) //按键 1 按下{TxBuf[1] = 1 ; //赋值tf = 1 ;led1=0; //本地led 灯闪烁Delay(200);led1=1;Delay(200);}if(KEY2 ==0 ) //按键 2 按下{TxBuf[2] =1 ; //赋值tf = 1 ;led2=0; //本地led 灯闪烁Delay(200);led2=1;Delay(200);}if (tf==1) //有键按下{nRF24L01_TxPacket(TxBuf); //发送数据 Transmit Tx buffer dataTxBuf[1] = 0x00; //清零TxBuf[2] = 0x00;tf=0;Delay(1000);}SetRX_Mode(); //设置成接受模式RxBuf[1] = 0x00; //接收的数组相应位清零RxBuf[2] = 0x00;Delay(1000);nRF24L01_RxPacket(RxBuf); //接收数据if(RxBuf[1]|RxBuf[2]){if( RxBuf[1]==1){led3=RxBuf[0];}if( RxBuf[2]==1){led4=RxBuf[4];}Delay(3000); //old is '1000'}RxBuf[1] = 0x00; //清零RxBuf[2] = 0x00;led3=1; //关灯led4=1;}}本程序存在的问题:反应不够灵敏,当在按键1和按键2之间切换的时候,对方的灯闪烁会有一定的延时,另外本程序没有消除按键的抖动。
C51设计多机通信程序代码实例
--------以上部分请勿修改!-------------;****************************************;文件:Transmission.asm;功能:A VR双CPU通信程序,异步方式,类似于UART ;器件:AT90S2313;硬件:主从CPU的PD.2通过上拉电阻连接;时钟:4.0MHz;设计:Lindong;日期:2003年8月8日;****************************************.include"2313def.inc".equ port =PORTD.equ pin =PIND.equ ddr =DDRD.equ bit =2;*****************************************;中断向量表;*****************************************.org 0x000rjmp mainrjmp INT0_isrretiretiretiretiretiretiretireti;*****************************************;程序入口;*****************************************.org 0x000Bmain: ldi R16,0xDF ;设置堆栈指针out spl,R16cbi port,bit ;设置端口方向cbi ddr,bitldi R16,0x02 ;INT0 下降沿有效out MCUCR,R16ldi R16,0x40 ;INT0 中断使能out GIMSK,R16sei ;全局中断使能ldi R28,0x60ldi R29,0x00ldi R22,0x10here: ldi R30,0x55 ;测试rcall sendbyterjmp here;***************************************** ;过程名:Delay;功能:us级别精确延时;入口参数:R16 延时时间微秒数-2;出口参数:无;影响资源:;***************************************** delay: dec R16nopbrne delaynopret;***************************************** ;外部中断INTI0中断服务程序(读数);***************************************** INT0_isr:ldi R16,0x49 ;延时75usrcall delaysbic pin,bitrjmp skipclr R30rcall readbit ;Clock 1rcall readbit ;Clock 2mov R31,R30ldi R20,0x08RNext: rcall readbit ;读数dec R20brne RNextdeal: nop ;数据处理,数据存放在R30中,两个时钟信号存在R31 的高两位skip: reti ;非起始信号,跳过;*****************************************;过程名:readbit;功能:从总线上读取一位数据;入口参数:无;出口参数:R30;影响资源:R16;*****************************************readbit:ldi R16,0x08 ;延时10usrcall delaywaitu1: sbis pin,bit ;Wait for "1"rjmp waitu1waitu2: sbis pin,bit ;Wait for "1"rjmp waitu2waitu3: sbis pin,bit ;Wait for "1"rjmp waitu3waitu4: sbis pin,bit ;Wait for "1"rjmp waitu4waitf1: sbic pin,bit ;Wait for the falling edgerjmp waitf1waitf2: sbic pin,bit ;Wait for the falling edgerjmp waitf2waitf3: sbic pin,bit ;Wait for the falling edgerjmp waitf3waitf4: sbic pin,bit ;Wait for the falling edgerjmp waitf4ldi R16,0x2B ;延时45usrcall delayclc ;清Csbis pin,bitsecror R30 ;存数ret;***************************************** ;过程名:sendbit;功能:传出一位数据;入口参数:R30;出口参数:无;影响资源:;***************************************** sendbit:sbrs R30,0rjmp send0send1: sbi ddr,bit ;Send a "1"ldi R16,0x3Arcall delaycbi ddr,bitldi R16,0x1Crcall delayretsend0: sbi ddr,bit ;Send a "0"ldi R16,0x1Crcall delaycbi ddr,bitldi R16,0x3Arcall delayret;***************************************** ;过程名:sendbyte;功能:传出一个字节数据;入口参数:R30;出口参数:无;影响资源:R24;***************************************** sendbyte: ;测试总线是否忙sbis pin,bitrjmp sendbyteldi R16,0x76 ;延时120usrcall delaysbis pin,bit ;测试rjmp sendbytecli ;关中断sbi ddr,bit ;总线初始化ldi R16,0x58 ;延时90usrcall delaycbi ddr,bitldi R16,0x1C ;延时30usrcall delaysbi ddr,bit ;Clock 1ldi R16,0x3A ;延时60usrcall delaycbi ddr,bitldi R16,0x1C ;延时30usrcall delaysbi ddr,bit ;Clock 2ldi R16,0x1Crcall delay ;延时30uscbi ddr,bitldi R16,0x3A ;延时60usrcall delayldi R24,0x08 ;设置计数器nextbit:rcall sendbit ;输出数据ror R30dec R24brne nextbitldi R16,0xFF ;清中断标志out GIFR,R16sei ;开中断ret;***************************************** ;This is the end。
两个MCS-51单片机之间双向通信
微型计算机技术专业方向课程设计
任务书
题目名称:两个MCS-51单片机之间双向通信
专业班级
姓名学号
学校:
指导教师:
课程设计任务书
课程名称:微型计算机技术
设计题目:两个MCS-51单片机之间双向通信
系统硬件要求:
利用两个单片机AT89C5实现如下功能:
1、甲机向乙机发送控制命令字符,甲机同时接收乙机发送的数字,并显示在数码管上。
2、乙机程序接收甲机发送字符并完成相应动作
说明:乙机接收到甲机发送的信号后,根据相应信号控制LED完成不同闪烁动作。
软件设计:
1)主程序设计
2)各功能子程序设计
其他要求:
1、每位同学独立完成本设计。
2、依据题目要求,提出系统设计方案。
3、设计系统电路原理图。
1、调试系统硬件电路、功能程序。
2、编制课程设计报告书并装订成册,报告书内容(按顺序)(1)报告书封面
(2)课程设计任务书
(3)系统设计方案的提出、分析
(4)系统中典型电路的分析
(5)系统软件结构框图
(6)系统电路原理图
(7)源程序
(8)课设字数不少于2000字
成绩
评语。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
}
}
//按键扫描子函数
void key_scan()
{
if(key1==0) //判断是否有按键按下
{
while(!key1) //等待按键松手
{
10);
j=_cror_(j,1);//循环右移一位
}
}
//主函数
void main()
{
uchar i;//定义局部变量
init(); //调用初始化子函数
while(1)
{
key_scan(); //调用键盘扫描子函数
display();//调用显示子函数
}
}
参考链接:/news/2010-02/1915.htm
*
接收程序
线路连接:同上, 主从单片机用3线连接,共地,rxd,txd交叉
程序效果:用于显示主机发送的数值
*/
#include<reg52.h> //头文件
#include<intrins.h> //循环文件
#define uchar unsigned char//宏定义
{
while(RI) //判断是否接受完
{
RI=0;//接受完了,标志位清零
for(i=0;i<5;i++) //把数组的数值都往前移一位,腾出table_tr【5】
table_tr[i]=table_tr[i+1];
}
//显示子函数
void display()
{
uchar i,j;//定义局部变量
j=0x7f; //赋值
for(i=0;i<6;i++) //显示六个数值
{
P2=j;
P0=table[table_tr[i]];
#define uint unsigned int
uchar code table[]={0X00,0x3f,0x06,0x5b,//数码管显示的数值
0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar table_tr[6];//暂存最后按下的六个数值
在主机中通过记下按键按下的次数,主机中显示最后
按下的六个数值,并发送给从机,从机也显示这六个数值
*/
#include<reg52.h> //头文件
#include<intrins.h> //循环移位文件
#define uchar unsigned char//宏定义
#define uint unsigned int
if(cnt==10) //按键按下的次数有没有等于10
cnt=0;//等于,则清零
}
}
void main()
{
init(); //调用初始化子函数
P0=0x00;
while(1)
void init()
{
TMOD=0x20;//T1工作在方式2
TH1=0XF4; //波特率为:4.8kbit/s,发送与接收的波特率要相等
TL1=0XF4;
TR1=1; //启动定时器1
SCON=0X50;//串口中断工作在方式1,允许接收
display();//防止掉显
}
cnt++; //加1,用于显示
SBUF=cnt;//送给缓冲区,发送
while(!TI); //等待发送完
TI=0; //发送完了,标志位清零
for(count=0;count<5;count++) //用于保存最后按下的六个按键数值
{
table_tr[count]=table_tr[count+1];
}
table_tr[5]=cnt; //把最后按下的按键数值赋给table_tr【5】
uchar count,cnt;//定义全局变量
//延时子函数,用于数码管显示
void delay(uchar i)
{
uchar x,y;
for(x=i;x>0;x--)
for(y=110;y>0;y--);
}
//初始化子函数
j=0x7f; //赋初值
for(i=0;i<6;i++)
{
P2=j; //点亮最右边的数码管
P0=table[table_tr[i]]; //显示该数值
delay(10); //延时,便于眼睛看清
sbit key1=P3^5; //位声明
uchar code table[]={0X00,0x3f,0x06,0x5b,//数码管显示的数值
0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar table_tr[6];//暂存最后按下的六个数值
uchar count,cnt;
TH1=0XF4;//波特率为4.8kbit/s
TL1=0XF4;
TR1=1;//启动定时器1
SCON=0X50;//串口工作在方式1,允许接收
}
//显示子函数
void display()
{
uchar i,j;//定义局部变量
table_tr[5]=SBUF;//装入接收的数值
}
display();//调用显示子函数
}
}
/*
发送程序
连线:两个单片机用3根线连起来,要共地,rxd,txd要交叉连接
程序效果:通过主机发送,从机接收
//延时子函数,用于数码管显示
void delay(uchar i)
{
uchar x,y;
for(x=i;x>0;x--)
for(y=110;y>0;y--);
}
//初始化子函数
void init()
{
TMOD=0x20;//T1工作在方式2