⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uart.c

📁 软件利用单片机内部的定时器及IO端口实现异步串口
💻 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 + -