?? 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 + -