51单片机串口通信(相关例程)

合集下载

51单片机串口通信实例

51单片机串口通信实例

51单片机串口通信实例一、原理简介51 单片机内部有一个全双工串行接口。

什么叫全双工串口呢?一般来说,只能接受或只能发送的称为单工串行;既可接收又可发送,但不能同时进行的称为半双工;能同时接收和发送的串行口称为全双工串行口。

串行通信是指数据一位一位地按顺序传送的通信方式,其突出优点是只需一根传输线,可大大降低硬件成本,适合远距离通信。

其缺点是传输速度较低。

与之前一样,首先我们来了解单片机串口相关的寄存器。

SBUF 寄存器:它是两个在物理上独立的接收、发送缓冲器,可同时发送、接收数据,可通过指令对SBUF 的读写来区别是对接收缓冲器的操作还是对发送缓冲器的操作。

从而控制外部两条独立的收发信号线RXD(P3.0)、TXD(P3.1),同时发送、接收数据,实现全双工。

串行口控制寄存器SCON(见表1) 。

表1 SCON寄存器表中各位(从左至右为从高位到低位)含义如下。

SM0 和SM1 :串行口工作方式控制位,其定义如表2 所示。

经验分享:学习单片机重要的是实践,所以开发板是很重要,给大家推荐些淘宝上信誉良好并且软硬件及小零件等、售前售后服务良好的皇冠级金钻店铺给大家,在硬件购买上少走弯路。

按住Ctrl键单击即可:慧净电子单片机(一皇冠)【天津商盟】天津锐志(电子)单片机经营部(两皇冠)金沙滩工作室(5钻)深圳育松电子元件,模块,传感器,批发部:淘宝最全最平价(5皇冠)志宏电子(4钻)表2 串行口工作方式控制位其中,fOSC 为单片机的时钟频率;波特率指串行口每秒钟发送(或接收)的位数。

SM2 :多机通信控制位。

该仅用于方式2 和方式3 的多机通信。

其中发送机SM2 = 1(需要程序控制设置)。

接收机的串行口工作于方式2 或3,SM2=1 时,只有当接收到第9 位数据(RB8)为1 时,才把接收到的前8 位数据送入SBUF,且置位RI 发出中断申请引发串行接收中断,否则会将接受到的数据放弃。

当SM2=0 时,就不管第位数据是0 还是1,都将数据送入SBUF,并置位RI 发出中断申请。

51单片机和计算机之间实现串口通信的电路图

51单片机和计算机之间实现串口通信的电路图

51单片机和计算机之间实现串口通信的电路图串口通讯参考程序如下:来源:深入浅出AVR单片机#include<reg51.h>unsigned char UART_RX; //定义串口接收数据变量unsigned char RX_flag; //定义穿行接收标记/**************************************************************************************** *****函数名:UART串口初始化函数调用:UART_init();参数:无返回值:无结果:启动UART串口接收中断,允许串口接收,启动T/C1产生波特率(占用)备注:振荡晶体为12MHz,PC串口端设置[ 4800,8,无,1,无]/**************************************************************************************** ******/void UART_init (void){EA = 1; //允许总中断(如不使用中断,可用//屏蔽)ES = 1; //允许UART串口的中断TMOD = 0x20; //定时器T/C1工作方式2SCON = 0x50; //串口工作方式1,允许串口接收(SCON = 0x40 时禁止串口接收)TH1 = 0xF3; //定时器初值高8位设置TL1 = 0xF3; //定时器初值低8位设置PCON = 0x80; //波特率倍频(屏蔽本句波特率为2400)TR1 = 1; //定时器启动}/**************************************************************************************** ******//**************************************************************************************** *****函数名:UART串口接收中断处理函数调用:[SBUF收到数据后中断处理]参数:无返回值:无结果:UART串口接收到数据时产生中断,用户对数据进行处理(并发送回去)备注:过长的处理程序会影响后面数据的接收/**************************************************************************************** ******/void UART_R (void) interrupt 4 using 1{ //切换寄存器组到1RI = 0; //令接收中断标志位为0(软件清零)UART_RX = SBUF; //将接收到的数据送入变量UART_dataRX_flag=1; //标记接收//用户函数内容(用户可使用UART_data做数据处理)//SBUF = UART_data; //将接收的数据发送回去(删除//即生效)//while(TI == 0); //检查发送中断标志位//TI = 0; //令发送中断标志位为0(软件清零)}/**************************************************************************************** ******//**************************************************************************************** *****函数名:UART串口发送函数调用:UART_T (?);参数:需要UART串口发送的数据(8位/1字节)返回值:无结果:将参数中的数据发送给UART串口,确认发送完成后退出,采用非中断方式备注:/**************************************************************************************** ******/void UART_T (unsigned char UART_data){ //定义串口发送数据变量ES=0; //禁止穿行中断SBUF = UART_data; //将接收的数据发送回去while(TI == 0); //检查发送中断标志位TI = 0; //令发送中断标志位为0(软件清零)ES=1; //打开穿行中断}/**************************************************************************************** *****函数名:UART串口发送字符串函数调用:UART_S (?);参数:需要UART串口发送的数据(8位/1字节)返回值:无结果:将参数中的数据发送给UART串口,确认发送完成后退出,采用非中断方式备注:/**************************************************************************************** ******/void UART_S(unsigned char *str){while(1){if(*str=='\0') break;UART_T(*str++);}}/**************************************************************************************** *****函数名:主函数调用:main();参数:返回值:无结果:备注:/**************************************************************************************** ******/void main(){unsigned char Buf_data[]={" welcome to MCU world. \n\r"}; UART_init();UART_S(Buf_data);while(1){if(RX_flag==1){UART_T(UART_RX);RX_flag=0;}}}。

51单片机串口通信程序。。含详细例子

51单片机串口通信程序。。含详细例子

{ P3_4=0; P3_3=1;
} void RstPro()//编程器复位 {
pw.fpProOver();//直接编程结束 SendData();//通知上位机,表示编程器就绪,可以直接用此函数因为协议号(ComBuf[0])还没被修改,下同 }
void ReadSign()//读特征字 {
} void serial () interrupt 4 using 3 //串口接收中断函数 {
if (RI) { RI = 0 ; ch=SBUF; read_flag= 1 ; //就置位取数标志 }
} main()
{ init_serialcom(); //初始化串口 while ( 1 ) { if (read_flag) //如果取数标志已置位,就将读到的数从串口发出 { read_flag= 0 ; //取数标志清 0 send_char_com(ch); } }
while(RI == 0); RI = 0; c = SBUF; // 从缓冲区中把接收的字符放入 c 中 SBUF = c; // 要发送的字符放入缓冲区 while(TI == 0); TI = 0; } }
4.//////////////// /////////////////////////////////////////////////////////
SendData(); } else break;//等待回应失败 } pw.fpProOver();//操作结束设置为运行状态 ComBuf[0]=0;//通知上位机编程器进入就绪状态 SendData(); }
void Lock()//写锁定位
{
pw.fpLock();
SendData();

51单片机与串口通信代码

51单片机与串口通信代码

51单片机与串口通信代码串口调试1. 发送:向总线上发命令2. 接收:从总线接收命令,并分析是地址还是数据。

3. 定时发送:从内存中取数并向主机发送.经过调试,以上功能基本实现,目前可以通过上位机对单片机进行实时控制。

程序如下://这是一个单片机C51串口接收(中断)和发送例程,可以用来测试51单片机的中断接收//和查询发送,另外我觉得发送没有必要用中断,因为程序的开销是一样的#i nclude <reg51.h>#i nclude<stdio.h>#i nclude <string.h>#define INBUF_LEN 4 //数据长度unsigned char inbuf1[INBUF_LEN];unsigned char checksum,count3 , flag,temp,ch;bit read_flag=0;sbit cp=P1^1;sbit DIR=P1^2;int i;unsigned int xdata *RAMDATA; /*定义RAM地址指针*/unsigned char a[6] ={0x11,0x22,0x33,0x44,0x55,0x66} ;void init_serialcomm(void){SCON=0x50; //在11.0592MHz下,设置串行口波特率为9600,方式1,并允许接收PCON=0x00;ES=1;TMOD=0x21; //定时器工作于方式2,自动装载方式 TH0=(65536-1000)%256;TL0=(65536-1000)/256;TL1=0xfd;TH1=0xfd;ET0=1;TR0=1;TR1=1;// TI=0;EA=1;// TI=1;RAMDATA=0x1F45;}void serial () interrupt 4 using 3{if(RI){ RI=0;ch=SBUF;TI=1; //置SBUF空switch(ch){case 0x01 :printf("A"); TI=0;break;case 0x02 :printf("B"); TI=0;break;case 0x03 :printf("C"); TI=0;break;case 0x04 :printf("D"); TI=0;break; default :printf("fg"); TI=0;break; }}}//向串口发送一个字符void timer0() interrupt 1 using 3{// char i;flag++;TH0=0x00;TL0=0x00;if(flag==10){// cp=!cp;// for(i=0;i<6;i++)P2=0x25;TI=1;temp=*RAMDATA;printf("%c",temp); TI=0;// RAMDATA--;flag=0;}}//主程序main(){init_serialcomm(); //初始化串口//向6264中送数据{*RAMDATA=0x33;}while(1){*RAMDATA=0x33;;}}调试过程中遇到的问题:1. 发送过程:在发送时必须保证TI=1:即发送缓冲器为空,否则将导致数据发不出去,如果想强制发送可以用:TI=1.具体发送数据:利用printf(“akjdfaklfj”);函数直接发送即可。

51单片机教程:单片机串行口通信程序设计

51单片机教程:单片机串行口通信程序设计

51单片机教程:单片机串行口通信程序设计1.串行口方式0应用编程 8051单片机串行口方式0为移位寄存器方式,外接一个串入并出的移位寄存器,就能扩展一个并行口。

单片机串行口通信程序设计硬件连接图例:用8051单片机串行口外接CD4094扩展8位并行输出口,如图所示,8位并行口的各位都接一个发光二极管,要求发光管呈流水灯状态。

串行口方式0的数据传送可采用中断方式,也可采用查询方式,无论哪种方式,都要借助于TI或RI标志。

串行发送时,能靠TI置位(发完一帧数据后)引起中断申请,在中断服务程序中发送下一帧数据,或者通过查询TI的状态,只要TI为0就继续查询,TI为1就结束查询,发送下一帧数据。

在串行接收时,则由RI引起中断或对RI查询来确定何时接收下一帧数据。

无论采用什么方式,在开始通信之前,都要先对控制寄存器SCON进行初始化。

在方式0中将,将00H送SCON就能了。

单片机串行口通信程序设计列子ORG 2000HSTART: MOV SCON,#00H ;置串行口工作方式0MOV A,#80H ;最高位灯先亮CLR P1.0 ;关闭并行输出(避象传输过程中,各LED的暗红现象) OUT0: MOV SBUF,A ;开始串行输出OUT1: JNB TI,OUT1 ;输出完否CLR TI ;完了,清TI标志,以备下次发送SETB P1.0 ;打开并行口输出ACALL DELAY ;延时一段时间RR A ;循环右移CLR P1.0 ;关闭并行输出JMP OUT0 ;循环说明:DELAY延时子程序能用前面我们讲P1口流水灯时用的延时子程序,这里就不给出了。

二、串行口异步通信org 0000HAJMP STARTORG 30HSTART: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开始工作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将程序编译通过,写入芯片,插入实验板,用通读电缆将实验板与主机的串行口相连就能实验了。

51系列串口通讯例程(参考仅供)

51系列串口通讯例程(参考仅供)

51系列串口通讯例程.rar > serial.c,1.// 题目:串口初始化C代码2.// 要求:3.// 1.波特率1200bps,无奇偶校验,停止位1,数据位84.// 2.定时器T1做波特率发生器5.// 软件模拟测试说明:6.// 1.这个测试采用查询方式进行串口通讯7.// 2.将软件仿真环境的晶震设为11.0592 MHz8.// 3.软件模拟全速运行, 观察波特率是1200bps9.// 4.在串口1中输入数字或字母,可观察到通讯是否有误。

10.//#pragma src11.#include <REG51.H>12.//串口初始化13.void serial_init(void)14.{15.//ET1 = 0; //CLR 0ABH ;禁止T1中断16. TMOD = 0x20; //MOV 89H,#20H ;timer 1 mode 2: 8-Bit reload(定时器T1 模式2: 8位自动初值重装)17. TH1 = 0xE8; //MOV 8DH,#0E8H18. TL1 = 0xE8; //MOV 8BH,#0E8H ;1200bps, 11.05919. TR1 = 1; //SETB 8EH ;启动定时器120. SCON = 0x50; // mode 1: 10-bit UART, enable receiver//(模式1: 10位异步发送/接收, 使能接收允许位)21.//SM1 = 1; // ;串行口模式122.//SM0 = 0;23.//REN = 1; // ;允许串行中断接收24. SM2 = 1; //SETB O9DH ;收到有效的停止位时才将RI置125. ES = 1; //SETB 0ACH ;允许串行中断26. EA = 1; //SETB 0AFH ;总中断开27.}28.//中断方式处理串口数据29.void serial(void) interrupt 4 using 130.{31.if(RI)32. {33.// RI = 0;34.// 串口接收, 采用临时缓冲35. }36.#if 037.if(TI)38. {39.// TI = 0;40.// 串口发送, 没有必要使用中断方式41. }42.#endif43.}44.// 查询方式接收串口数据45.unsigned char getchar(void)46.{47.while(!RI);// 没有收到串口数据则一直等待48. RI=0;49.return SBUF;50.}51.// 查询方式发送串口数据52.void putchar(unsigned char ch)53.{54. SBUF=ch;55.while(!TI);56. TI=0;57.}58.code unsigned char HEX_TAB []="0123456789ABCDEF";59.void puthex(unsigned char ch)60.{61. unsigned char i,j;62. i=ch>>4;63. j=ch&0x0f;64. putchar(HEX_TAB[i]);65. putchar(HEX_TAB[j]);66.}51系列串口通讯例程.rar > test.c1.// 采用查询方式进行串口通讯的例子2.// 采用这种方式的弊端:3.// 1.如果对方没有发送数据,则本机无限等待,而不能做其它事情4.// 2.如果对方发送数据而本机正做其它事情,那么有可能丢失数据。

深入理解51单片机串口通信及通信实例

深入理解51单片机串口通信及通信实例

深入理解51单片机串口通信及通信实例串口通信的原理串口通信(SerialCommunicaTIons)的概念非常简单,串口按位(bit)发送和接收字节。

尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。

它很简单并且能够实现远距离通信。

比如IEEE488定义并行通行状态时,规定设备线总长不得超过20米,并且任意两个设备间的长度不得超过2米;而对于串口而言,长度可达1200米。

典型地,串口用于ASCII码字符的传输。

通信使用3根线完成,分别是地线、发送、接收。

由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据。

其他线用于握手,但不是必须的。

串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。

对于两个进行通信的端口,这些参数必须匹配。

a,波特率:这是一个衡量符号传输速率的参数。

指的是信号被调制以后在单位时间内的变化,即单位时间内载波参数变化的次数,如每秒钟传送240个字符,而每个字符格式包含10位(1个起始位,1个停止位,8个数据位),这时的波特率为240Bd,比特率为10位*240个/秒=2400bps。

一般调制速率大于波特率,比如曼彻斯特编码)。

通常电话线的波特率为14400,28800和36600。

波特率可以远远大于这些值,但是波特率和距离成反比。

高波特率常常用于放置的很近的仪器间的通信,典型的例子就是GPIB设备的通信。

b,数据位:这是衡量通信中实际数据位的参数。

当计算机发送一个信息包,实际的数据往往不会是8位的,标准的值是6、7和8位。

如何设置取决于你想传送的信息。

比如,标准的ASCII码是0~127(7位)。

扩展的ASCII码是0~255(8位)。

如果数据使用简单的文本(标准ASCII码),那么每个数据包使用7位数据。

每个包是指一个字节,包括开始/停止位,数据位和奇偶校验位。

由于实际数据位取决于通信协议的选取,术语包指任何通信的情况。

51单片机串口通信程序

51单片机串口通信程序

51单片机串口通信程序51单片机是我国自主研发的一款微控制器,在国内广泛应用于各种电子设备中。

在很多应用场景中,需要通过串口进行通信,以实现数据传输。

本文将介绍51单片机串口通信程序的编写方法。

一、串口介绍串口是一种通信接口,用于在电子设备之间传输数据。

其主要特点是一条通信线路同时只能传输一位数据,因此称为串口。

串口和并口属于不同的通信接口标准。

串口的优点是具有通信距离远、传输速率快、可靠性高等优点,因此广泛应用于各种场合中。

串口有两种工作模式:同步模式和异步模式。

在实际应用中,异步串口通信更为常见。

二、异步串口通信原理在异步串口通信中,数据的传输是通过发送端和接收端的时钟信号不同步实现的。

在发送数据时,发送端会发出一个起始位,接下来是数据位,最后是一个或多个停止位。

在接收端,当检测到起始位时,开始接收数据。

根据通信协议,在接收完数据位后,接收端会判断是否正确,然后再结束本次通信。

1. 硬件连接在51单片机和电脑之间进行串口通信,需要用到串口转USB线。

将串口转USB线的TxD接口与51单片机的P3.1接口相连,RxD接口与P3.0接口相连。

此外,需要一个5V的电源供给51单片机。

2. 准备工作在编写程序之前,需要进行一些准备工作:(1)将P3口设为外部中断P3口的最低2位是外部中断的2个输入端,需要将它们设为中断输入。

EA=1;EX0=1;(2)设置波特率串口通信需要设置波特率。

常见的波特率有9600、19200、38400等。

对应的波特率常数为0xFD、0xFA、0xF4等。

TH1=0xFD;//波特率9600(3)使能串口中断在发送和接收数据时,会不断产生中断,需要将中断使能。

ES=1;//允许串口中断3. 编写程序(1)发送数据void SendData(unsigned char SendBuff[],unsigned int ULength){unsigned int i;for(i=0;i<ULength;i++){SBUF=SendBuff[i];//发送数据while(TI==0); //等待,直到发送完成TI=0;}}(2)接收数据(3)主函数TMOD|=0x20;//定时器1工作方式2TH1=0xFD;//波特率9600TR1=1;//打开定时器1SCON=0x50;//串口方式1,8位数据,无校验,1停止位EA=1;//开总中断ES=1;//开串口中断while(1){SendData(pSendData,4);//发送数据 RecvData(pRecvData,4);//接收数据if(pRecvData[0]=='K'){P0=0x01;//点亮LED}else{P0=0x00;//关闭LED}}}四、总结。

51单片机串口485通讯程序

51单片机串口485通讯程序

/* 以下为单片机串口485通讯程序,从机程序(当然也适用于主机程序),主机发送可以先用串口帮手软件来调试,经过Keil uVision4实际测试,测试效果如结尾图片所示, 大部分来自网络,只是改了两个地方: len = sizeof(dbuf),if(i >=( __ERRLEN+1)) // 帧超长,错误,返回,就可以实现了,其中的原因自已体会吧*/#ifndef __485_C__#define __485_C__#include <reg51.h>#include <string.h>#include <stdio.h>#include <intrins.h>#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 dbuf[__MAXSIZE];//={0,1,2,3,4,5,6,7}; // 该缓冲区用于保存设备状态信息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);dev = 0x01;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 __GETDA TA_:// len = strlen(dbuf);//在C51中不能这个函数计算unsigned char型,这个函数只能计算char型len = sizeof(dbuf);// len =0x08;send_data(__STA TUS_, 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]; // 保存接收到的帧__ERRLEN=12;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表示0xdbecc = ecc^0xdb;db = 0;break;case 0xdc:data_buf[i] = 0xc0; // 0xdbdc表示0xc0ecc = ecc^0xc0;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) // 帧超长,错误,返回if(i >=( __ERRLEN+1)) // 帧超长,错误,返回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,发送0xdbdcTI = 0;SBUF = 0xdb;while(!TI);TI = 0;SBUF = 0xdc;while(!TI)TI = 0;break;default: // 普通数据则直接发送TI = 0;SBUF = da;while(!TI);TI = 0;}}#endif/* 调试结果*/。

51串口通信程序带详细注释

51串口通信程序带详细注释

51串口通信程序(带详细注释)#include;#include; //后面有一个比较函数#define uchar unsigned char#define uint unsigned intbit UART_Flag=0; //定义串口接收标志位uchar str[50];//定义一数组uchar length=0; //数组长度从0开始void init() //初始化uart{TMOD=0X20; //定时器1定时器方式工作模式2,可自动重载的8位计数器常把定时/计数器1以模式2作为串行口波特率发生器SCON=0X50; //选择工作模式1使能接收,允许发送,允许接收EA=1; //开总中断ES=1; //打开串口中断ET1=0; //打开定时器中断PCON=0X80; //8位自动重载,波特率加倍TH1=0XFF; //用22.1184 mhz波特率TL1=0XFF;TR1=1; //打开中时器}void UART_Putch(uchar dat) //输出一个字符{SBUF=dat; //把数据送给sbuf缓存器中while(TI!=1);//发送标志位 TI如果发送了为1,没发送为0,没发送等待,到了退出循环TI=0; //到了,TI清为0}void init1() interrupt 4 //uart中断,4为串口中断{if(RI==1) //收到数据{uchar m=SBUF; //m为计算机发送给串口的数据,例,open //总体思想是,计算机通知串口,我要发数据了RI=0;//收到清0if(m=='\r')//判断m这位数据有无\r{UART_Putch('\r'); //回车UART_Putch('\n'); // 换行str[length]='\0'; //数据最后位加0标志位表示发完了数据UART_Flag=1; // 传完标志位}else if(m=='\n'){}else if(m=='\b')//b表退格 //下面几句表删锄{UART_Putch('\b');UART_Putch(' ');UART_Putch('\b');length=length-1; //删锄了后总长度减一}else{str[length++]=m; //比如m为open,先传0后传p,length加一UART_Putch(m);//输出比如open}}}void check(char *str) //计算机发一数据,我来检查,{if( strcmp(&quot;open&quot;,str)==0 ) //比较两数是否相同,相同为0,不同为1 //要加string.h头文件{UART_Putch('o'); //计算机中写入open我回复ok UART_Putch('k');UART_Putch('\r'); //回车是跑到这一行的最前UART_Putch('\n'); //换行是跳到下一行}else if( strcmp(&quot;close&quot;,str)==0 ) {UART_Putch('o');UART_Putch('k');UART_Putch('\r');UART_Putch('\n'); }else//否则出错{UART_Putch('e'); UART_Putch('r');UART_Putch('r');UART_Putch('o');UART_Putch('r');UART_Putch('!'); UART_Putch('\r'); UART_Putch('\n'); }}void main(){init();while(1){if(UART_Flag==1) //接收标志位表示接收完成 {check(str);//检查length=0; //长度清0UART_Flag=0;//标志位清0}}}。

51单片机串口通信连续发送接收字节

51单片机串口通信连续发送接收字节

51单片机串口通信连续发送接收字节当使用单片机串口通信,连续发送字节时,如何处理呢?使用串口中断接收发送字节,中断内的程序尽可能简单,因为考虑到占用时间。

本文以连续发送4个字节为例,给出例程如下所示:本例程使用的单片机型号为:IAP15W4K58S//工作频率为11.0592MHz#include "reg51.h"#include "intrins.h"typedef unsigned char BYTE;typedef unsigned int WORD;#define FOSC 11059200L //系统频率//#define BAUD 115200 //#define BAUD 9600 //定义串口波特率#define Num_byte 4 //接收数据4个字节BYTE Data_temp[Num_byte]={0,0,0,0};sfr P0M1 = 0x93;sfr P0M0 = 0x94;sfr P1M1 = 0x91;sfr P1M0 = 0x92;sfr P2M1 = 0x95;sfr P2M0 = 0x96;sfr P3M1 = 0xb1;sfr P3M0 = 0xb2;sfr P4M1 = 0xb3;sfr P4M0 = 0xb4;sfr P5M1 = 0xC9;sfr P5M0 = 0xCA;sfr P6M1 = 0xCB;sfr P6M0 = 0xCC;sfr P7M0 = 0xE2;sfr AUXR = 0x8e; //辅助寄存器sfr T2H = 0xd6; //定时器2高8位sfr T2L = 0xd7; //定时器2低8位sfr P_SW1 = 0xA2; //外设功能切换寄存器1sbit LED1=P1^1;sbit LED2=P1^2;bit busy=0; //定义是否接收完4个字节BYTE num=0; //记录4个字节的数据void SendData(BYTE dat);void SendString(char *s);BYTE read_Byte();void delay();void main(){P0M0 = 0x00;P0M1 = 0x00;P1M0 = 0x00;P1M1 = 0x00;P2M0 = 0x00;P2M1 = 0x00;P3M0 = 0x00;P3M1 = 0x00;P4M0 = 0x00;P4M1 = 0x00;P5M0 = 0x00;P5M1 = 0x00;P6M0 = 0x00;P7M0 = 0x00;P7M1 = 0x00;P_SW1 &= 0x3F; //(P3.0/RxD, P3.1/TxD)SCON = 0x50; //8位可变波特率,允许接收T2L = (65536 - (FOSC/4/BAUD)); //设置波特率重装值T2H = (65536 - (FOSC/4/BAUD))>>8;AUXR = 0x15; //T2为1T模式, 并启动定时器2,选择定时器2为串口1的波特率发生器ES = 1; //使能串口1中断EA = 1;//SendString("STC15F2K60S2\r\nUart Test !\r\n");while(1){if(busy){ES=0;for(num=0;num<Num_byte;num++){SBUF= Data_temp[num]+0x05;while(!TI);TI=0;}num=0;ES=1;busy=0;}//SendData(3);//delay();//delay();;}/*----------------------------UART 中断服务程序-----------------------------*/void Uart() interrupt 4 using 1{ES=0;RI = 0; //清除RI位Data_temp[num++]= SBUF;if(num==Num_byte)busy=1;ES=1;}/*----------------------------发送串口数据----------------------------*/void SendData(BYTE dat){while (busy); //等待前面的数据发送完成SBUF = dat; //写数据到SBUF寄存器busy = 1;}/*----------------------------发送字符串----------------------------*/void SendString(char *s){while (*s) //检测字符串结束标志{SendData(*s); //发送当前字符s++;}//接收1个字节BYTE read_Byte(){ BYTE character;character = SBUF;return character;}void delay(){ BYTE i,j;for(i=220;i--;i>0)for(j=220;j--;j>0); }。

51单片机串口通信(相关例程)

51单片机串口通信(相关例程)

51单片机串口通信1./*打开串口调试程序,将波特率设置为9600,无奇偶校验晶振11.0592MHz,发送和接收使用的格式相同,如都使用字符型格式,在发送框输入hello,I Love MCU ,在接收框中同样可以看到相同字符,说明设置和通信正确*/#include <REG52.H>/*主程序*/void main (void){SCON = 0x50; /* SCON: 模式1, 8-bit UART, 使能接收*/TMOD |= 0x20; /* TMOD: timer 1, mode 2,8-bit reload*/TH1 = 0xFD; /* TH1: **********************************/ TR1 = 1; /* TR1: timer 1 run */EA = 1; /*打开总中断*/ES = 1; /*打开串口中断*/while (1) /*主循环不做任何动作*/{}}void UART_SER (void) interrupt 4 //串行中断服务程序{unsigned char Temp; //定义临时变量if(RI) //判断是接收中断产生{RI=0; //标志位清零Temp=SBUF; //读入缓冲区的值P1=Temp; //把值输出到P1口,用于观察SBUF=Temp; //把接收到的值再发回电脑端}if(TI) //如果是发送标志位,清零TI=0;}2.51单片机与电脑串口通信的C程序,最好是中断方式的#include <reg51.h>#include <string.h>unsigned char ch;bit read_flag= 0 ;void init_serialcom( void ) //串口通信初始设定{SCON = 0x50 ; //UART为模式1,8位数据,允许接收TMOD |= 0x20 ; //定时器1为模式2,8位自动重装PCON |= 0x80 ; //SMOD=1;TH1 = 0xFD ; //Baud:19200 fosc="11".0592MHzIE |= 0x90 ; //Enable Serial InterruptTR1 = 1 ; // timer 1 run}//向串口发送一个字符void send_char_com( unsigned char ch){SBUF=ch;while (TI== 0);TI= 0 ;}void serial () interrupt 4 using 3 //串口接收中断函数{if (RI){RI = 0 ;ch=SBUF;read_flag= 1 ; //就置位取数标志}}main(){init_serialcom(); //初始化串口while ( 1 ){if (read_flag) //如果取数标志已置位,就将读到的数从串口发出{read_flag= 0 ; //取数标志清0send_char_com(ch);}}}3.// 单片机串行口发送/接收程序,每接收到字节即发送出去// 和微机相接后键入的字符回显示在屏幕上// 可用此程序测试#include <reg51.h>#define XTAL 11059200 // CUP 晶振频率#define baudrate 9600 // 通信波特率void main(void){unsigned char c;TMOD = 0x20; // 定时器1工作于8位自动重载模式, 用于产生波特率TH1=(unsigned char)(256 - (XTAL / (32L * 12L * baudrate)));TL1=(unsigned char)(256 - (XTAL / (32L * 12L * baudrate))); // 定时器0赋初值SCON = 0x50;PCON = 0x00;TR1 = 1;IE = 0x00; // 禁止任何中断{while(RI == 0);RI = 0;c = SBUF; // 从缓冲区中把接收的字符放入c中SBUF = c; // 要发送的字符放入缓冲区while(TI == 0);TI = 0;}}4.//////////////// ///////////////////////////////////////////////////////////E51Pro.c//Easy 51Pro编程器主程序,负责通讯,管理编程操作/////////////////////////////////////////////////////////////////////////#include <E51Pro.h>BYTE ComBuf[18];//串口通讯数据缓存,发送和接收都使用UINT nAddress;//ROM中地址计数UINT nTimeOut;//超时计数ProWork pw;//编程器一般操作void Delay_us(BYTE nUs)//微秒级延时<255us{TH0=0;TL0=0;TR0=1;while(TL0<nUs)//利用T0做定时计数器,循环采样,直到达到定时值{}TR0=0;}void Delay_ms(UINT nMs)//豪秒级的延时<65535ms{UINT n=0;TR0=1;while(n<nMs)////利用T0做定时计数器,循环采样,直到达到定时值{TH0=0;TL0=20;while(TH0<4){}n++;}TR0=0;}BOOL WaitComm()//等待上位机的命令,18字节{RI=0;while(!RI){}//等待第一个字节ComBuf[n]=SBUF;RI=0;n++;for(n;n<=17;n++){nTimeOut=0;while(!RI){nTimeOut++;if(nTimeOut>10000)//后17个字节都有超时限制return 0;}ComBuf[n]=SBUF;RI=0;}return 1;}BOOL WaitResp()//等待上位机回应,1字节,有超时限制{nTimeOut=0;RI=0;while(!RI){nTimeOut++;if(nTimeOut>50000){return 0;}}RI=0;ComBuf[0]=SBUF;return 1;}BOOL WaitData()//写器件时等待上位机数据,18字节,有超时限制{BYTE n;RI=0;for(n=0;n<=17;n++){nTimeOut=0;while(!RI){nTimeOut++;if(nTimeOut>10000){return 0;}}RI=0;ComBuf[n]=SBUF;}return 1;}void SendData()//发送数据或回应操作完成,18字节{BYTE n=0;for(n;n<=17;n++){TI=0;SBUF=ComBuf[n];while(!TI){}TI=0;}}void SendResp()//回应上位机1个字节,在写器件函数中使用{TI=0;SBUF=ComBuf[0];while(!TI){}TI=0;}void SetVpp5V()//设置Vpp为5v{P3_4=0;P3_3=0;}void SetVpp0V()//设置Vpp为0v{P3_3=0;P3_4=1;}void SetVpp12V()//设置Vpp为12v{P3_4=0;P3_3=1;}void RstPro()//编程器复位{pw.fpProOver();//直接编程结束SendData();//通知上位机,表示编程器就绪,可以直接用此函数因为协议号(ComBuf[0])还没被修改,下同}void ReadSign()//读特征字{pw.fpReadSign();SendData();//通知上位机,送出读出器件特征字}void Erase()//擦除器件{pw.fpErase();SendData();//通知上位机,擦除了器件}void Write()//写器件{BYTE n;pw.fpInitPro();//编程前的准备工作SendData();//回应上位机表示进入写器件状态,可以发来数据while(1){if(WaitData())//如果等待数据成功{if(ComBuf[0]==0x07)//判断是否继续写{for(n=2;n<=17;n++)//ComBuf[2~17]为待写入数据块{if(!pw.fpWrite(ComBuf[n]))//<<< <<<<<<调用写该器件一个单元的函数{pw.fpProOver();//出错了就结束编程ComBuf[0]=0xff;SendResp();//回应上位机一个字节,表示写数据出错了WaitData();//等待上位机的回应后就结束return;}nAddress++;//下一个单元}ComBuf[0]=1;//回应上位机一个字节,表示数据块顺利完成,请求继续SendResp();}else if(ComBuf[0]==0x00)//写器件结束break;else//可能是通讯出错了{pw.fpProOver();return;}}else//等待数据失败{pw.fpProOver();return;}}pw.fpProOver();//编程结束后的工作Delay_ms(50);//延时等待上位机写线程结束ComBuf[0]=0;//通知上位机编程器进入就绪状态SendData();}void Read()//读器件{BYTE n;pw.fpInitPro();//先设置成编程状态SendData();//回应上位机表示进入读状态while(1){if(WaitResp())//等待上位机回应1个字节{if(ComBuf[0]==0)//ComBuf[0]==0表示读结束{break;}else if(ComBuf[0]==0xff)//0xff表示重发{nAddress=nAddress-0x0010;}for(n=2;n<=17;n++)//ComBuf[2~17]保存读出的数据块{ComBuf[n]=pw.fpRead();//<<<<<<<<<<调用写该器件一个单元的函数nAddress++;//下一个单元}ComBuf[0]=6;//向上位机发送读出的数据块SendData();}elsebreak;//等待回应失败}pw.fpProOver();//操作结束设置为运行状态ComBuf[0]=0;//通知上位机编程器进入就绪状态SendData();}void Lock()//写锁定位{pw.fpLock();SendData();}///////////////////////////////////////////////////////////////////////////////////所支持的FID,请在这里继续添加/////////////////////////////////////////////////////////////////////////////extern void PreparePro00();//FID=00:AT89C51编程器extern void PreparePro01();//FID=01:AT89C2051编程器extern void PreparePro02();//FID=02:AT89S51编程器void main(){SP=0x60;SetVpp5V();//先初始化Vpp为5vSCON=0x00;TCON=0x00;//PCON=0x00;//波特率*2IE=0x00;//TMOD: GATE|C/!T|M1|M0|GATE|C/!T|M1|M0// 0 0 1 0 0 0 0 1TMOD=0x21;//T0用于延时程序TH1=0xff;TL1=0xff;//波特率28800*2,注意PCON//SCON: SM0|SM1|SM2|REN|TB8|RB8|TI|RI// 0 1 0 1 0 0 0 0SCON=0x50;TR1=1;Delay_ms(1000);//延时1秒后编程器自举ComBuf[0]=0;SendData();while(1)//串口通讯采用查询方式{if(!WaitComm())//如果超时,通讯出错{Delay_ms(500);ComBuf[0]=0;//让编程器复位,使编程器就绪}switch(ComBuf[1])//根据FID设置(ProWork)pw中的函数指针{case 0: //at89c51编程器PreparePro00(); break;case 1: //at89c2051编程器PreparePro01(); break;case 2: //at89s51编程器PreparePro02(); break;//case 3:支持新器件时,请继续向下添加// break;//case 4:// break;default: ComBuf[0]=0xff;ComBuf[1]=0xff; //表示无效的操作break;}switch(ComBuf[0])//根据操作ID跳到不同的操作函数{case 0x00:RstPro();break; / /编程器复位case 0x01:ReadSign();break; //读特征字case 0x02:Erase();break;//擦除器件case 0x03:Write();break;//写器件case 0x04:Read();break;//读器件case 0x05:Lock();break;//写锁定位default: SendData();break;}}}5.v oid InitSerial(void){TMOD = 0x20; // T1 方式2PCON=0x00; // PCON=00H,SMOD=0 PD = PCON.2 = 1 进入掉电模式TH1 = TL1 = BAUD_9600; // BAUD: 9600SCON = 0x50; // 串行通信方式1 REN=1 允许接收ET1 = 0; // 不允许中断TR1 = 1; // 开启定时器1IE = 0; // 关闭所有中断允许位memset(&SerialBuf, 0x00, SERIAL_BUF_LEN); // 初始化SerialBuf[SERIAL_BUF_LEN] }/**********************************************************名称:SendByte()**功能:串口发送一个字节**输入:ucData**返回:无**说明:无********************************************************/void SendByte(unsigned char ucData){SBUF = ucData;while(!TI){_CLRWDT_;}TI = 0;}RS232串口通信程序#include <AT89X52.H>unsigned char code dispcode1[]={" welcome! "}; unsigned char code dispcode2[]={""}; unsigned char i,j,k,l,DData;sbit RS = P3^5;sbit RW = P3^6;sbit E = P3^7;unsigned char m=0;void delay(){for(l=0;l<=100;l++){}}void enable() //write order{RS=0;RW=0;E=0;delay();E=1;}void enable2() //write data{RS=1;RW=0;E=0;delay();E=1;}void initializtion() //lcd initializtion{for(i=0;i<=100;i++)P0=0x01;enable();P0=0x38;enable();P0=0x0f;enable();P0=0x06;enable();}void Display(m,DData) // display data{P0=0xC0+m; //write addressenable();P0=DData; //write dataenable2();}void Esisr() interrupt 4 //串口接收中断服务程序{unsigned char temp;ES=0;if(RI == 1){RI = 0;temp = SBUF; //接收数据SBUF=temp; //将接收到的数据发送至PC机Display(m,temp); //将接收到的数据送LCD显示while(!TI); //等待数据发送完成TI=0;m++;if(m>16)m=0;}ES=1;}void system_initial(void) //system initializtion{TMOD=0x21;// 定时器1工作方式2,定时器0工作方式1PCON=0x00;//数据传输率选择。

51单片机的2个串口分别通信的方法

51单片机的2个串口分别通信的方法

51单片机的2个串口资源分别通信的方法当使用51单片机的2个串口资源进行通信时,比如用一个串口与PLC的串口使用RS485协议通信,一个串口通过蓝牙模块和另一个单片机无线通信时,该如何处理呢?传统的51单片机只有1个串口资源,只能采用分时复用的方法。

STC的15系列增强版51单片机具有多个串口资源,本文将描述如何使用IAP15W4K58S单片机用一个串口资源与PLC的RS485有线通信,另一个串口资源与Arduino单片机通过蓝牙模块无线通信,该通讯连接过程中PLC作为主机,IAP15W4K58S作为中间机,Arduino单片机作为最低层级。

工作过程是按下启动按键,PLC发信息给IAP15W4K58S单片机发高速脉冲控制步进电机驱动的机械臂运动取走货物,当货物取走后,IAP15W4K58S单片机通过蓝牙模块通知Arduino单片机控制的小车将新货物运送过来。

连接结构示意图如下图所示。

本例程使用的单片机型号为:IAP15W4K58S,该单片机有4个采用UART 工作方式的全双工异步串行通信接口(分别为串口1、串口2、串口3和串口4),每个串行口由2个数据缓冲器、1个移位寄存器、1个串行控制寄存器和1个波特率发生器等组成。

本项目使用串行口1和串行口2。

串行口1的两个缓冲器共用寄存器SBUF (99H),串行口2的两个缓冲器共用寄存器S2BUF(9BH)。

10位(1起始位,8位数据位,1停止位)可变波特率(9600)。

串口1对应的硬件部分是TxD和RxD,串行口2对应硬件部分是TxD2和RxD2。

串口1选择引脚P3.0(RxD)和P3.1(TxD),串口2选择引脚P1.0(RxD)和P1.1(TxD)。

串口1既可以选择T1作为波特率发生器,也可以选择T2作为波特率发生器。

本文串口1提供2个选择(T1和T2),串口2只能选择T2作波特率发生器。

但是当串口1和串口2的波特率相同时,可以共用T2作为波特率发器,当T2工作在1T模式时,串行口1的波特率=SYSclk/(65536-[RL_TH2,RL_TL2])/4,SYSclk表示系统时钟频率,[RL_TH2,RL_TL2]表示T2H,T2L的定时初值设置值。

[指南]51单片机串口通信程序(方式2)

[指南]51单片机串口通信程序(方式2)

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单片机串口通信实例

51单片机串口通信实例

51系列单片机串口通信实例教程2010-01-22 15:17:11 来源: 电子工程师论坛单片机的串口通信看起来是很复杂的,主要是因为他用到了更多的寄存器,与前面的知识相比他更具综合能力,写起来考虑的问题自然也变多了.而前面学习过的定时器与中断将是单片机通信的基础.单片机的中断系统中第4个中断就是串口中断,要进行串口通信首先就要打开CPU总中断EA,还要打开串口通信中断ES,这是串口通信的前堤,而串口通信也跟计时器一样有很多的模式,因此我们还要设置SCON寄存器来指定采用哪一种方式进行通信,而在通信的过程中,我们还要设定通信的波特率,不然的话,单片机是没办法进行采样的,这样也不会得到正确的结果了.我在实验过程中用到的是1号定时器来设定的波特率,用到了计时器方式2,也就是8位自动重装,这样可以简化编程,它的实现思想就是将常数放入TH,而TL中则是初始化参数,当溢出时,单片机会自动将TH中的常数装入TL中.再来说说波特率,我们为什么要设定波特率,因为单片机会以16倍波特率的速度进行采样,而在实验中我们用的是10位异步收发方式,因此要将SM0置0,SM1置1.而其中的10位有8位数据位,第一位和最后一位是发送数据的起始与结束.采用高的皮特率就不会出错啦.而波特率是有一个公式的:方式0的波特率 = fosc/12方式2的波特率 =(2SMOD/64)· fosc方式1的波特率 =(2SMOD/32)·(T1溢出率)方式3的波特率 =(2SMOD/32)·(T1溢出率)T1 溢出率= fosc /{12×[256 -(TH1)]}根据公式我们很容易就算出当晶振为110592HZ时,要达到9600的波特率,我们只需要将TL1置FDH即可,如下图:除此之外,你还要将SCON中的REN位置1,不然的话,单片机是不会接收数据的.还有不要忘了选择定时器的工作方式,设置TMOD为0x20既是工作方式2,8位自动重装定时器.这样一来,初始批工作算是差不多了.而串口通信分为中断方式,和查询方式,如果你想用查询方式你也不用设置IE寄存器了.在串口通信中,还有一个很重要的寄存器SBUF,其实也不是一个,是两个,只是它们共用同一个地址,再根据表达式的不同,单片机会自动选择使用哪一个SBUF.下面是我写的一个例子程序,产生的效果是:向单片机发送任一个0~255之间的数,将会被显示到数码管上.并且单片机还会自动把刚才传过去的数又发送回来 ,实验过程中用到了几个工具如下:串口调试助手V2.1.exe,51串口波特率计算器.exe(我已打包在附件中)还有一些必用的就不说了.C代码#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit sda = P1^0;sbit clk = P1^1;sbit dig1 = P1^2;sbit dig2 = P1^3;sbit dig3 = P1^4;sbit dig4 = P1^5;uchar r,flag;uchar code table[]={0x7e,0x0c,0xb6,0x9e,0xcc,0xda,0xfa,0x0e,0xfe,0xde,0xef,0xf9,0x72,0xb8,0xf2,0xe2};void init();void write(uchar);void display(uchar);void delay(uchar);void main(){init();while(1){//查询方式通信//if(RI==1) //RI为1表示收到一字节数据//{// RI = 0;//此步必不可少,因为硬件不能将其置0 // r = SBUF;//}display(r); //中断方式通信delay(10);if(flag==1){flag = 0;ES = 0;SBUF = r; //放送数据while(!TI);TI = 0;ES = 1;}}/** 串口中断 **/void ser() interrupt 4 {RI = 0;r = SBUF;flag = 1;}/** 延迟函数 **/void delay(uchar t) {uchar x,y;for(x=t;x>0;x--)for(y=101;y>0;y--);}/** 初始化 **/void init(){dig1 = 1;dig2 = 1;dig3 = 1;dig4 = 1;r = 0xff;TMOD = 0x20;TH1 = 0xfd;TL1 = 0xfd;TR1 = 1; //启动定时器1,从而设定了串口通信的波特率SM0 = 0;SM1 = 1; //设定串口通信方式为十位异步收发器REN = 1; //打开串口通信EA = 1;ES = 1;}/** 向数据码管写入一个字节数据 **/void write(uchar u){uchar i;for(i=0;i<8;i++){clk = 1;sda = u&0x80;clk = 0;u = u<<1;}}/** 显示一个3位的整数 **/void display(uchar num){uchar bai,shi,ge; bai = num/100;shi = num%100/10; ge = num%10;/* 显示个位 */dig4 = 0;write(table[ge]); delay(10);dig4 = 1;/* 显示百位 */if(bai!=0){dig2 = 0;write(table[bai]); delay(10);dig2 = 1;/* 显示十位 */dig3 = 0;write(table[shi]); delay(10);dig3 = 1;}else{if(shi==0){dig3 = 1;//delay(10);}else{/* 显示十位 */dig3 = 0;write(table[shi]); delay(10);dig3 = 1;}}}。

51单片机汇编模拟串口通信程序

51单片机汇编模拟串口通信程序

51单片机汇编模拟串口通信程序T2作为波特率控制UART_RXD是硬中断0或1 口,如果能进入中断,说明该线有一个起始位产生,进入中断后调用下面的接收程序。

退出硬中断之前还需要将硬中断标志重新复位。

UART_TXD是任何其它IO即可。

UART_SEND:P USH IEP USH DPHP USH DPLP USH PSWP USH 00HP USH ACCCLR EASETB UART_TXD ;START BITMOV R0,ACLR TR2 ;TR2置1,计数器2启动,时间计数启动。

MOV A,RCAP2L;计数器2重新装载值MOV TL2,A ;置计数器2初值;T2需要重新装载MOV A,D PH CLR TF2MOV A,RCA P2HMOV TH2,AMOV A,R0SETB TR2 ;TR2 置1,计数器JNB TF2,$CLR TF2JNB TF2,$CLR TF2CLR UART_TXD ;START BITJNB TF2,$CLR TF2JNB TF2,$CLR TF2MOV R0,#08HUART_SEND_L OOP:RRC AMOV UART_TXD,C ;8 BIT JNB TF2,$CLR TF2DJNZ RO,UART_SEND_L OOP SETB UART_TXD ;END BIT JNB TF2,$CLR TF2JNB TF2,$CLR TF2POP ACCPOP OOHPOP PSWPOP DPLPOP DPHPOP IERET....;;;;;;; UART_REC:P USH IEP USH DPHP USH DPLCLR EACLR TR2 ;TR2置1,计数器2启动,时间计数启动。

MOV A,RCAP2L;计数器2 重新装载值CLR TF2MOV TL2,A ;置计数器2初值;T2需要重新装载MOV A,DPHMOV A,RCA P2HMOV TH2,AJB UART_RXD,$ ;RECSETB TR2 ;TR2置1,计数器2启动,时间计数启动。

51单片机的串口通信程序之欧阳化创编

51单片机的串口通信程序之欧阳化创编

单片机串口通信程序创作:欧阳化#inelude <reg52.h> #include<intrins.h>#include<stdio.h>#include <math.h>#define uchar unsigned char #define uint unsigned int sbit Keyl = P2A3;sbit Key2 = P2A2;sbit Key3 = P2A1;sbit Key4 = P2A0;sbit BELL = P3A6;sbit CONNECT = P3A7;unsigned int Keyl_flag = 0;iinsigned int Key2_flag = 0;unsigned int Key3_flag = 0;unsigned int Key4_flag = 0;unsigned charb;unsigned char codeNum[21] = {0xc0,0xf9,0xa4, OxbO, 0x99,0x92,0x82z 0xf8,0x80,0x90,0x40,0x79,0x24,0x30,0x19,0x12, 0x02,0x78,0x00, 0x10,0x89}; unsigned char code Disdigit[4]= {0x7F,0xBF,0xDF,0xEF};unsignedchar 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) { H=o ; break; } }} void SeanKey(){ if(Keyl ==0) { delayms(lOO); if(Keyl ==0) { Keyljlag = 1; Key2Jlag = 0; Key3Jlag = 0; Key4Jlag = 0; Keyl =1;} else; } if(Key2 == 0) { delayms(lOO); if(Key2 ==0) { Key2Jlag = 1; Keyljlag = 0; Key3Jlag = 0; Key4Jlag = 0; Key2 =1;} else; } if(Key3 == 1; SendData(0x55); Keyljlag = 0; } else0) { delayms(50); if(Key3 == 0) { =1; Keyl_flag = 0; Key2_flag = 0; 0; Key3 = 1; }else; } if(Key4 ==0) { delayms(50); if(Key4 == 0) { =1; Keyl_flag = 0; Key2_flag = 0;0; Key4 = 1; } else; } else; }voidKeyProc(){ if(Keyl_flag) { TRI =Key3JlagKey4_flag = Key4JlagKey3Jlag =if(Key2_flag) { TRI =1; SendData(Oxll); Key2_flag = 0; } elseif(Key3_flag) { Pl=Oxff; BELL = 0; CONNECT =1; Key3_flag = 0; ) else if(Key4_flag) { CONNECT =0; BELL = 1; Key4_flag = 0; } else; }void Initdisplay(void){Disbuf[0] = l;Disbuf[l] = 2;Disbuf[2]=3;Disbuf[3] = 4;}void DisplayO 〃显示{unsigned int i = 0;unsignedint temp,count; temp = Disdigit[count]; P2=temp; temp = Disbuf[count]; temp =Num [temp]; P0=temp; count++; if (count==4) count =0; ) void timeOO interrupt 1 using2{ DisplayO; THO = (65535 ・ 2000)/256; TLO = (65535 ・2000)%256;} void main(){Initdisplay();TMOD = 0x21;TH0 = (65535 ・ 2000)/256;TL0 = (65535 ・ 2000)%256;TR0 = 1;ETO = 1; TH1 = OxFD;//11.0592MTL1 = OxFD;PCO N&=0x80;TRl = 1;ET1 = 1;SCON = 0x40; 〃串口方式REN = 1; PT1 = O;PTO = 1;EA =1;while(l) { ScanKeyO; KeyProc(); if(RI) { D isbuf[O] = 0; Disbuf[l] = 20; Disbuf[2]=SBUF>>4; Disbuf[3]二SBUF&0x0f; RI = 0; } else; }}。

51串口通信实验报告

51串口通信实验报告

51串口通信实验报告实验内容将数据1~9发送到另一单片机,用数码管显示出来设计方法发送端单片机与接收端单片机通过MAX232互连,接受端以数码管显示每次串口接受到的数据。

采用波特率9600的定时器1方式2发送及接收。

实验电路源程序发送端:#include <reg51.h>void main(){unsigned int send[11]={0x90,0x80,0xf8,0x82,0x92,0x99,0xb0,0xa4,0xf9,0xc0,0xff};unsigned int i,j;TMOD=0x20; /*设置波特率为9600的定时器1方式2*/TL1=0xfd;TH1=0xfd;SCON=0x40;PCON=0x00;TR1=1;while(1){for(i=0;i<10;i++){SBUF=send[i];while(TI==0);for(j=0;j<40000;j++); /*延时*/TI=0;}}}接收端#include <reg51.h>#define uint unsigned intvoid main(){uint i,j;uint receive[11];TMOD=0x20; /*设置波特率为9600的定时器1方式2*/ TL1=0xfd;TH1=0xfd;SCON=0x50;PCON=0x00;TR1=1;while(1){for(i=0;i<10;i++){receive[i]=SBUF;P0=receive[i];while(RI==0);for(j=0;j<30000;j++);RI=0;}for(j=0;j<50000;j++); /*延时*/}}流程图。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

51单片机串口通信(相关例程) 51单片机串口通信(相关例程)
一、简介
51单片机是一种常用的微控制器,它具有体积小、功耗低、易于编
程等特点,被广泛应用于各种电子设备和嵌入式系统中。

串口通信是
51单片机的常见应用之一,通过串口通信,可以使单片机与其他外部
设备进行数据交互和通信。

本文将介绍51单片机串口通信的相关例程,并提供一些实用的编程代码。

二、串口通信基础知识
1. 串口通信原理
串口通信是通过串行数据传输的方式,在数据传输过程中,将信息
分为一个个字节进行传输。

在51单片机中,常用的串口通信标准包括RS232、RS485等。

其中,RS232是一种常用的串口标准,具有常见的DB-9或DB-25连接器。

2. 串口通信参数
在进行串口通信时,需要设置一些参数,如波特率、数据位、停止
位和校验位等。

波特率表示在单位时间内传输的比特数,常见的波特
率有9600、115200等。

数据位表示每个数据字节中的位数,一般为8位。

停止位表示停止数据传输的时间,常用的停止位有1位和2位。

校验位用于数据传输的错误检测和纠正。

三、串口通信例程介绍
下面是几个常见的51单片机串口通信的例程,提供给读者参考和学习:
1. 串口发送数据
```C
#include <reg51.h>
void UART_Init()
{
TMOD = 0x20; // 设置计数器1为工作方式2(8位自动重装) TH1 = 0xFD; // 设置波特率为9600
SCON = 0x50; // 设置串口工作方式1,允许串行接收
TR1 = 1; // 启动计数器1
}
void UART_SendChar(unsigned char dat)
{
SBUF = dat; // 发送数据
while (!TI); // 等待发送完成
TI = 0; // 清除发送完成标志
}
void main()
{
UART_Init(); // 初始化串口
while (1)
{
UART_SendChar('A'); // 发送字母A
}
}
```
2. 串口接收数据
```C
#include <reg51.h>
void UART_Init()
{
TMOD = 0x20; // 设置计数器1为工作方式2(8位自动重装) TH1 = 0xFD; // 设置波特率为9600
SCON = 0x50; // 设置串口工作方式1,允许串行接收
TR1 = 1; // 启动计数器1
}
void UART_Recv()
{
unsigned char dat;
if (RI) // 检测是否接收到数据
{
dat = SBUF; // 读取接收到的数据 RI = 0; // 清除接收中断标志
// 处理接收到的数据
}
}
void main()
{
UART_Init(); // 初始化串口
EA = 1; // 允许中断
ES = 1; // 允许串口中断
while (1)
// 主循环处理其他任务
}
}
```
3. 串口发送字符串
```C
#include <reg51.h>
void UART_Init()
{
TMOD = 0x20; // 设置计数器1为工作方式2(8位自动重装) TH1 = 0xFD; // 设置波特率为9600
SCON = 0x50; // 设置串口工作方式1,允许串行接收
TR1 = 1; // 启动计数器1
}
void UART_SendString(unsigned char *str)
{
while (*str != '\0')
SBUF = *str; // 逐个发送字符
while (!TI); // 等待发送完成
TI = 0; // 清除发送完成标志
str++; // 指针指向下一个字符
}
}
void main()
{
UART_Init(); // 初始化串口
while (1)
{
UART_SendString("Hello, World!"); // 发送字符串
}
}
```
四、总结
本文介绍了51单片机串口通信的基础知识和相关编程例程,包括
串口发送数据、串口接收数据和串口发送字符串。

通过学习这些例程,
读者可以更好地理解和使用51单片机的串口通信功能。

希望本文对读者有所帮助,谢谢阅读。

相关文档
最新文档