1、现在就以11.0592M的晶振为例,谈谈三种模拟串口的方法。方法一:延时法通过上述计算大家知道,串口的每位需延时0.104秒,中间可执行96个指令周期。#defineucharunsignedcharsbitP1_0=0x90;P1_10x91;P1_20x92;RXDP1_0TXDP1_1WRDYN44/写延时RDDYN43/读延时/往串口写一个字节voidWByte(ucharinput)i=8;TXD=(bit)0;/发送启始位Delay2cp(39);/发送8位数据位while(i-)TXD=(bit)(input&0x01);/先传低位Delay2cp(36);input=input
2、1;/发送校验位(无)TXD=(bit)1;/发送结束Delay2cp(46);/从串口读一个字节RByte(void)Output=0;temp=RDDYN;Delay2cp(RDDYN*1.5);/此处注意,等过起始位Output=1;if(RXD)|=0x80;/先收低位Delay2cp(35);/(96-26)/2,循环共占用26个指令周期while(-temp)/在指定的时间内搜寻结束位。Delay2cp(1);if(RXD)break;/收到结束位便退出returnOutput;/延时程序*Delay2cp(unsignedchari)while(-i);/刚好两个指令周期。此种方
3、法在接收上存在一定的难度,主要是采样定位存在需较准确,另外还必须知道每条语句的指令周期数。此法可能模拟若干个串口,实际中采用它的人也很多,但如果你用KeilC,本人不建议使用此种方法,上述程序在P89C52、AT89C52、W78E52三种单片机上实验通过。方法二:计数法51的计数器在每指令周期加1,直到溢出,同时硬件置溢出标志位。这样我们就可以通过预置初值的方法让机器每96个指令周期产生一次溢出,程序不断的查询溢出标志来决定是否发送或接收下一位。/计数器初始化S2INI(void)TMOD|=0x02;/计数器0,方式2TH0=0xA0;/预值为256-96=140,十六进制A0TL0=TH
4、0;TR0=1;/开始计数TF0=0;/发送启始位WaitTF0();/发送结束位TR0=0;/查询计数器溢出标志位WaitTF0()while(!TF0);接收的程序,可以参考下一种方法,不再写出。这种办法个人感觉不错,接收和发送都很准确,另外不需要计算每条语句的指令周期数。方法三:中断法中断的方法和计数器的方法差不多,只是当计算器溢出时便产生一次中断,用户可以在中断程序中置标志,程序不断的查询该标志来决定是否发送或接收下一位,当然程序中需对中断进行初始化,同时编写中断程序。本程序使用Timer0中断。TM0_FLAG/设传输标志位/计数器及中断初始化/在发送或接收才开始使用ET0=1;/允
5、许定时器0中断EA=1;/中断允许总开关/接收一个字符RByte()/启动Timer0/等过起始/位间延时TM0_FLAG)break;/停止Timer0/中断1处理程序IntTimer0()interrupt1TM0_FLAG=1;/设置标志位。/查询传输标志位TM0_FLAG);TM0_FLAG=0;/清标志位中断法也是我推荐的方法,和计数法大同小异。发送程序参考计数法,相信是件很容易的事。另外还需注明的是本文所说的串口就是通常的三线制异步通信串口(UART),只用RXD、TXD、GND。附:51 IO口模拟串口通讯C源程序(定时器计数法)i ncludeBT_SND=P10;BT_REC
6、=P11;/*IO口模拟232通讯程序使用两种方式的C程序占用定时器0*/MODE_QUICKF_TMF0TIMER0_ENABLETIMER0_DISABLEACC0=ACC0;ACC1=ACC1;ACC2=ACC2;ACC3=ACC3;ACC4=ACC4;ACC5=ACC5;ACC6=ACC6;ACC7=ACC7;F_TM=1;/发送一个字符PSendChar(unsignedinch)#ifdefACC=inch;F_TM=0;BT_SND=0;/startbitTIMER0_ENABLE;/启动F_TM);BT_SND=ACC0;/先送出低位BT_SND=ACC1;BT_SND=ACC
7、2;BT_SND=ACC3;BT_SND=ACC4;BT_SND=ACC5;BT_SND=ACC6;BT_SND=ACC7;BT_SND=1;TIMER0_DISABLE;/停止timer#elseii;ii=0;while(ii#endifPGetChar()/等过起始位ACC0=BT_REC;ACC1=BT_REC;ACC2=BT_REC;ACC3=BT_REC;ACC4=BT_REC;ACC5=BT_REC;ACC6=BT_REC;ACC7=BT_REC;F_TM)if(BT_REC)ACC;rch,ii;rch=0;rchrch|=0x80;rch;/检查是不是有起始位bitStartBitOn()(BT_REC=0);main()gch;TMOD=0x22;/*定时器1为工作模式2(8位自动重装),0为模式2(8位自动重装)*/PCON=00;/在发送或接收才开始使用TH0=(256-96);/9600bps就是1000000/9600=104.167微秒执行的timer是/104.167*11.0592/12=96PSendChar(0x55);PSendChar(0xaa);PSendChar(0x00);PSendChar(0xff);while(1)if(StartBitOn()gch=PGetChar();PSendChar(gch);
copyright@ 2008-2023 冰点文库 网站版权所有
经营许可证编号:鄂ICP备19020893号-2