51单片机模拟串口的三种方法Word文档格式.docx

上传人:b****6 文档编号:20927565 上传时间:2023-01-26 格式:DOCX 页数:13 大小:17.73KB
下载 相关 举报
51单片机模拟串口的三种方法Word文档格式.docx_第1页
第1页 / 共13页
51单片机模拟串口的三种方法Word文档格式.docx_第2页
第2页 / 共13页
51单片机模拟串口的三种方法Word文档格式.docx_第3页
第3页 / 共13页
51单片机模拟串口的三种方法Word文档格式.docx_第4页
第4页 / 共13页
51单片机模拟串口的三种方法Word文档格式.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

51单片机模拟串口的三种方法Word文档格式.docx

《51单片机模拟串口的三种方法Word文档格式.docx》由会员分享,可在线阅读,更多相关《51单片机模拟串口的三种方法Word文档格式.docx(13页珍藏版)》请在冰豆网上搜索。

51单片机模拟串口的三种方法Word文档格式.docx

通过上述计算大家知道,串口的每位需延时秒,中间可执行96个指令周期。

#defineucharunsignedchar

sbitP1_0=0x90;

sbitP1_1=0x91;

sbitP1_2=0x92;

#defineRXDP1_0

#defineTXDP1_1

#defineWRDYN44//写延时

#defineRDDYN43//读延时

//往串口写一个字节

voidWByte(ucharinput)

{

uchari=8;

TXD=(bit)0;

//发送启始

Delay2cp(39);

//发送8位数据位

while(i--)

{

TXD=(bit)(input&

0x01);

//先传低位

Delay2cp(36);

input=input>

>

1;

}

//发送校验位(无)

TXD=(bit)1;

//发送结束

Delay2cp(46);

}

//从串口读一个字节

ucharRByte(void)

ucharOutput=0;

uchartemp=RDDYN;

Delay2cp(RDDYN*;

//此处注意,等过起始位

Output>

=1;

if(RXD)Output|=0x80;

//先收低位

Delay2cp(35);

//(96-26)/2,循环共

占用26个指令周期

while(--temp)//在指定的

时间内搜寻结束位。

Delay2cp

(1);

if(RXD)break;

//收到结束位便退出

returnOutput;

//延时程序*

voidDelay2cp(unsignedchari)

while(--i);

//刚好两个

指令周期。

此种方法在接收上存在一定的难度,主要是采样定位存在需较准确,另外还必须知道

每条语句的指令周期数。

此法可能模拟若干个串口,实际中采用它的人也很多,但如果你用Keil

C,本人不建议使用此种方法,上述程序在P89C52、AT89C52、W78E52三种单片机上实验通过。

方法二:

计数法

51的计数器在每指令周期加1,直到溢出,同时硬件置溢出标志位。

这样我们就可以

通过预置初值的方法让机器每96个指令周期产生一次溢出,程序不断的查询溢出标志来决定是否

发送或接收下一位。

//计数器初始化

voidS2INI(void)

TMOD|=0x02;

//计数器0,方式2

TH0=0xA0;

//预值为256-96=140,十六进制A0

TL0=TH0;

TR0=1;

//开始计数

TF0=0;

//发送启始位

WaitTF0();

//发送结束位

TR0=0;

}

//查询计数器溢出标志位

voidWaitTF0(void)

while(!

TF0);

接收的程序,可以参考下一种方法,不再写出。

这种办法个人感觉不错,接收和发送

都很准确,另外不需要计算每条语句的指令周期数。

方法三:

中断法

中断的方法和计数器的方法差不多,只是当计算器溢出时便产生一次中断,用户可以

在中断程序中置标志,程序不断的查询该标志来决定是否发送或接收下一位,当然程序中需对中

断进行初始化,同时编写中断程序。

本程序使用Timer0中断。

#defineTM0_FLAGP1_2//设传输标志位

//计数器及中断初始化

//在发送或

接收才开始使用

ET0=1;

//允许定时

器0中断

EA=1;

//中断允许

总开关

//接收一个字符

ucharRByte()

TR0=1;

//启动Timer0

TL0=TH0;

//等过起始

WaitTF0();

//位间延时

TM0_FLAG)if(RXD)break;

//停止

Timer0

//中断1处理程序

voidIntTimer0()interrupt1

TM0_FLAG=1;

//设置标志位。

//查询传输标志位

while(!

TM0_FLAG);

TM0_FLAG=0;

//清标志位

中断法也是我推荐的方法,和计数法大同小异。

发送程序参考计数法,相信是件很容

易的事。

另外还需注明的是本文所说的串口就是通常的三线制异步通信串口(UART),只用RXD、TXD、

GND。

附:

51IO口模拟串口通讯C源程序(定时器计数法)

#include

sbitBT_SND=P1^0;

sbitBT_REC=P1^1;

/**********************************************

IO口模拟232通讯程序

使用两种方式的C程序占用定时器0

**********************************************/

#defineMODE_QUICK

#defineF_TMF0

#defineTIMER0_ENABLETL0=TH0;

#defineTIMER0_DISABLETR0=0;

sbitACC0=ACC^0;

sbitACC1=ACC^1;

sbitACC2=ACC^2;

sbitACC3=ACC^3;

sbitACC4=ACC^4;

sbitACC5=ACC^5;

sbitACC6=ACC^6;

sbitACC7=ACC^7;

F_TM=1;

//发送一个字符

voidPSendChar(unsignedcharinch)

#ifdefMODE_QUICK

ACC=inch;

F_TM=0;

BT_SND=0;

//startbit

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;

BT_SND=1;

 

TIMER0_DISABLE;

//停止timer

#else

unsignedcharii;

ii=0;

while(ii<

8)

if(inch&

1)

else

ii++;

inch>

#endif

unsignedcharPGetChar()

//等过起始位

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)

break;

returnACC;

unsignedcharrch,ii;

rch=0;

rch>

rch|=0x80;

returnrch;

//检查是不是有起始位

bitStartBitOn()

return(BT_REC==0);

voidmain()

unsignedchargch;

TMOD=0x22;

/*定时器1为工作模式2(8位自动重装),0为模式2(8位

自动重装)*/

PCON=00;

TR0=0;

//在发送或接收才开始使用

TF0=0;

TH0=(256-96);

//9600bps就是1000000/9600=微秒执行的

timer是

//

*12=96

ET0=1;

EA=1;

PSendChar(0x55);

PSendChar(0xaa);

PSendChar(0x00);

PSendChar(0xff);

while

(1)

if(StartBitOn())

gch=PGetChar();

PSendChar(gch);

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 其它

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1