51模拟串口Word文档格式.docx
《51模拟串口Word文档格式.docx》由会员分享,可在线阅读,更多相关《51模拟串口Word文档格式.docx(21页珍藏版)》请在冰豆网上搜索。
别的晶振频率大家自已去算吧。
现在就以11.0592M的晶振为例,谈谈三种模拟串口的方法。
方法一:
延时法
通过上述计算大家知道,串口的每位需延时0.104秒,中间可执行96个指令周期。
#define
uchar
unsigned
char
sbit
P1_0
=
0x90;
P1_1
0x91;
P1_2
0x92;
RXD
P1_0
TXD
P1_1
WRDYN
44
//写延时
RDDYN
43
//读延时
//往串口写一个字节
void
WByte(uchar
input)
{
i=8;
TXD=(bit)0;
//发送启始
位
Delay2cp(39);
//发送8位数据位
while(i--)
TXD=(bit)(input&
0x01);
//先传低位
Delay2cp(36);
input=input>
>
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;
//收到结束位便退出
return
Output;
//延时程序*
Delay2cp(unsigned
char
i)
while(--i);
//刚好两个
指令周期。
此种方法在接收上存在一定的难度,主要是采样定位存在需较准确,另外还必须知道
每条语句的指令周期数。
此法可能模拟若干个串口,实际中采用它的人也很多,但如果你用Keil
C,本人不建议使用此种方法,上述程序在P89C52、AT89C52、W78E52三种单片机上实验通过。
方法二:
计数法
51的计数器在每指令周期加1,直到溢出,同时硬件置溢出标志位。
这样我们就可以
通过预置初值的方法让机器每96个指令周期产生一次溢出,程序不断的查询溢出标志来决定是否
发送或接收下一位。
//计数器初始化
S2INI(void)
TMOD
|=0x02;
//计数器0,方式2
TH0=0xA0;
//预值为256-96=140,十六进制A0
TL0=TH0;
TR0=1;
//开始计数
TF0=0;
//发送启始位
WaitTF0();
//发送结束位
TR0=0;
}
//查询计数器溢出标志位
WaitTF0(
)
while(!
TF0);
接收的程序,可以参考下一种方法,不再写出。
这种办法个人感觉不错,接收和发送
都很准确,另外不需要计算每条语句的指令周期数。
方法三:
中断法
中断的方法和计数器的方法差不多,只是当计算器溢出时便产生一次中断,用户可以
在中断程序中置标志,程序不断的查询该标志来决定是否发送或接收下一位,当然程序中需对中
断进行初始化,同时编写中断程序。
本程序使用Timer0中断。
TM0_FLAG
//设传输标志位
//计数器及中断初始化
//在发送或
接收才开始使用
ET0=1;
//允许定时
器0中断
EA=1;
//中断允许
总开关
//接收一个字符
RByte()
//启动Timer0
//等过起始
//位间延时
TM0_FLAG)
break;
//停止
Timer0
//中断1处理程序
IntTimer0()
interrupt
1
TM0_FLAG=1;
//设置标志位。
//查询传输标志位
TM0_FLAG);
TM0_FLAG=0;
//清标志位
中断法也是我推荐的方法,和计数法大同小异。
发送程序参考计数法,相信是件很容
易的事。
另外还需注明的是本文所说的串口就是通常的三线制异步通信串口(UART),只用RXD、TXD、
GND。
附:
51IO口模拟串口通讯C源程序(定时器计数法)
#include
BT_SND
=P1^0;
BT_REC
=P1^1;
/**********************************************
IO
口模拟232通讯程序
使用两种方式的C程序
占用定时器0
**********************************************/
MODE_QUICK
F_TM
F0
TIMER0_ENABLE
TIMER0_DISABLE
ACC0=
ACC^0;
ACC1=
ACC^1;
ACC2=
ACC^2;
ACC3=
ACC^3;
ACC4=
ACC^4;
ACC5=
ACC^5;
ACC6=
ACC^6;
ACC7=
ACC^7;
F_TM=1;
//发送一个字符
PSendChar(unsigned
inch)
#ifdef
ACC=inch;
F_TM=0;
BT_SND=0;
//start
bit
TIMER0_ENABLE;
//启动
F_TM);
BT_SND=ACC0;
//先送出低位
BT_SND=ACC1;
BT_SND=ACC2;
BT_SND=ACC3;
BT_SND=ACC4;
BT_SND=ACC5;
BT_SND=ACC6;
BT_SND=ACC7;