标题:
51单片机_STC89C52_AT89S52_模拟串口收发数据程序(半双工)
[打印本页]
作者:
shushikuan
时间:
2021-6-8 17:12
标题:
51单片机_STC89C52_AT89S52_模拟串口收发数据程序(半双工)
本程序实现51单片机如STC89C52、AT89S52等单机模拟串口半双工收发数据,即接收数据时不能发送数据,发送数据时不能接收数据。
占用系统资源定时器1或定时器2、外部中断1。
当使用定时器1时,波特率固定为4800bps;当使用定时器2时,波特率在300~4800bps之间可调。
01.png
(47.98 KB, 下载次数: 73)
下载附件
2021-6-8 17:08 上传
02.png
(41.2 KB, 下载次数: 54)
下载附件
2021-6-8 17:08 上传
单片机源程序如下:
/************************************************************
* 名称: 51单片机模拟半双工串口收发数据
* CPU : STC89C52 @ 11.0592MHz
* IDE : KeilC51 UV4
* 作者 : 舒世宽
* 日期 : 2021-06-08
************************************************************/
#include "at89x52.h"
#define BAUD (4800) //波特率范围 300 ~ 4800
#define FOSC (11059200UL) //晶振频率
#define TMR_VAL (65536UL-FOSC/12/BAUD)
#define MYUART_TX_PIN P2_3 //可定义为除P3_3外的任意引脚
#define MYUART_RX_PIN P3_3 //因为使用了外部中断,所以必须为P3_3
#define MYUART_RX_BUF_LEN 20 //接收缓冲区长度
#define MYUART_RX_LED P1_0 //接收数据指示灯
#define MYUART_TX_LED P1_1 //发送数据指示灯
bit MYUART_TX_FLAG = 0; //发送模式
bit MYUART_RX_FLAG = 0; //接收模式
bit MYUART_TX_BYTE_DONE = 0; //发送完成一个字节
unsigned char sbufdata = 0;
unsigned char data_bit_i = 0;
unsigned char byte_i= 0;
unsigned char myuart_rxbuf[MYUART_RX_BUF_LEN] = {0};
void delay()
{
unsigned int i,j;
for(i=0;i<100;i++)
for(j=0;j<100;j++);
}
void myuart_init_time()
{
T2MOD = 0; //默认值
T2CON = 0; //默认为16位自动重装定时器
RCAP2L = TL2 = TMR_VAL; //设置定时初值低字节
RCAP2H = TH2 = TMR_VAL>>8; //设置定时初值高字节
TF2 = 0; //清除TF2标志
TR2 = 1; //定时器2停止计时
ET2 = 1; //允许定时器2中断
}
void myuart_init_recv()
{
//初始化外部中断1
IT1 = 1; // 1 --- 下降沿触发, 0 --- 低电平持续触发
EX1 = 1; // 开启外部中断1
}
//外部中断1处理程序
void isr_ext1(void) interrupt 2
{
unsigned char i;
if(MYUART_RX_PIN == 0)
{
for(i = 0;i<5;i++); //延时,软件滤波
if(MYUART_RX_PIN == 0)
{
EX1 = 0; //禁止外部分中断1
MYUART_RX_FLAG = 1;
sbufdata = 0;
data_bit_i = 0;
myuart_init_time();
}
}
}
void isr_timer2(void) interrupt 5
{
unsigned char tmp;
TF2 = 0; //定时器2中断标志必须由软件清零
//接收
if(MYUART_RX_FLAG == 1)
{
MYUART_RX_PIN = 1; //先置位,再读取数据
if(data_bit_i < 8){
if(1==MYUART_RX_PIN)sbufdata |= 1<<data_bit_i;
data_bit_i++;
MYUART_RX_LED = 0;
}else if(data_bit_i == 8 && MYUART_RX_PIN == 1){
myuart_rxbuf[byte_i++]=sbufdata;
byte_i %= MYUART_RX_BUF_LEN; //防止溢出接收缓冲区
TR2 = 0; //关闭定时器2
EX1 = 1; //允许外部分中断1
MYUART_RX_LED = 1;
MYUART_RX_FLAG = 0; //接收结束
MYUART_RX_PIN = 1; //置位,准备后面数据接收
}else{
TR2 = 0; //关闭定时器2
EX1 = 1; //允许外部分中断1
MYUART_RX_LED = 1;
MYUART_RX_FLAG = 0; //接收结束
MYUART_RX_PIN = 1; //置位,准备后面数据接收
}
}
//发送
if(MYUART_TX_FLAG == 1)
{
if(data_bit_i ==0){
MYUART_TX_PIN = 0; //拉低,发送起始位
MYUART_TX_LED = 0;
}else if(data_bit_i < 9){
tmp = sbufdata & (1<<(data_bit_i-1));//先发送低位再发送高位
if(tmp == 0)
MYUART_TX_PIN = 0;
else
MYUART_TX_PIN = 1;
}else if(data_bit_i < 12){ //连续3个停止位的时间
MYUART_TX_PIN = 1; //拉高,发送停止位
}else{
TR2 = 0;
RCAP2L = TL2 = TMR_VAL; //设置定时初值低字节
RCAP2H = TH2 = TMR_VAL>>8; //设置定时初值高字节
MYUART_TX_BYTE_DONE = 1; // 发送完成一个字节
MYUART_TX_LED = 1;
MYUART_TX_PIN = 1; //拉高,准备后面数据发送
}
data_bit_i++;
}
}
void myuart_write_byte(unsigned char dat)
{
data_bit_i = 0;
sbufdata = dat;
TR2 = 1; //启动定时器
MYUART_TX_BYTE_DONE = 0;
while(MYUART_TX_BYTE_DONE==0);
}
void myuartSendString(char * pstr)
{
if(*pstr)
{
MYUART_TX_FLAG = 1;
myuart_init_time();
while(*pstr)
{
myuart_write_byte(*pstr++);
}
MYUART_TX_FLAG = 0;
}
}
void myuartSendBuffer(unsigned char * pbuf,unsigned char len)
{
unsigned char i;
if(len>0)
{
MYUART_TX_FLAG = 1;
myuart_init_time();
for(i=0;i<len;i++)myuart_write_byte(pbuf[i]);
MYUART_TX_FLAG = 0;
}
}
void main(void)
{
int a,b,i;
MYUART_TX_PIN = 1;
MYUART_RX_PIN = 1;
EA = 1; //开启全局中断
myuart_init_recv(); //串口接收初始化
while(1){
delay();a = byte_i;
delay();b = byte_i;
if(a==b && a>0)
{
myuartSendBuffer(myuart_rxbuf,byte_i);
for(i=0;i<MYUART_RX_BUF_LEN;i++)myuart_rxbuf[i] = 0;
a=0;b=0;byte_i=0;
}
//myuartSendString("my uart demo test! shushikuan@163.com 12345 ok!!!!"); //50个字符
//myuartSendString("my uart demo test ok");
}
}
复制代码
以上代码51hei下载地址:
simuart.7z
(24.9 KB, 下载次数: 41)
2021-6-8 19:23 上传
点击文件名下载附件
51单片机_STC89C52_AT89S52_模拟串口收发数据(半双工)
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1