单片机IO口模拟串口程序(发送+接收)_第1页
单片机IO口模拟串口程序(发送+接收)_第2页
单片机IO口模拟串口程序(发送+接收)_第3页
单片机IO口模拟串口程序(发送+接收)_第4页
单片机IO口模拟串口程序(发送+接收)_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

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

文档简介

1、前一阵一直在做单片机的程序,由于串口不够,需要用IO口来模拟出一个串口。经过若干曲折并参考了一些现有的资料,基本上完成了。现在将完整的测试程序,以及其中一些需要总结的部分贴出来。程序硬件平台:11.0592M晶振,STC单片机(兼容51)/* 在单片机上模拟了一个串口,使用P2.1作为发送端* 把单片机中存放的数据通过P2.1作为串口TXD发送出去*/#include <reg51.h>#include <stdio.h>#include <string.h>typedef unsigned char uchar;int i;uchar code info

2、= 0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55;sbit newTXD = P21;/模拟串口的发送端设为P2.1void UartInit() SCON = 0x50; / SCON: serail mode 1, 8-bit UART TMOD |= 0x21; / T0工作在方式1,十六位定时 PCON |= 0x80; / SMOD=1; TH0 = 0xFE; / 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=11.0592MHz TL0 =

3、 0x7F; / 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=11.0592MHz/ TH0 = 0xFD; / 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=18.432MHz/ TL0 = 0x7F; / 定时器0初始值,延时417us,目的是令模拟串口的波特率为2400bps fosc=18.432MHzvoid WaitTF0(void) while(!TF0); TF0=0; TH0=0xFE; / 定时器重装初值 fosc=11.0592MHz TL0=0x7F; / 定时器重装初值 fosc=11.05

4、92MHz / TH0 = 0xFD; / 定时器重装初值 fosc=18.432MHz / TL0 = 0x7F; / 定时器重装初值 fosc=18.432MHzvoid WByte(uchar input) /发送启始位 uchar j=8; TR0=1; newTXD=(bit)0; WaitTF0(); /发送8位数据位 while(j-) newTXD=(bit)(input&0x01); /先传低位 WaitTF0(); input=input>>1; /发送校验位(无) /发送结束位 newTXD=(bit)1; WaitTF0(); TR0=0; void

5、 Sendata() for(i=0;i<sizeof(info);i+)/外层循环,遍历数组 WByte(infoi); void main() UartInit(); while(1) Sendata(); #/* 模拟接收程序,这个程序的作用从模拟串口接收数据,然后将这些数据发送到实际串口* 在单片机上模拟了一个串口,使用P3.2作为发送和接收端* 以P3.2模拟串口接收端,从模拟串口接收数据发至串口*/#include<reg51.h>#include<stdio.h>#include<string.h>typedef unsigned cha

6、r uchar ;/这里用来切换晶振频率,支持11.0592MHz和18.432MHz/#define F18_432#define F11_0592 uchar tmpbuf264=0;/用来作为模拟串口接收数据的缓存struct uchar recv :6 ;/tmpbuf2数组下标,用来将模拟串口接收到的数据存放到tmpbuf2中 uchar send :6 ;/tmpbuf2数组下标,用来将tmpbuf2中的数据发送到串口tmpbuf2_point=0,0;sbit newRXD=P32 ;/模拟串口的接收端设为P3.2void UartInit() SCON=0x50 ;/ SCON

7、: serail mode 1, 8-bit UART TMOD|=0x21 ;/ TMOD: timer 1, mode 2, 8-bit reload,自动装载预置数(自动将TH1送到TL1);T0工作在方式1,十六位定时 PCON|=0x80 ;/ SMOD=1; #ifdef F11_0592 TH1=0xE8 ;/ Baud:2400 fosc=11.0592MHz 2400bps为从串口接收数据的速率 TL1=0xE8 ;/ 计数器初始值,fosc=11.0592MHz 因为TH1一直往TL1送,所以这个初值的意义不大 TH0=0xFF ;/ 定时器0初始值,延时208us,目的是

8、令模拟串口的波特率为9600bps fosc=11.0592MHz TL0=0xA0 ;/ 定时器0初始值,延时208us,目的是令模拟串口的波特率为9600bps fosc=11.0592MHz #endif #ifdef F18_432 TH1=0xD8 ; / Baud:2400 fosc=18.432MHz 2400bps为从串口接收数据的速率 TL1=0xD8 ; / 计数器初始值,fosc=18.432MHz 因为TH1一直往TL1送,所以这个初值的意义不大 TH0=0xFF ;/ 定时器0初始值,延时104us,目的是令模拟串口的波特率为9600bps fosc=18.432MH

9、z TL0=0x60 ;/ 定时器0初始值,延时104us,目的是令模拟串口的波特率为9600bps fosc=18.432MHz #endif IE|=0x81 ;/ 中断允许总控制位EA=1;使能外部中断0 TF0=0 ; IT0=1 ;/ 设置外部中断0为边沿触发方式 TR1=1 ;/ 启动TIMER1,用于产生波特率void WaitTF0(void) while(!TF0); TF0=0 ; #ifdef F11_0592 TH0=0xFF ;/ 定时器重装初值 模拟串口的波特率为9600bps fosc=11.0592MHz TL0=0xA0 ;/ 定时器重装初值 模拟串口的波特率

10、为9600bps fosc=11.0592MHz #endif #ifdef F18_432 TH0=0xFF ; / 定时器重装初值 fosc=18.432MHz TL0=0x60 ; / 定时器重装初值 fosc=18.432MHz #endif /接收一个字符uchar RByte() uchar Output=0 ; uchar i=8 ; TR0=1 ; /启动Timer0 #ifdef F11_0592 TH0=0xFF ;/ 定时器重装初值 模拟串口的波特率为9600bps fosc=11.0592MHz TL0=0xA0 ;/ 定时器重装初值 模拟串口的波特率为9600bps

11、fosc=11.0592MHz #endif #ifdef F18_432 TH0=0xFF ;/ 定时器重装初值 fosc=18.432MHz TL0=0x60 ;/ 定时器重装初值 fosc=18.432MHz #endif TF0=0 ; WaitTF0();/等过起始位 /接收8位数据位 while(i-) Output>>=1 ; if(newRXD)Output|=0x80 ;/先收低位 WaitTF0();/位间延时 TR0=0 ;/停止Timer0 return Output ;/向COM1发送一个字符void SendChar(uchar byteToSend)

12、SBUF=byteToSend ; while(!TI); TI=0 ;void main() UartInit(); while(1) if(tmpbuf2_point.recv!=tmpbuf2_point.send)/差值表示模拟串口接收数据缓存中还有多少个字节的数据未被处理(发送至串口) SendChar(tmpbuf2tmpbuf2_point.send+); /外部中断0,说明模拟串口的起始位到来了void Simulated_Serial_Start()interrupt 0 EX0=0 ; /屏蔽外部中断0 tmpbuf2tmpbuf2_point.recv+=RByte();

13、 /从模拟串口读取数据,存放到tmpbuf2数组中 IE0=0 ; /防止外部中断响应2次,防止外部中断函数执行2次 EX0=1 ; /打开外部中断0以上是两个独立的测试程序,分别是模拟串口发送的测试程序和接收的测试程序上面两个程序在编写过程中参考了这篇文章51单片机模拟串口的三种方法(在后文中简称51),但在它的基础上做了一些补充,下面是若干总结的内容:1、51在接收数据的程序中,采用的是循环等待的方法来检测起始位(见51的“附:51 IO口模拟串口通讯C源程序(定时器计数法)” 部分),这种方法在较大程序中,可能会错过起始位(比如起始位到来的时候程序正好在干别的,而没有处于判断起始位到来的

14、状态),或者一直在检测起始位,而没有办法完成其他工作。为了避免这个问题,在本接收程序中采用了外部中断的方法,将外部中断0引脚作为模拟串口的接收端,设IT0=1(将外部中断0设为边缘触发)。这样当起始位(低电平)到来时,就会引发外部中断,然后在外部中断处理函数中接收余下的数据。这种方法可以保证没数据的时候程序该干什么干什么,一旦模拟串口接收端有数据,就可以立即接收到。2、加入了模拟串口接收缓冲区。在较大程序中,单片机要完成的工作很多,在模拟串口接收到了数据之后立即处理的话,有可能处理不过来造成丢失数据,或者影响程序其他部分执行。本程序中加入了64个字节的缓冲区,从模拟串口接收到的数据先存放在缓冲

15、区中。这样就算程序一时没工夫处理这些数据,腾出手来之后也能在缓冲区中找到它们。3、51文中的WByte函数和RByte函数中都先打开计数器后关闭计数器。如果使用本文的外部中断法来接收数据,并且外部中断处理函数里外都调用了WByte或RByte的话,需要将这两个函数中的TR0=1,TR0=0操作的语句除去,并在UartInit()中加入一句TR0=1;即让TR0始终开着就可以。由于之前没有意识到这个问题,因此在具体应用时出现了奇怪的问题:表现为中断处理函数执行完毕之后,似乎回不到主程序,程序停在了一个不知道的地方。后来经过排查后找到了问题所在,那个程序的中断处理函数中用了RByte,中断处理函数

16、外用到了WByte,而这两个函数的最后都有TR0=0。这样当中断处理函数执行完毕后,TR0实际上是为0的,返回主程序后(中断前的主程序可能正好处于其他的WByte或RByte执行中),原先以来定时器0溢出改变TF0才能执行下去的WByte函数就无法进行下去,从而导致整个程序停下来不动。(在本文的接收测试程序中不存在这个问题,因为中断处理程序中虽调用了RByte,但中断处理程序外却没有调用RByte或WByte)下面是修改后的RByte、WByte和WaitTF0函数,仅供参考:/* 定时器0溢出后重装初值*/void WaitTF0(void) TF0=0 ; #ifdef F11_0592

17、TH0=0xFF ;/ 定时器重装初值 fosc=11.0592MHz TL0=0xA0 ;/ 定时器重装初值 fosc=11.0592MHz #endif #ifdef F18_432 TH0=0xFF ;/ 定时器重装初值 fosc=18.432MHz TL0=0x60 ;/ 定时器重装初值 fosc=18.432MHz #endif while(!TF0); TF0=0 ;/* 从串口B接收一个字符*/uchar RByte() uchar Output=0 ; uchar i=8 ; / TR0=1; /启动Timer0/* #ifdef F11_0592 TH0 = 0xFF; /

18、定时器重装初值 模拟串口的波特率为9600bps fosc=11.0592MHz TL0 = 0xA0; / 定时器重装初值 模拟串口的波特率为9600bps fosc=11.0592MHz #endif #ifdef F18_432 TH0 = 0xFF; / 定时器重装初值 fosc=18.432MHz TL0 = 0x60; / 定时器重装初值 fosc=18.432MHz #endif*/ WaitTF0();/等过起始位 /接收8位数据位 while(i-) Output>>=1 ; if(newRXD)Output|=0x80 ; /先收低位 WaitTF0();/位间延时 / while(!TF0) if(newRXD) break; /此句和下一句不能加,如果加上了将导致耗时过长,影响下一个字节的接收 / WaitTF0(); /等过结束位 / TR0=0;

温馨提示

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

评论

0/150

提交评论