51单片机入门零基础25串口发数.doc_第1页
51单片机入门零基础25串口发数.doc_第2页
51单片机入门零基础25串口发数.doc_第3页
51单片机入门零基础25串口发数.doc_第4页
51单片机入门零基础25串口发数.doc_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1.1 串口发数1.1.1 串口发数的原理在模拟外部晶振为11.0592 MHz、波特率为9 600 bps的情况下,设置常量BAUD为0xFE80,并将该常量赋值到TL0、TH0两个寄存器中,实现定时。每到相应时间触发定时中断程序,将外部引脚的状态读入并存入预先设定的数组中,完成模拟串口读入字节的任务。常用的波特率配置如图 2.51所示。由于STC15L104E没有串口,因而必须利用定时器模拟串口。其方法是,定义一个常量,根据所需要的波特率对该常量赋值,并将该常量值赋到定时所用的寄存器中。图 1.11 常用波特率配置对于BAUD的具体算法是BAUD=65536-SYSclk/3/BAUDRATE/M(1T:M=1;12T:M=12)。65536是定时器T0的溢出值,因为T0定时器为16位定时器,所以溢出值为216,SYSclk为系统时钟频率11.0592MHZ,BAUDRATE为波特率9600bps,而我们使用的是单周期M=1,所以我们要像定时器里存入0xfe80。对于BAUD的算法,上一节讲到定时器中断的原理,定时器计时65536位的时候就会溢出,然后进入中断。而我们要模拟的串口波特率为9600bps,我们想要每一位执行的时间T1就是1/9600s,而系统晶振震荡一次读一位的时间T2为1/11.0592us(单周期),那么我们要读的位数就为T1/T2。那算法公式中的3是什么呢,这是因为我们每读一位要抽样三次来检查读取的数据。我们要计数SYSclk/3/BAUDRATE/M位的时候产生中断,就要用65536-SYSclk/3/BAUDRATE/M,赋值给定时器,定时器定期检查串口,实现串口模拟。本实验中我们用到的寄存器有AUXR、TMOD、TCON、IE、IP,前两节都已经详细介绍,本节不做深入讲解。1.1.2 硬件连接模拟串口的硬件连接须将单片机两个引脚分别定义为收数据发数据,在这里我们定义P3.1为发送数据,P3.0为接收数据。原理图如图 2.52所示。图 1.12 模拟串口的硬件连接1.1.3 原工程详解打开串口发数的程序,分析一下程序。a. 首先是头文件,宏定义BAUD为0xfe80(算法1.1.1中已介绍,在这里不详细说明)。宏定义#define是给原内容起个新名字,方便后面直接写新名字,用法是#define 新名字 原内容,注意没有分号。#define BAUD 0xFE80的意义就是用BAUD代替0xfe80。定义AUXR寄存器,定义接收串口(P30)和发送串口(P31)。声明类型typedef,typedef是只将已有的类型换个别的名字,typedef bit BOOL;的意思就是将bit换成BOOL的名字,下面两句同样道理。定义模拟串口的标志,其中TBUF/RBUF为存放数据的缓存区,TDAT/RDAT为要传送的数据,TCNT/RCNT为抽样计数器,TBIT/RBIT为字节的位数,TING/RING为起始标志位,TEND/REND为结束标志位。接着声明了4个子函数,分别是串口初始化函数、延时函数、发送字节函数和发送字符串子函数。声明子函数的写法在前面的章节都介绍过,此处不介绍。/*声明*/#include reg51.h#define BAUD0xFE80 sfr AUXR = 0x8E;sbit RXB = P30; /定义 UART TX/RX sbit TXB = P31;typedef bit BOOL; typedef unsigned char BYTE;typedef unsigned int WORD;BYTE TBUF,RBUF; /模拟串口的状态标志BYTE TDAT,RDAT;BYTE TCNT,RCNT;BYTE TBIT,RBIT;BOOL TING,RING; /起始标志位BOOL TEND,REND; /结束标志位void UART_INIT();void Delay_mS(unsigned int time);void UART_SendByte(unsigned char date);void UART_SendString(unsigned char* Data,unsigned int len);注意*Data是一个指针,也是一个数组,数组就是指针,也可写成Data。b. 接下来分析四个子函数。void Delay_mS(unsigned int time) /延时time mS的延时程序,最大可以延时65535毫秒 unsigned int i; /定义一个名字是“i”的无符号int型变量 while(time) /等到毫秒数减到0 for(i=0;i142;i+);/延时1mS time -; / 等效于time=time-1; 延时子函数,这个子函数无返回值,参数是无符号整形的time。进入子函数声明变量i,进入while循环执行for循环直到time为0,for循环内的延时时间相当于1ms。For循环就是for(条件1; 条件2; 条件3),条件1为起始,看条件1是否符合条件2,符合执行for中的语句,执行结束后执行条件3,再看执行条件3后的条件是否符合条件2,符合继续执行语句,以此类推直到不符合条件2跳出循环。所以这个子函数每进入while一次就执行for循环一次(跑142个数),这个for语句没有,说明它起的是一个延时作用,延时1ms后time就减1一次,直到time减到0跳出while循环,最后我们延时的数是142*time次,完成了延时。/*发送字符子函数*/void UART_SendByte(unsigned char date) /发送字符 if (TEND) / 等待数据的传送 TEND = 0; TBUF =date; TING = 1; Delay_mS(100);发送字节子函数,等待数据的传送if (TEND), TEND=1执行内部语句,将TEND重新赋值0,把要发送的数据date(参数)给TBUF,后面的中断模拟串口可知发数是通过TBUF发出去的,所以要将data给TBUF。将发送起始位TING赋值1,跳出if语句。调用延时子函数延时100ms。我们赋的初值TEND=1,所以在主函数中调用此函数时,这个函数里的语句都直接执行。这个发送字节函数的作用是每执行一次就发送一个字节(8位)。/*发送字符串*/void UART_SendString(unsigned char* Data,unsigned int len) /发送句子 unsigned int i=0; for(;i8; /timer0 预装载值 TR0 = 1; /tiemr0 开启 ET0 = 1; /开启 timer0 中断 PT0 = 1; /提升 timer0 中断优先级 EA = 1; /开总中断 TING = 0;/状态标志位赋初值 RING = 0; TEND = 1; REND = 0; TCNT = 0; RCNT = 0;模拟串口初始化子函数。将TMOD赋值0x00,说明T0工作在16位自动重装模式。AUXR寄存器赋值0x80,说明T0为单周期不分频(1T模式)。给定时器0赋初值,将BAUD的高8位赋给TH0(BAUD8将BAUD右移8位,BAUD就由0xfe80变成0x80),低8位赋给TL0(直接赋值),说明定时器定时BAUD个位时就产生中断。ET0=1开启定时器0中断,PT0提升T0的中断优先级,EA开启总中断。将模拟串口状态标志位中的TEND发送结束位赋值1,其他赋值0。这些都并不陌生了,不细讲解。c. 接着我们分析中断程序,它是模拟串口的中心程序。void tm0() interrupt 1 using 1/time0中断查询来模拟串口 if (RING)/开始接收 if (-RCNT = 0) RCNT = 3; / 重置发送波特率计数器 if (-RBIT = 0) RBUF = RDAT; /数据保存到RBUF RING = 0; /停止接收 REND = 1; /设置接收完成标志 else RDAT = 1; if (RXB) RDAT |= 0x80; /shift RX data to RX buffer else if (!RXB) RING = 1; /启动标志位 RCNT = 4; / 初始接收波特率计数器 RBIT = 9; /初始接收比特数(8位加一位停止位)先看中断中的接收程序,RING初始为0,所以直接进入else if (!RXB)。由串口协议知当串口有数据接收时起始位为低电平,接收结束后结束为为高电平。所以如果有数据接收(RXB=0)进入else if语句中,RING=1启动标志位,RCNT=4初始化波特率计数器,RBIT=9初始比特数。这是第一次对接收数据抽样,此时是对数据第一位之前的一位起始位进行抽样(起始位为低电平)。第二次进入中断时RING=1进入if (RING),-RCNT=3不执行下面语句,此时是对起始位第二次抽样。第三次进入中断-RCNT=2,不执行下面语句,此时是对起始位第三次抽样,此时抽样的位置为一个周期(即一个波特率的周期频率),这也是为什么我们在计算溢出时要除以的那个“3”的原因。第4次进入中断-RCNT=1,不执行下面语句,此时是数据位第一位的1/3处抽样。第5次进入中断-RCNT=0(在数据位第一位的2/3处抽样),将RCNT重新赋值3,执行else语句(-RBIT=8不为0),RDAT初始为0,右移一位还为0(RDAT = 1;),读取接收位,若接收位为0,则RDAT数据为不变为0,若接收位为1,那么将RDAT最高位置1。上面讲述的过程为读取第一位数据的过程。RCNT赋值3,进行下一轮的抽样,定时器定时一周,-RCNT=2后第一次进入中断(此时在数据第一位的末端),-RCNT=1进行第二次抽样(此时在数据第二位的1/3处),-RCNT=0将RCNT重新置3,执行读数。直到抽样进行8轮,也就是读取8位接收数据结束,进行第九轮抽样的时候(读取结束位为高电平),-RBIT=0那么RBUF = RDAT;数据保存到RBUF,RING = 0停止接收,REND = 1设置接收完成标志 。读取一个字节结束。 为方便理解,见图 2.53,数字为TCNT,我们设我们要接收的数据是10101010。图 1.13 模拟串口脉冲图每一个0的位置就是我们读取数据的位置,可参照上面的讲解看这个图。 if (-TCNT = 0) TCNT = 3; /reset send baudrate counter if (TING) /judge whether sending if (TBIT = 0) TXB = 0; /send start bit TDAT = TBUF; /load data from TBUF to TDAT TBIT = 9; /initial send bit number (8data bits+1 stop bit) else TDAT = 1; /shift data to CY if (-TBIT = 0) TXB = 1; TING = 0; /stop send TEND = 1; /set send completed flag else TXB = CY; /write CY toTX port 中断中的发送程序,在发送字符子函数中TING=1、TEND=0,TCNT初值为0所以直接进入程序if (TING)。TBIT初值为0执行TXB=0发送串口低电平开始发送、TDAT=TUBF将TUBF保存到TDAT、TBIT=9。再次进入中断执行else(TBIT=9),将要发送的数据右移一位,执行TXB=CY(-TBIT=8)将溢出位发给TXB,循环8次(-TBIT=1)将八位都发给TXB发送出去,第9次-TBIT=0,TXB置高,TING置0停止发送,TEND=1结束标志位。发送结束。最后我们分析主函数。void main() UART_I

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论