51单片机串口通信试验汇编程序
- 格式:docx
- 大小:8.24 KB
- 文档页数:5
一、实验项目名称串口通信实验二、实验内容现有两台单片机应用系统。
甲机发送内存中以TR_BUF为首地址的10个数据串,乙机把接收到的数据存入以RC_BUF为首地址的内存单元中。
设甲、乙两机的振荡频率为12MHz,串行口均工作在方式1下。
要求甲机用查询方式编程,乙机用中断方式编程。
三、实验原理图(纯软件部分实验报告可不要本部分)四、编程思路及算法分析流程图:五、程序清单甲机发送内存中以TR_BUF为首地址的10个数据串.org 0000hmov r2,#10mov r1,#tr_bufmov a,#0fehlp1: mov @r1,arl ainc r1djnz r2,lp1mov TMOD,#20Hmov th1,#0fdhmov tl1,#0fdhsetb tr1mov scon,#40hmov r0,#tr_bufmov r7,#100acall dy1slp: mov sbuf,@r0jnb ti,$clr tiinc r0djnz r7,lpsjmp $dy1s: mov r6,#200m1: mov r5,#0fahdjnz r5,$djnz R6,m1retEnd乙机把接收到的数据存入以RC_BUF为首地址的内存单元中org 0000hajmp mainorg 0023hajmp s20fworg 0030hmain: mov TMOD,#20Hmov th1,#0fdhmov tl1,#0fdhsetb tr1setb essetb eamov scon,#50hmov r0,#rc_bufmov r2,#10sjmp $s20fw: clr rimov @r0,sbufinc r0djnz r2,fanmov r3,#10mov r1,#rc_buflp1: mov a,@r1mov p1,aacall dy1sinc r1djnz r3,lp1fan: retidy1s: mov r6,#200m1: mov r5,#0fahdjnz r5,$djnz R6,m1retend六、实验仿真结果要有适当的图文解释。
51单片机的串口通信程序(C语言) 51单片机的串口通信程序(C语言)在嵌入式系统中,串口通信是一种常见的数据传输方式,也是单片机与外部设备进行通信的重要手段之一。
本文将介绍使用C语言编写51单片机的串口通信程序。
1. 硬件准备在开始编写串口通信程序之前,需要准备好相应的硬件设备。
首先,我们需要一块51单片机开发板,内置了串口通信功能。
另外,我们还需要连接一个与单片机通信的外部设备,例如计算机或其他单片机。
2. 引入头文件在C语言中,我们需要引入相应的头文件来使用串口通信相关的函数。
在51单片机中,我们需要引入reg51.h头文件,以便使用单片机的寄存器操作相关函数。
同时,我们还需要引入头文件来定义串口通信的相关寄存器。
3. 配置串口参数在使用串口通信之前,我们需要配置串口的参数,例如波特率、数据位、停止位等。
这些参数的配置需要根据实际需要进行调整。
在51单片机中,我们可以通过写入相应的寄存器来配置串口参数。
4. 初始化串口在配置完串口参数之后,我们需要初始化串口,以便开始进行数据的发送和接收。
初始化串口的过程包括打开串口、设置中断等。
5. 数据发送在串口通信中,数据的发送通常分为两种方式:阻塞发送和非阻塞发送。
阻塞发送是指程序在发送完数据之后才会继续执行下面的代码,而非阻塞发送是指程序在发送数据的同时可以继续执行其他代码。
6. 数据接收数据的接收与数据的发送类似,同样有阻塞接收和非阻塞接收两种方式。
在接收数据时,需要不断地检测是否有数据到达,并及时进行处理。
7. 中断处理在串口通信中,中断是一种常见的处理方式。
通过使用中断,可以及时地响应串口数据的到达或者发送完成等事件,提高程序的处理效率。
8. 串口通信实例下面是一个简单的串口通信实例,用于在51单片机与计算机之间进行数据的传输。
```c#include <reg51.h>#include <stdio.h>#define BAUDRATE 9600#define FOSC 11059200void UART_init(){TMOD = 0x20; // 设置定时器1为模式2SCON = 0x50; // 设置串口为模式1,允许接收TH1 = 256 - FOSC / 12 / 32 / BAUDRATE; // 计算波特率定时器重载值TR1 = 1; // 启动定时器1EA = 1; // 允许中断ES = 1; // 允许串口中断}void UART_send_byte(unsigned char byte){SBUF = byte;while (!TI); // 等待发送完成TI = 0; // 清除发送完成标志位}unsigned char UART_receive_byte(){while (!RI); // 等待接收完成RI = 0; // 清除接收完成标志位return SBUF;}void UART_send_string(char *s){while (*s){UART_send_byte(*s);s++;}}void main(){UART_init();UART_send_string("Hello, World!"); while (1){unsigned char data = UART_receive_byte();// 对接收到的数据进行处理}}```总结:通过以上步骤,我们可以编写出简单的51单片机串口通信程序。
以下程序通过实践检测完全可以放心使用不过注意硬件电路的连接单片机的串口通信主要理解SCON的状态控制寄存器的用法波特率的设定1 两个单片机一个为主机一个为从机,又主机控制从机的LED灯得简单程序入手注意硬件的连线将单片机串口的第二引脚与另一单片机串口的第三引脚相连同时另一单片机的第二串口引脚也与前一个单片机的第三引脚相连主机部分的程序设计//主机程序发送控制信号的#include〈reg52。
h〉#define uchar unsigned char#define uint unsigned intsbit KEY=P3^0;//按键sbit ledA=P1^1;//定义了三个灯来指示发送的字符是什么sbit ledB=P1^3;sbit ledC=P1^5;sbit ledstop=P1^6;uchar KEY_number=0;//按键计数void delay(unsigned int z)//延时函数{unsigned int x,y;for(x=z;x〉0;x—-)for(y=240;y〉0;y-—);}void init(){SCON=0x40;//主机串口工作方式1 REN=0 之允许发送不能接收TMOD=0x20;PCON=0x00;TH1=0xfd;TL1=0xfd;T1=RI=0;//必须要做来保证可以顺利进入终端TR1=1;EA=1;ES=1;}void Put_charToSBUF(uchar c) //把一个字符写入SBUF{SBUF=c;while(TI==0); //巧妙的等待处理等带发送完毕TI=0;}void main(){init();while(1){if(KEY==0){delay(5);if(KEY==0){ P1=0xff;while(!KEY);KEY_number++;if(KEY_number==4) KEY_number=0;}}switch (KEY_number){case 0: ledstop=0; break;case 1: ledA=~ledA; Put_charToSBUF(’A’);break;case 2: ledB=~ledB; Put_charToSBUF('B'); break;case 3: ledC=~ledC; Put_charToSBUF('C'); break;}delay(100) ;}}从机部分的程序#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit d1=P1^0;sbit d2=P1^1;sbit d3=P1^2;void delay(unsigned int z)//延时函数{unsigned int x,y;for(x=z;x〉0;x—-)for(y=240;y〉0;y—-);}void init(){SCON=0x50;//允许串口接收 TMOD=0x20;PCON=0x00;TH1=0xfd;TL1=0xfd;RI=0;TR1=1;EA=1;ES=1;}void main(){init();while(1){if(RI){RI=0;switch(SBUF){case 'A’: d1=~d1;break;case 'B’: d1=1; d2=~d2;break;case ’C’: d2=1; d3=~d3; break;}}else d1=d2=d3=1;delay(100) ;}}上面的程序是一主一从单片机之间也可以建立一个双向的通信过程//甲机程序发送控制信号的同时接收乙机发来的串口信息并//且显示在数码管上#include〈reg52。
51单片机与PC串口通信程序及硬件电路图#include <reg51.h>#define BUFFERLEGTH 10//----------------------------------------------------------------- void UART_init(); //串口初始化函数void COM_send(void); //串口发送函数char str[20];char j;//-------------------------------------------------------------------void main(void){unsigned char i;UART_init();j=0; //初始化串口for(i = 0;i < 10 ;i++){COM_send(); //首先发送一次数据作为测试用};while(1);}//-------------------------------------------------------------//--------------------------------------------------------------------------------------------------// 函数名称: UART_init()串口初始化函数// 函数功能:在系统时钟为11.059MHZ时,设定串口波特率为9600bit/s// 串口接收中断允许,发送中断禁止//--------------------------------------------------------------------------------------------------void UART_init(){//初始化串行口和波特率发生器SCON =0x50; //选择串口工作方式1,打开接收允许TMOD =0x20; //定时器1工作在方式2,定时器0工作在方式1 TH1 =0xfA; //实现波特率9600(系统时钟11.0592MHZ)PCON = 0x80;TR1 =1; //启动定时器T1ET1 =0;ES=1; //允许串行口中断PS=1; //设计串行口中断优先级EA =1; //单片机中断允许}//------------------------------------------------------------void COM_send(void){unsigned char point = 0;for(point=0;str[point]!='\0';point++) //连续发送二十位数据 //把缓存区的数据都发送到串口 {SBUF=str[point];while(!TI);TI=0;//str[point]='\0';}}//--------------------------------------------------------------//--------------------------------------------------------------------------------------------------// 函数名称: com_interrup()串口接收中断处理函数// 函数功能:接收包括起始位'S'在内的十位数据到数据缓冲区//--------------------------------------------------------------------------------------------------void com_interrupt(void) interrupt 4 using 3{unsigned char RECEIVR_buffer;bit flag=1;if(RI) //处理接收中断{RI=0; //清除中断标志位RECEIVR_buffer=SBUF; //接收串口数据str[j]=SBUF;if (RECEIVR_buffer == '$'){ ES=0;str[j]='\0';SCON =0x40; //接收不允许COM_send(); //发送数据ES=1;j=0;flag=0;SCON=0x50; //接收允许}if(flag)j++;}}。
51单片机串口通信程序(方式2)//应网要求而写//给89c2051单片机编程,用管脚控制其状态输出,即管脚1为高电平时单片机串行口输出十六进制“BBBB0000”的脉冲信号,如果是低电平时再由其他的管脚控制其输出“CCCC5555”和“AAAA1111”。
// 要求:1、单片机没隔40ms发送一组数据// 2、串行口工作是在模式2下进行输出的// 3、波特率是93.75k//此程序写2011年6月9日//特别声明,此程序还未在硬件上测试,请网友们帮忙测试,多提宝贵意见#include <reg51.h>sbit key1 = P1^0;sbit key2 = P1^1;sbit key3 = P1^2;code unsigned char senddata1[4 ]={0xBB,0xBB,0x00,0x00 };code unsigned char senddata2[4]={0xCC,0xCC,0x00,0x00 };code unsigned char senddata3[4 ]={0xAA,0xAA,0x00,0x00 };bit flagcomsend; //串口发送标志,void R_S_Byte(unsigned char R_Byte) //串发送程序{SBUF = R_Byte;while( TI == 0 );TI = 0;}void comsend(unsigned char *TxRxBuffer){unsigned char i;//ES=0;for(i=0;i<4;i++) // 只发送了实际的数据{R_S_Byte(TxRxBuffer[i]);}//ES=1;}void StartUARTT0( void ){ //波特率93.75晶振 6M 串口方式2TMOD = 0x01;SCON = 0x80; //串口方式2,不允许接收TH0 = 0xB1;// 定时器0,方式1,定时40MSTL0 = 0xE0;PCON = 0x00; //波特率不加倍ET0 = 1; PT0 = 1;TR0 = 1;EA = 1;ES = 0;}void intt0( void ) interrupt 1 using 1{ET0 = 0;TH0 = 0xB1;// 定时器0,方式1,定时40MS TL0 = 0xE0;flagcomsend=1; //串口发送标志ET0 = 1; TF0 = 0;}void main(){StartUARTT0( );TR0 = 0;while(1){key1 = 1; key2 = 1; key3 = 1;if( key1||key2||key3){TR0 = 1;}else{TR0 = 0;}if(flagcomsend){flagcomsend = 0;if( key1&&(!key2)&&(!key3)){comsend(senddata1 );}else if( key2&&(!key1)&&(!key3)) {comsend(senddata2 );}else if( key3&&(!key2)&&(!key1)) {comsend(senddata3 );}else{TR0 = 0;}}}}。
51单片机汇编语言教程:第22课-单片机串行口通信程序设计.mov SCON,#50h;Standard UART settingsMOV R0,#0AAH;准备送出的数SETB REN;允许接收SETB TR1;T1开始工作WAIT:MOV A,R0CPL AMOV R0,AMOV SBUF,ALCALL DELAYJBC TI,WAIT1;如果TI等于1,则清TI并转WAIT1AJMP WAITWAIT1:JBC RI,READ;如果RI等于1,则清RI并转READAJMP WAIT1READ:MOV A,SBUF;将取得的数送P1口MOV P1,ALJMP WAITDELAY:;延时子程序MOV R7,#0ffHDJNZ R7,$RETEND将程序编译通过,写入芯片,插入实验板,用通读电缆将实验板与主机的串行口相连就能实验了。
上面的程序功能很简单,就是每隔一段时间向主机轮流送数55H和AAH,并把主机送去的数送到P1口。
能在PC端用串行口精灵来做实验。
串行口精灵在我主页上有下载。
运行串行口精灵后,按主界面上的“设置参数”按钮进入“设置参数”对话框,按下面的参数进行设置。
注意,我的机器上用的是串行口2,如果你不是串行口2,请自行更改串行口的设置。
设置完后,按确定返回主界面,注意右边有一个下拉列表,应当选中“按16进制”。
然后按“开始发送”、“开始接收”就能了。
按此设置,实验板上应当有两只灯亮,6只灯灭。
大家能自行更改设置参数中的发送字符如55,00,FF等等,观察灯的亮灭,并分析原因,也能在主界面上更改下拉列表中的“按16进制”为“按10进制”或“按ASCII字符”来观察现象,并仔细分析。
这对于大家理解16进制、10进制、ASCII字符也是很有好处的。
程序本身很简单,又有注释,这里就不详加说明了。
三、上述程序的中断版本org0000HAJMP STARTorg0023hAJMP SERIAL;ORG30HSTART:mov SP,#5fh;mov TMOD,#20h;T1:工作模式2mov PCON,#80h;SMOD=1mov TH1,#0FDH;初始化波特率(参见表)mov SCON,#50h;Standard UART settingsMOV R0,#0AAH;准备送出的数SETB REN;允许接收SETB TR1;T1开始工作SETB EA;开总中断SETB ES;开串行口中断SJMP$SERIAL:MOV A,SBUFMOV P1,ACLR RIRETIEND本程序没有写入发送程序,大家能自行添加。
单片机89C51全双工串行通信汇编有甲、乙两台单片机,以工作方式2全双工串行通信,第9位作为奇偶校验位。
编出实现以下功能的程序:甲机:将0到F的十六进制数,总共16个数存放到片内RAM中的30H~3FH,然后再将30H~3FH 中的数据发送到乙机,乙机对接收的数据进行奇偶校验,若校验正确则乙机向甲机发出“数据发送正确”的信息(现取00H作为回答信号),甲机接收到乙机的此信息再发送下一个字节。
若奇偶校验错,则乙机发出“数据发送不正确”的信息(现取FFH作为回答信号)给甲机要求甲机再次发送原数据,直到数据发送正确。
乙机:将甲机发送的数据存入乙机片内RAM的50H~5FH单元中,进行奇偶校验,并发出相应的回答信息(即00H或FFH)给甲机。
接收完了16个数据后,通过P0依次从0到F开始显示,看看是否接收到的数据是否正确。
甲机程序:ORG 0000HLJMP MAINORG 0023H ;中断入口地址LJMP SECORG 0100H ;程序开始地址MAIN: MOV SCON,#80H ;串行口工作方式2,PCON未设置,波特率不加倍MOV IE,#90H ;打开总中断和串口中断;下面绿色字体程序是将数据写入RAM中的30H~3FH单元中,如果地址单元中已经有数据,可以将这段绿色程序删掉MOV R0,#00H ;给R0赋初值(0~F)MOV R1,#30H ;给地址指针R1赋数据存放的初始地址MOV R2,#10H ;存放16个数据LOOP: MOV A,R0 ;将R0中的值赋给AACALL TAB ; 调用子程序TABMOV @R1,A ;将A中的值送R1中地址INC R0 ;R0加1取下一个数INC R1 ;R1加1取下一个数据存放地址DJNZ R2,LOOP ;是否将16个数据存放完毕,否继续跳转到LOOP存放MOV R1,#30H ;给地址指针R1赋提取数据的初始地址MOV R2,#00H ;要提取数据个数的初值MOV A,@R1 ;将R1中的内容作为地址,把该地址的内容送AMOV C,P ;取奇偶位送CMOV TB8,C ;将C送TB8MOV SBUF,A ;发送数据LJMP $ ;等待中断SEC: JBC TI,D1 ;中断响应如果是TI=1,引起的清TI跳转到D1,否则向下执行CLR RI ;中断是由RI引起的,清RIMOV A,SBUF ;将接到的数据送ACJNE A,#00H,ERR ;将A中的数据与00H比较,不相等跳转到ERR,否则向下执行D1: INC R1 ;表示接收正确,程序继续发送数据。
51单片机串口通信软件程序集串口通信的单片机程序beep bit p3.7 ;蜂鸣器定义org 00hjmp mainorg 23h ;串行中断入口地址jmp com_int ;串行中断服务程序;*********** 主程序开始*******************org 30hmain: mov sp,#30h ;设置堆栈lcall rest ;初始化lcall comm ;串口初始化jmp $ ;原地等待; ************* 初始化*********************rest: mov p0,#00h ;禁止数码管显示mov p2,#255clr beep ;禁止蜂鸣器mov p1,#255 ;禁止LED显示RET ;返回; ************** 串口初始化*****************;设置串行口工作方式1,定时器1作为波特率发生器;波特率设置为2400 ;comm: mov tmod,#20h ;设置定时器T1工作方式2mov tl1,#0f3h ;定时器计数初值,波特率2400mov th1,#0f3h ;定时器重装值setb ea ;允许总的中断setb es ;允许串行中断mov pcon,#00h ;波特率不倍增mov scon,#50h ;设置串口工作方式1,REN = 1 允许接收setb tr1 ;定时器开始工作ret ;返回;*************** 串口中断服务程序***********; 如果接收0FF 表示上位机需要联机信号,单片机发送0FFH作为; 应答信号,如果接收到数字1~ n,表示相应的功能;; 这里,如果收到1 ,则单片机向计算机发送字符'H';; 如果收到2 ,则单片机向计算机发送字符'e';; 如果收到其他的数据,则发送'J';com_int: clr es ;禁止串行中断clr ri ;清除接收标志位mov a,sbuf ;从缓冲区取出数据mov p1,amov dptr,#tabcjne a,#0ffh,in_1 ;检查数据mov sbuf,#255 ;收到联机信号,发送联机信号jnb ti,$ ;等待发送完毕clr ti ;清除发送标志setb es ;允许串行中断reti ;中断返回in_1: cjne a,#1H, in_2 ;如果收到1movc a,@a+dptrmov sbuf,a ;发送'h'jnb ti,$ ;等待发送完毕clr ti ;清除发送中断标志setb es ;允许串行中断reti ;中断返回in_2: cjne a,#2,in_3 ;接收到 2movc a,@a+dptrmov sbuf,a ;发送'e'jnb ti,$ ;等待发送完毕clr ti ;清除发送中断setb es ;允许串行中断reti ;中断返回in_3: mov a,#03hmovc a,@a+dptrmov sbuf,a ;发送'j'jnb ti,$ ;等待发送完毕clr ti ;清除发送中断标志setb es ;允许串行中断reti ;返回tab: db '2','h','e','j'end51单片机串口调试程序一例/*定义为中断方式串口处理*/#define INTERSENDSTR/*不为8032系列芯片*///#define CHIP_8032#include <absacc.h>#include <reg51.h>#include <string.h>#include "err.h"#ifdef INTERSENDSTRunsigned char xdata sSendComBuf[256],sRecComBuf[256];unsigned char data bOut,bIn,bSout,bSin;#else#define DEFSENDCHAR TI=0;SBUF=ACC;while(!TI);TI=0;#endif//bps设置9600就是PSetBps(96)(11.0592Mhz)unsigned char PSetBps(unsigned int bps) SMALL{unsigned int t1;unsigned char t2;#ifdef INTERSENDSTR/*如果使用中断方式发送数据,必须等待发送数据完毕才能更换波特率*/ while(bSin!=bSout){;}ES=0;#endif#ifdef CHIP_8032if(3456%bps){return ERR_SET_BPS;}t1=3456/bps;t1--;t1=~t1;RCAP2H=t1/256;RCAP2L=t1;T2MOD=0x00;/*使用定时器2做波特率发生器*/T2CON=0x34;/*TF2=0;EXF2=0;RCLK=1;TCLK=1;EXEN2=0;TR2=1;C/T2=0;CP/RL2=0 */#elset1=576/bps;if((576%bps)||((t1==0))||(t1>=2*256)){return ERR_SET_BPS;}if(t1>256){PCON=00;t2=256-(288/bps);}else{PCON=0x80;t2=256-t1;}TH1=t2;TL1=t2;TR1=1;#endif/*模式3*/SM0=0;RI=0;TI=0;REN=1;SM1=1;SM2=1;#ifdef INTERSENDSTRbOut=bIn;bSout=bSin;ES=1;#endifreturn OK;}void PSendChar(unsigned char ch) SMALL {#ifdef INTERSENDSTRunsigned char tch;tch=bSin+1;while(tch==bSout){;}sSendComBuf[bSin]=ch;ES=0;if((bSout==bSin)){SBUF=sSendComBuf[bSin];bSin++;}else{bSin++;}ES=1;#elseACC=ch;DEFSENDCHAR;#endif}unsigned char PGetChar() SMALL{unsigned char ch;#ifdef INTERSENDSTRch=sRecComBuf[bOut];bOut++;return ch;#elsech=SBUF;RI=0;#endif}bit PCharInCom() SMALL{#ifdef INTERSENDSTRif(bIn!=bOut){return 1;}return 0;#elsereturn RI;#endif}void PSendString(unsigned char *st) SMALL{while(*st){PSendChar(*st);st++;}}void PSendArray(unsigned char *st,unsigned int len) SMALL {unsigned int ii;for(ii=0;ii<len;ii++){PSendChar(st[ii]);}}#ifdef INTERSENDSTR void PSerialInt() interrupt 4 {if(RI){sRecComBuf[bIn]=SBUF; bIn++;RI=0;}if(TI){TI=0;if(bSout!=bSin){bSout++;}if(bSout!=bSin){SBUF=sSendComBuf[bSout]; }}}#endif。
51单片机汇编模拟串口通信程序汇编编写的模拟串口通信程序T2 作为波特率控制UART_RXD 是硬中断0 或1 口,如果能进入中断,说明该线有一个起始位产生,进入中断后调用下面的接收程序。
退出硬中断之前还需要将硬中断标志重新复位。
UART_TXD是任何其它IO 即可。
UART_SEND: PUSH IE PUSH DPH PUSH DPL PUSH PSW PUSH 00H PUSH ACC CLR EA SETB UART_TXD ;START BIT MOV R0,A CLR TR2 ;TR2 置1,计数器2 启动,时间计数启动。
MOV A,RCAP2L;计数器2 重新装载值MOVTL2,A ;置计数器2 初值;T2 需要重新装载MOV A,DPH MOV A,RCAP2H MOV TH2,A MOV A,R0 SETB TR2 ;TR2 置1,计数器JNB TF2,$ CLR TF2 JNB TF2,$ CLR TF2 CLR UART_TXD ;START BIT JNB TF2,$ CLR TF2 JNBTF2,$ CLR TF2 MOV R0,#08HUART_SEND_LOOP: RRC A MOV UART_TXD,C ;8 BIT JNB TF2,$ CLR TF2 JNB TF2,$ CLR TF2 DJNZR0,UART_SEND_LOOP SETB UART_TXD ;END BIT JNB TF2,$ CLR TF2 JNB TF2,$ CLR TF2 POP ACC POP 00H POP PSW POP DPL POP DPH POP IE RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UART_REC: PUSH IE PUSH DPH PUSH DPL CLR EA CLR TR2 ;TR2 置1,计数器2 启动,时间计数启动。
51单片机串口通信试验汇编程序(今天是硬生生的把它给抠出来了):PC 通过串口助手向单片机系统传递命令和数据:以A5开始,以5A结束;中间是数据,长度不一,要求把数据部分用led灯显示出来;并且要求循环显示;//This is my x_Ed program code//we use it as the pc communicated with the mcu//At the same time,we want to see the result by LCD;STFLAG BIT 00H //收到起始码标志,1为收到起始码EDFLAG BIT 01H //到结束码标志,1为收到结束码TMFLAG BIT 02H //定时时间到标志,1为定时时间到ORG 0000HSJMP Initialize//主程序入口(初始化程序)ORG 000BH //定时器0入口LJMP TIMER0 //定时器0中断ORG 0023H //串口中断程序的入口地址LJMP Transfer //跳转到接受中断入口///////////////////////////////////////////////////////////////ORG 0050HInitialize:MOV SP,#70H //设置堆栈MOV TMOD,#21H //T1工作方式2 T0工作MOV TH1,#0FDH //波特率9600MOV TL1,#0FDH //波特率9600 自动重装载MOV TH0,#3CH //定时50msMOV TL0,#0BH //定时50msMOV SCON,#50H //串口工作方式1MOV R6,#00H //定时次数计数器20一秒MOV R5,#00H //接收数据长度计数器MOV R4,#00H //控制输出控制寄存器MOV R0,#30H //数据存储地址MOV R1,#30H //控制输出的数据缓存CLR STFLAG //清起始标志位CLR EDFLAG //清结束标志位CLR TMFLAG //清时钟标志位SETB PS //提高串口中断的优先级SETB TR1 //打开定时器1;SETB ES //打开串口中断允许位SETB ET0 //定时器0中断允许位SETB EA //打开全局中断允许位/////////////////等待接受命令//////////////////////// Main: JB STFLAG,NODE3 //已经收到起始位SJMP Main //未起始继续等待NODE3: JB EDFLAG,NODE4 //已经收到结束位SJMP Main //未结束继续等待NODE4: SETB TR0 //打开定时器0;NODE5: JB TMFLAG,OUTPUTSJMP NODE5///////////////////等待上位机传送数据并记录//////// Transfer: CLR ESMOV A,SBUFCJNE A,#0A5H,NODE0 //检测到起始位SETB STFLAGSJMP JIEDIANNODE0: CJNE A,#05AH,NODE1 //检测到结束位SETB EDFLAGMOV DPH,R5MOV R4,DPHclr ES //打开串口中断允许位SJMP ret00NODE1: MOV @R0,A //既非起始码,又非结束码,则为数据INC R0INC R5MOV SBUF,#055HJIEDIAN: CLR TICLR RISETB ESret00: RETITIMER0: CLR TR0MOV TH0,#3CHMOV TL0,#0B0HINC R6CJNE R6,#20,RTNSETB TMFLAGMOV R6,#00HRTN: SETB TR0RETIOUTPUT: CLR TR0clr TMFLAGMOV A,@R1MOV P1,AINC R1DJNZ R4,NODE4MOV R1,#30HCLR TMFLAGMOV DPH,R5MOV R4,DPHSJMP NODE4RETIEND。
∙51单片机的串口通信程序(C语言)∙发布时间:2009-6-2 阅读次数:2551 字体大小: 【小】【中】【大】作者:佚名来源:不详#include <reg52.h>#include<intrins.h>#include <stdio.h>#include <math.h>#define uchar unsigned char#define uint unsigned intsbit Key1 = P2^3;sbit Key2 = P2^2;sbit Key3 = P2^1;sbit Key4 = P2^0;sbit BELL = P3^6;sbit CONNECT = P3^7;unsigned int Key1_flag = 0;unsigned int Key2_flag = 0;unsigned int Key3_flag = 0;unsigned int Key4_flag = 0;unsigned char b;unsigned char code Num[21]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x40,0x79,0x24,0x30,0x19,0x12,0x 02,0x78,0x00,0x10,0x89};unsigned char code Disdigit[4] = {0x7F,0xBF,0xDF,0xEF};unsigned char Disbuf[4];void delayms(uint t){uint i;while(t--){/* 对于11.0592M时钟,约延时1ms */for (i=0;i<125;i++){}}}//-----------------------------------------------------void SendData(uchar Dat) {uchar i=0;SBUF = Dat;while (1){if(TI){TI=0;break;}}}void ScanKey(){if(Key1 == 0){delayms(100);if(Key1 == 0){Key1_flag = 1;Key2_flag = 0;Key3_flag = 0;Key4_flag = 0;Key1 = 1;}else;}if(Key2 == 0){delayms(100);if(Key2 == 0){Key2_flag = 1;Key1_flag = 0;Key3_flag = 0;Key4_flag = 0;Key2 = 1;}else;}if(Key3 == 0){delayms(50);{Key3_flag = 1;Key1_flag = 0;Key2_flag = 0;Key4_flag = 0;Key3 = 1;}else;}if(Key4 == 0){delayms(50);if(Key4 == 0){Key4_flag = 1;Key1_flag = 0;Key2_flag = 0;Key3_flag = 0;Key4 = 1;}else;}else;}void KeyProc(){if(Key1_flag){TR1 = 1;SendData(0x55);Key1_flag = 0;}else if(Key2_flag){TR1 = 1;SendData(0x11);Key2_flag = 0;}else if(Key3_flag){P1=0xff;BELL = 0; CONNECT = 1;}else if(Key4_flag){CONNECT = 0;BELL = 1;Key4_flag = 0;}else;}void Initdisplay(void){Disbuf[0] = 1;Disbuf[1] = 2;Disbuf[2] = 3;Disbuf[3] = 4;}void Display() //显示{unsigned int i = 0;unsigned int temp,count;temp = Disdigit[count];P2 =temp;temp = Disbuf[count];temp = Num[temp];P0 =temp;count++;if (count==4)count=0;}void time0() interrupt 1 using 2 {Display();TH0 = (65535 - 2000)/256;TL0 = (65535 - 2000)%256;}void main(){Initdisplay();TMOD = 0x21;TH0 = (65535 - 2000)/256;TL0 = (65535 - 2000)%256;TR0 = 1;ET0 = 1;TH1 = 0xFD; //11.0592MTL1 = 0xFD;PCON&=0x80;TR1 = 1;ET1 = 1;SCON = 0x40; //串口方式REN = 1;PT1 = 0;PT0 = 1;EA = 1;while(1){ScanKey();KeyProc();if(RI){Disbuf[0] = 0;Disbuf[1] = 20;Disbuf[2] = SBUF>>4;Disbuf[3] = SBUF&0x0f;RI = 0;}else;}}。
(1)主机程序 AT89C51-A ORG 00HJMP STARTSTART: MOV SP,#60H ;设置堆栈MOV TMOD,#00100000B ;TIMER1工作在MODE2ANL PCON,#01111111B ;SMOD=0MOV TH1,#0F3H ;波特率为2400MOV TL1,#0F3HSETB TR1 ;启动TIMER1MOV SCON,#11010000B ;UART工作在MODE3MOV IE,#10010000B ;UART中断使能SETB SM2 ;设SM2=1MOV P2,#0FFH ;给P2口赋初值MOV 32H,0FFH ;两个副CPU地址暂存器SCAN0: MOV R3,#F7H ;键盘扫描初始值SCAN: JB RI,UARTI ;是否有接收中断MOV R1,#00H ;TABLE取码指针SCAN1: MOV A,R3 ;输出行扫描MOV P1,AMOV A,P1MOV R4,ASETB CMOV R5,#03H ;扫描4列L1: RLC AJNC KEYIN ;C=0表示有键按下INC R1 ;C不等于0,未按则取码指针加1 DJNZ R5,L1 ;扫描下一列MOV A,R3 ;扫描下一行SETB CRRC AMOV R3,AJC SCAN1 ;4行扫描完JMP SCAN0KEYIN: MOV R7,#0D0H ;消除抖动D2: MOV R6,#19HDJNZ R6,$DJNZ R7,D2D3: MOV A,P1 ;按键放开否?XRL A,R4JZ D3MOV A,R1 ;至TABLE取键盘码MOV DPTR,#TABLEMOVC A,@A+DPTRMOV 30H,AXRL A,#83H ;“#1”是否按下?JZ UART1MOV A,30HXRL A,#C6H ;“#2”是否按下?JZ UART2MOV A,30HMOV SBUF,A ;载入SBUF发送出去WAIT: JBC TI,SCAN ;发送完毕否?JMP WAITUART1: SETB TB8 ;设TB8=1MOV SBUF,#01H ;发送AT89C51-B的地址01H WAIT1: JBC TI,L2 ;发送完毕否?JMP WAIT1L2: CLR TB8 ;清除TB8=0JMP SCAN0UART2: SETB TB8 ;设TB8=1MOV SBUF,#02H ;发送AT89C51-C的地址02H WAIT2: JBC TI,L3 ;发送完毕否?JMP WAIT2L3: CLR TB8 ;清除TB8=0JMP SCAN0UARTI: PUSH ACC ;压入堆栈PUSH PSWJBC RI,L5 ;是否为接收中断?RI=1?JMP RETURNL5: JB SM2,L6 ;SM2=1接收地址,SM2=0接收数据MOV A,SBUF ;接收数据载入累加器MOV 33H,A ;暂存入(33H)RAMMOV A,32H ;判断接收到89C51-B或89C51-C的数据?CJNE A,#01H,L8 ;接收到AT89C51-B的数据?MOV A,33H ;是则输出至P2显示(低4位)MOV P2,ASETB SM2 ;设SM2=1,准备接收下一个地址MOV 32H,#0FFH ;清除地址(32H)RAMJMP RETURNL8: CJNE A,#02H,RETURN ;接收到AT89C51-C的数据?MOV A,33H ;是则输出至P2显示(高4位)MOV P2,ASETB SM2 ;设SM2=1,准备接收下一个地址MOV 32H,#0FFHJMP RETURNL6: MOV A,SBUF ;载入接收到的地址CJNE A,#01H,L7 ;是AT89C51-B的地址?MOV 32H,A ;是则将此89C51-B的地址存入(32H)RAMCLR SM2 ;设SM2=0,准备接收数据JMP RETURNL7: CJNE A,#02H,RETURN ;是89C51-C的地址?MOV 32H,A ;是则将此89C51-C的地址存入(32H)RAMCLR SM2 ;设SM2=0,准备接收数据RETURN: POP PSW ;取回PSW POP ACCRETITABLE: DB F9H,A4H,B0HDB 99H,92H,82HDB F8H,80H,90H,DB 83H,C6H,FFHEND(2)从机程序 AT89C51-BORG 00HJMP STARTORG 23H ;UART中断起始地址JMP UARTISTART: MOV TMOD,#00100000B ;TIMER1工作在MODE2 ANL PCON,#01111111B ;SMOD=0MOV TH1,#0F3H ;波特率为2400MOV TL1,#0F3HSETB TR1 ;启动TIMER1MOV SCON,#11010000B ;UART工作在MODE3MOV IE,#10010000B ;UART中断使能SETB SM2 ;设SM2=1MOV 30H,#0FFH ;P1指拨开关的初值MOV P2,#0FFH ;给P2口赋初值LOOP: MOV A,P1 ;读入P1指拨开关CJNE A,30H,UART1 ;判断有否有变化?JMP LOOPUART1: ORL A,#0F0H ;有变化则取低4位MOV 30H,A ;存入P1指拨开关的新值SETB TB8 ;设TB8=1MOV SBUF,#01 ;发送本身地址(01H)给89C51-A WAIT1: JBC TI,L1 ;发送完毕否?JMP WAIT1L1: CLR TB8 ;是则清除TB8=0MOV SBUF,30H ;将指拨开关的值发送给89C51-A WAIT2: JBC TI,LOOP ;发送完毕否?JMP WAIT2UARTI: PUSH ACC ;压入堆栈PUSH PSWJBC RI,L5 ;是否为接收中断?JMP RETURNL5: JB SM2,L6 ;SM2=1接收地址,SM2=0接收数据MOV A,SBUF ;SM2=0,则接收数据并输出至P2MOV P2,ASETB SM2 ;设SM2=1,准备接收下一个地址JMP RETURNL6: MOV A,SBUF ;SM2=1,载入地址CJNE A,#01H,RETURN ;是否(01H)地址?CLR SM2 ;是则清除SM2=0,准备接收数据RETURN: POP PSW POP ACCRETI继续阅读。
51 单片机串口通信试验汇编程序
(今天是硬生生的把它给抠出来了):PC 通过串口助手向单片机系统传递命令和数据:以A5 开始,以5A 结束;中间是数据,长度不一,要求把数据部分用led 灯显示出来;并且要求循环显示;
//This is my x_Ed program code
//we use it as the pc communicated with the mcu
//At the same time,we want to see the result by LCD;
STFLAG BIT 00H // 收到起始码标志, 1 为收到起始码EDFLAG BIT 01H // 到结束码标志, 1 为收到结束码TMFLAG BIT 02H // 定时时间到标志, 1 为定时时间到ORG 0000H
SJMP Initialize// 主程序入口(初始化程序)
ORG 000BH // 定时器0 入口
LJMP TIMER0 // 定时器0 中断
ORG 0023H // 串口中断程序的入口地址
LJMP Transfer // 跳转到接受中断入口
///////////////////////////////////////////////////////////////
ORG 0050H
Initialize:
MOV SP,#70H // 设置堆栈
MOV TMOD,#21H //T1 工作方式 2 T0 工作MOV TH1,#0FDH // 波特率9600
MOV TL1,#0FDH //波特率9600 自动重装载MOV TH0,#3CH //定时50ms
MOV TL0,#0BH // 定时50ms
MOV SCON,#50H // 串口工作方式 1
MOV R6,#00H
// 定时次数计数器20 一秒
MOV R5,#00H //接收数据长度计数器
MOV R4,#00H //控制输出控制寄存器
MOV R0,#30H //数据存储地址
MOV R1,#30H //控制输出的数据缓存
CLR STFLAG //清起始标志位
CLR EDFLAG //清结束标志位
CLR TMFLAG //清时钟标志位
SETB PS //提高串口中断的优先级SETB TR1 // 打开定时器1;
SETB ES //打开串口中断允许位
SETB ET0 // 定时器0 中断允许位
SETB EA //打开全局中断允许位
///////////////// 等待接受命令//////////////////////// Main: JB STFLAG ,NODE3 //已经收到起始位
SJMP Main // 未起始继续等待
NODE3: JB EDFLAG,NODE4 // 已经收到结束位
SJMP Main // 未结束继续等待
NODE4: SETB TR0 // 打开定时器0;
NODE5: JB TMFLAG,OUTPUT
SJMP NODE5
/////////////////// 等待上位机传送数据并记录////////
Transfer: CLR ES
MOV A,SBUF
CJNE A,#0A5H,NODE0 // 检测到起始位
SETB STFLAG
SJMP JIEDIAN
NODE0: CJNE A,#05AH,NODE1 // 检测到结束位
SETB EDFLAG
MOV DPH,R5
MOV R4,DPH
clr ES //打开串口中断允许位
SJMP ret00
NODE1: MOV @R0,A // 既非起始码,又非结束码,则为数据INC R0
INC R5
MOV SBUF,#055H
JIEDIAN: CLR TI
CLR RI
SETB ES
ret00: RETI
TIMER0: CLR TR0
MOV TH0,#3CH
MOV TL0,#0B0H INC R6
CJNE R6,#20,RTN
SETB TMFLAG
MOV R6,#00H
RTN: SETB TR0
RETIOUTPUT: CLR TR0 clr TMFLAG MOV A,@R1 MOV P1,A INC R1 DJNZ R4,NODE4 MOV R1,#30H CLR TMFLAG
MOV DPH,R5
MOV R4,DPH
SJMP NODE4
RETI
END。