51单片机模拟串口的三种方法_第1页
51单片机模拟串口的三种方法_第2页
51单片机模拟串口的三种方法_第3页
51单片机模拟串口的三种方法_第4页
51单片机模拟串口的三种方法_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

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

文档简介

1、51单片机模拟串口的三种方法51单片机模拟串口的三种方法随着单片机的使用日益频繁,用其作前置机进行采集和通信也常见于各种应用,一般是利用前置机采集各种终端数据后进行处理、存储,再主动或被动上报给管理站。这种情况下下,采集会需要一个串口,上报又需要另一个串口,这就要求单片机具有双串口的功能,但我们知道一般的51系列只提供一个串口,那么另一个串口只能靠程序模拟。本文所说的模拟串口,就是利用51的两个输入输出引脚如P1.0和P1.1,置1或0分别代表高低电平,也就是串口通信中所说的位,如起始位用低电平,则将其置0,停止位为高电平,则将其置1,各种数据位和校验位则根据情况置1或置0。至于串口通信的波特

2、率,说到底只是每位电平持续的时间,波特率越高,持续的时间越短。如波特率为9600BPS,即每一位传送时间为1000ms/9600=0.104ms,即位与位之间的延时为为0.104毫秒。单片机的延时是通过执行若干条指令来达到目的的,因为每条指令为1-3个指令周期,可即是通过若干个指令周期来进行延时的,单片机常用11.0592M的的晶振,现在我要告诉你这个奇怪数字的来历。用此频率则每个指令周期的时间为(12/11.0592)us,那么波特率为9600BPS每位要间融多少个指令周期呢?指令周期s=(/9600)/(12/11.0592)=96,刚好为一整数,如果为4800BPS则为96x2=192,

3、如为19200BPS则为48,别的波特率就不算了,都刚好为整数个指令周期,妙吧。至于别的晶振频率大家自已去算吧。现在就以11.0592M的晶振为例,谈谈三种模拟串口的方法。方法一:延时法通过上述计算大家知道,串口的每位需延时0.104秒,中间可执行96个指令周期。#defineucharunsignedcharsbitP1_0=0x90;sbitP1_1=0x91;sbitP1_2=0x92;#defineRXDP1_0#defineTXDP1_1#defineWRDYN44/写延时#defineRDDYN43/读延时/往串口写一个字节voidWByte(ucharinput)uchari=8

4、;TXD=(bit)0;/发送启始位Delay2cp(39);/发送8位数据位while(i-)TXD=(bit)(input&0x01);/先传低位Delay2cp(36);input=input1;/发送校验位(无)TXD=(bit)1;/发送结束位Delay2cp(46);/从串口读一个字节ucharRByte(void)ucharOutput=0;uchari=8;uchartemp=RDDYN;/发送8位数据位Delay2cp(RDDYN*1.5);/此处注意,等过起始位while(i-)Output=1;if(RXD)Output|=0x80;/先收低位Delay2cp(35);/

5、(96-26)/2,循环共占用26个指令周期while(-temp)/在指定的时间内搜寻结束位。Delay2cp(1);if(RXD)break;/收到结束位便退出returnOutput;/延时程序*voidDelay2cp(unsignedchari)while(-i);/刚好两个指令周期。此种方法在接收上存在一定的难度,主要是采样定位存在需较准确,另外还必须知道每条语句的指令周期数。此法可能模拟若干个串口,实际中采用它的人也很多,但如果你用KeilC,本人不建议使用此种方法,上述程序在P89C52、AT89C52、W78E52三种单片机上实验通过。方法二:计数法51的计数器在每指令周期加

6、1,直到溢出,同时硬件置溢出标志位。这样我们就可以通过预置初值的方法让机器每96个指令周期产生一次溢出,程序不断的查询溢出标志来决定是否发送或接收下一位。/计数器初始化voidS2INI(void)TMOD|=0x02;/计数器0,方式2TH0=0xA0;/预值为256-96=140,十六进制A0TL0=TH0;TR0=1;/开始计数TF0=0;voidWByte(ucharinput)/发送启始位uchari=8;TR0=1;TXD=(bit)0;WaitTF0();/发送8位数据位while(i-)TXD=(bit)(input&0x01);/先传低位WaitTF0();input=inp

7、ut1;/发送校验位(无)/发送结束位TXD=(bit)1;WaitTF0();TR0=0;/查询计数器溢出标志位voidWaitTF0(void)while(!TF0);TF0=0;接收的程序,可以参考下一种方法,不再写出。这种办法个人感觉不错,接收和发送都很准确,另外不需要计算每条语句的指令周期数。方法三:中断法中断的方法和计数器的方法差不多,只是当计算器溢出时便产生一次中断,用户可以在中断程序中置标志,程序不断的查询该标志来决定是否发送或接收下一位,当然程序中需对中断进行初始化,同时编写中断程序。本程序使用Timer0中断。#defineTM0_FLAGP1_2/设传输标志位/计数器及中

8、断初始化voidS2INI(void)TMOD|=0x02;/计数器0,方式2TH0=0xA0;/预值为256-96=140,十六进制A0TL0=TH0;TR0=0;/在发送或接收才开始使用TF0=0;ET0=1;/允许定时器0中断EA=1;/中断允许总开关/接收一个字符ucharRByte()ucharOutput=0;uchari=8;TR0=1;/启动Timer0TL0=TH0;WaitTF0();/等过起始位/发送8位数据位while(i-)Output=1;if(RXD)Output|=0x80;/先收低位WaitTF0();/位间延时while(!TM0_FLAG)if(RXD)b

9、reak;TR0=0;/停止Timer0returnOutput;/中断1处理程序voidIntTimer0()interrupt1TM0_FLAG=1;/设置标志位。/查询传输标志位voidWaitTF0(void)while(!TM0_FLAG);TM0_FLAG=0;/清标志位中断法也是我推荐的方法,和计数法大同小异。发送程序参考计数法,相信是件很容易的事。另外还需注明的是本文所说的串口就是通常的三线制异步通信串口(UART),只用RXD、TXD、GND。附:51 IO口模拟串口通讯C源程序(定时器计数法)#includesbitBT_SND=P10;sbitBT_REC=P11;/*I

10、O口模拟232通讯程序使用两种方式的C程序占用定时器0*/#defineMODE_QUICK#defineF_TMF0#defineTIMER0_ENABLETL0=TH0;TR0=1;#defineTIMER0_DISABLETR0=0;sbitACC0=ACC0;sbitACC1=ACC1;sbitACC2=ACC2;sbitACC3=ACC3;sbitACC4=ACC4;sbitACC5=ACC5;sbitACC6=ACC6;sbitACC7=ACC7;voidIntTimer0()interrupt1F_TM=1;/发送一个字符voidPSendChar(unsignedcharinc

11、h)#ifdefMODE_QUICKACC=inch;F_TM=0;BT_SND=0;/startbitTIMER0_ENABLE;/启动while(!F_TM);BT_SND=ACC0;/先送出低位F_TM=0;while(!F_TM);BT_SND=ACC1;F_TM=0;while(!F_TM);BT_SND=ACC2;F_TM=0;while(!F_TM);BT_SND=ACC3;F_TM=0;while(!F_TM);BT_SND=ACC4;F_TM=0;while(!F_TM);BT_SND=ACC5;F_TM=0;while(!F_TM);BT_SND=ACC6;F_TM=0;w

12、hile(!F_TM);BT_SND=ACC7;F_TM=0;while(!F_TM);BT_SND=1;F_TM=0;while(!F_TM);TIMER0_DISABLE;/停止timer#elseunsignedcharii;ii=0;F_TM=0;BT_SND=0;/startbitTIMER0_ENABLE;/启动while(!F_TM);while(ii=1;BT_SND=1;F_TM=0;while(!F_TM);#endifTIMER0_DISABLE;/停止timer/接收一个字符unsignedcharPGetChar()#ifdefMODE_QUICKTIMER0_ENA

13、BLE;F_TM=0;while(!F_TM);/等过起始位ACC0=BT_REC;TL0=TH0;F_TM=0;while(!F_TM);ACC1=BT_REC;F_TM=0;while(!F_TM);ACC2=BT_REC;F_TM=0;while(!F_TM);ACC3=BT_REC;F_TM=0;while(!F_TM);ACC4=BT_REC;F_TM=0;while(!F_TM);ACC5=BT_REC;F_TM=0;while(!F_TM);ACC6=BT_REC;F_TM=0;while(!F_TM);ACC7=BT_REC;F_TM=0;while(!F_TM)if(BT_R

14、EC)break;TIMER0_DISABLE;/停止timerreturnACC;#elseunsignedcharrch,ii;TIMER0_ENABLE;F_TM=0;ii=0;rch=0;while(!F_TM);/等过起始位while(ii=1;if(BT_REC)rch|=0x80;ii+;F_TM=0;while(!F_TM);F_TM=0;while(!F_TM)if(BT_REC)break;TIMER0_DISABLE;/停止timerreturnrch;#endif/检查是不是有起始位bitStartBitOn()return(BT_REC=0);voidmain()un

15、signedchargch;TMOD=0x22;/*定时器1为工作模式2(8位自动重装),0为模式2(8位自动重装)*/PCON=00;TR0=0;/在发送或接收才开始使用TF0=0;TH0=(256-96);/9600bps就是/9600=104.167微秒执行的timer是/104.167*11.0592/12=96TL0=TH0;ET0=1;EA=1;PSendChar(0x55);PSendChar(0xaa);PSendChar(0x00);PSendChar(0xff);while(1)if(StartBitOn()gch=PGetChar();PSendChar(gch);I2C

16、串行总线标准驱动程序(C51)-万能程序发布时间:2008年2月25日 16时0分/*-文件名 I2C.c版本 1.1b作者 鞠春阳最后修改时间 2003年5月12日版权所有 资料 请到下载=*/#include reg51.h#include intrins.hunsigned char SystemError;sbit SCL= P16; /定义串行时钟线所在口 使用时根据自己的需要来定义sbit SDA= P17; /定义串行数据线所在口 使用时根据自己的需要来定义#define SomeNOP(); _nop_();_nop_();_

17、nop_();_nop_();/*-调用方式:void AD7416_I2CStart(void) 2003/05/04函数说明:私有函数,I2C专用-*/void I2CStart(void)EA=0;SDA=1; SCL=1; SomeNOP();/数据线保持高,时钟线从高到低一次跳变,I2C通信开始SDA=0; SomeNOP(); SCL=0;/*-调用方式:void AD7416_I2CStop(void) 2003/05/04函数说明:私有函数,I2C专用-*/void I2CStop(void)SCL=0; SDA=0; SomeNOP(); /数据线保持低,时钟线从低到高一次跳

18、变,I2C通信停止SCL=1; SomeNOP(); SDA=1; EA=1;/*-调用方式:I2CAck(void) 2003/05/13函数说明:私有函数,I2C专用,等待从器件接收方的应答ACK BY AD7416-*/WaitAck(void)unsigned char errtime=255;/因故障接收方无ACK,超时值为255。SDA=1;SCL=1;SystemError=0x10; while(SDA) errtime-;if(!errtime) AD7416_I2CStop();AD7416_SystemError=0x11; /出错后给全局变量赋值return;SCL=0

19、; /*-调用方式:void SendAck(void) 2003/05/13函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,应答信号。-*/void SendAck(void)SDA=0; SomeNOP(); /数据线保持低,时钟线发生一次从高低的跳变 发送一个应答信号SCL=1; SomeNOP();SCL=0;/*-调用方式:void SendAck(void) 2003/05/13函数说明:私有函数,I2C专用,主器件为接收方,从器件为发送方时,非应答信号。-*/void SendNotAck(void)SDA=1; SomeNOP(); /数据线保持高,时钟线发生

20、一次从高低的跳变 没有应答SCL=1; SomeNOP();SCL=0;/*-调用方式:void I2CSend(uchar ch) 2003/05/13函数说明:私有函数,I2C专用-*/void I2CSendByte(Byte ch)unsigned char i=8;while (i-)SCL=0;_nop_();SDA=(bit)(ch&0x80); ch=1; SomeNOP(); /时钟保持低可以发送数据SCL=1; SomeNOP();SCL=0;/*-调用方式:uchar I2CReceive(void) 2003/05/13函数说明:私有函数,I2C专用-*/Byte I2

21、CReceiveByte(void)unsigned char i=8,data=0;SDA=1;while (i-)data=1;SCL=0;SomeNOP();SCL=1;SomeNOP(); /时钟做一次从低到高的跳变 可以接收数据data|=SDA;SCL=0;return data;标签: 电源mc34063中文MC34063 中文资料PDF及MC34063应用1. MC34063 DC/DC变换器控制电路简介:MC34063是一单片双极型线性集成电路,专用于直流-直流变换器控制部分。片内包含有温度补偿带隙基准源、一个占空比周期控制振荡器、驱动器和大电流输出开关,能输出1.5A的开关

22、电流。它能使用最少的外接元件构成开关式升压变换器、降压式变换器和电源反向器。特点:*能在3.0-40V的输入电压下工作*短路电流限制*低静态电流*输出开关电流可达1.5A(无外接三极管)*输出电压可调*工作振荡频率从100HZ到100KHZ2.MC34063引脚图及原理框图3 MC34063应用电路图: 3.1 MC34063大电流降压变换器电路3.2 MC34063大电流升压变换器电路3.3 MC34063反向变换器电路3.4 MC34063降压变换器电路3.5 MC34063升压变换器电路 = MC34063 电路原理 振荡器通过恒流源对外接在CT 管脚(3 脚)上的定时电容不断地充电和放

23、电以产生振荡波形。充电和放电电流都是恒定的,振荡频率仅取决于外接定时电容的容量。与门的C 输入端在振荡器对外充电时为高电平,D 输入端在比较器的输入电平低于阈值电平时为高电平。当C 和D输入端都变成高电平时触发器被置为高电平,输出开关管导通;反之当振荡器在放电期间,C 输入端为低电平,触发器被复位,使得输出开关管处于关闭状态。电流限制通过检测连接在VCC和5 脚之间电阻上的压降来完成功能。当检测到电阻上的电压降接近超过300 mV 时,电流限制电路开始工作,这时通过CT 管脚(3 脚) 对定时电容进行快速充电以减少充电时间和输出开关管的导通时间,结果是使得输出开关管的关闭时间延长。 带隔离输出的DC

温馨提示

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

评论

0/150

提交评论