📄 uart.c
字号:
/* 软件模拟串口测试程序*/
/* 该软件模拟串口主要用于半双工通讯,波特率为9600,或4800或2400或1200
使用定时器0为波特率发生器器,使用INT0为RXD,平时通过TXD检测起始位的下降沿
检测到下降沿后启动接受波特率发生器器接受8位数据及一个停止位,然后又处于接受
模式等待起始位,如不能正常接受到停止位,则停止接受直到接受到停止位为止,
本串口*/
/* 2005年7月16日,曾任义*/
#include <reg52.h>
typedef unsigned char uchar;
#define true 1
#define false 0
#define SEND 1
#define RECEIVE 0
#define B9600 0xf3
#define B9600B 0x30
#define TIME2H_10 0Xb1 /* 0Xb1e0 10MS 24M 晶振*/
#define TIME2L_10 0Xe0
uchar bdata SendBuf;
sbit SendBuf_LSB = SendBuf^0;
uchar bdata RecBuf;
sbit RecBuf_LSB = RecBuf^0;
sbit RecBuf_MSB = RecBuf^7;
bit write_read; /* 模拟串口发送或接受标志,1为发送,0为接受*/
sbit SendPort = P3^1;
sbit RecPort = P3^2;
sbit TXEN = P1^6; /* 发送控制端*/
sbit workled = P3^5;
bit SendINT; /* 发送中断*/
bit RecINT; /* 接受中断*/
bit RecError; /* 结束出错,未接受到停止位*/
bit Time_flag;
uchar count; /* 发送或接受计数器*/
uchar ledcount;
uchar ReadData;
void Int_Open();
void Init_Sys();
void Init_Time();
void SendData(uchar buf);
bit Mscom_Open(uchar Baud,uchar port);
//-------------------------------------------------------------
void main()
{
Init_Sys();
Int_Open();
//Mscom_Open(B9600,1);
Mscom_Open(B9600B,2);
while(1)
{
if(Time_flag)
{
Time_flag=0;
ledcount++;
if(ledcount>=100)
{
ledcount=0;
//workled = ~workled;
}
//SendData(0x55);
}
if(RecINT)
{
RecINT=0;
SendData(ReadData);
}
if(RecError) /* 发生了接受错误*/
{
if(RecPort)/* 检查接受总线*/
{
RecError=false;
EX0 = true;
}
}
}
}
//---------------------------------------------------------------
void Init_Sys()
{
TXEN = false; /* 接受模式*/
Init_Time();
}
//---------------------------------------------------------------
void Int_Open()
{
PT0 = true;
IT0=true; /* 设置EX0为边沿触发*/
EX0 = true;
ET2 = true;
ET0 = true;
EA = true;
}
//---------------------------------------------------------------
void Init_Time()
{
TMOD = 0x22; /* 定时器1,2都设置为工作方式2,自动重装8位*/
RCAP2H=TIME2H_10;
RCAP2L=TIME2L_10; /* 定时器0,2 赋初值*/
TH2=RCAP2H; /* 设置定时器2的定时时间*/
TL2=RCAP2L;
T2CON=0x00; /* 设置定时器2的工作模式*/
TR2 = true;
}
//---------------------------------------------------------------
bit Mscom_Open(uchar Baud,uchar port)
{
bit res=0;
if(port==1) /* 打开1号串口*/
{
TH1 = Baud;
SCON = 0x50;
PCON = 0x80;
TR1=true;
res=1;
}
else if(port==2) /* 打开2号串口*/
{
TH0 = Baud;
res=1;
}
return res;
}
//---------------------------------------------------------------
void SendData(uchar buf)
{
TXEN=true; /* 发送模式*/
SendBuf = buf;
count=0;
write_read = SEND;
EX0=false;
TR0 = true; /* 启动发送*/
}
/***************************************************************/
/* 定时器2中断,用于产生基数为1毫秒的可变定时时钟信号,用于超时及延时处理*/
/* 自动重装*/
void int_time2() interrupt 5
{
TF2 = false;
Time_flag=true;
}
//--------------------------------------------------------------
// 定时器0即模拟串口位发送或接受中断
void Serial2_int() interrupt 1
{
if(write_read) /* 为发送中断*/
{
if(count==0)
{
SendPort=0;
count++;
}
else if(count<11) /* 发送数据位和2个停止位*/
{
SendPort = SendBuf_LSB;
SendBuf >>= 1;
SendBuf |= 0x80;
count++;
}
else
{
TR0 = false;
TXEN = false; /* 接受模式*/
EX0=true; /* 准备接受*/
SendINT = 1; /* 置发送中断*/
}
}
else /* 接受位中断*/
{
if(count==0) /* 接受起始位*/
{
if(RecPort) /* 判断是否接受到错误的起始位*/
{
TR0 = false; /* 停止接受*/
EX0 = true; /* 等待起始位*/
}
else count=1; /* 接受数据位*/
}
else if(count<9) /* 接受8位数据*/
{
RecBuf >>=1;
RecBuf_MSB = RecPort;
count++;
}
else if(count==9) /* 接受停止位*/
{
if(RecPort) /* 判断是否为停止位*/
{
workled=1;
ReadData = RecBuf;
TR0 = false;
EX0 = true; /* 准备接受下一个起始位*/
RecINT = 1; /* 置发送中断*/
}
else
{
TR0 = false;
RecError=1; /* 接受错误*/
}
}
}
}
//---------------------------------------------------------------
// 串口接受起始中断
void ReceiveStart_int() interrupt 0
{
if(INT0 == false)
{
TL0=0x9c; /* 起始位检查时间*/
TR0 = true; /* 开始接受*/
write_read=false; /* 开始接受*/
count=0;
EX0=false;
workled=0;
}
}
//---------------------------------------------------------------
// program end
//---------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -