|
本帖最后由 niuniu 于 2015-3-25 00:13 編輯
#include "..\include\AT89X52.H"
#include "..\include\rs232.h"
uchar RS232_Rec;
static bit RS232_Rec_flag=0;
static bit RS232_Trn_flag=1;
//----------------------------------------------------------
// 函數(shù)名稱 RS232_Init()
// 函數(shù)功能 串口初始化,設置默認通信速率為9600bps
// 單片機主振頻率11.0592MHz,主頻為其它值時
// 通信速率按比例變化。
// 入口參數(shù):無
// 函數(shù)返回:無
// 函數(shù)引用:無
// 變量引用:無
// 變量修改:TMOD:設置T1為串口波特率發(fā)生器
// TH1,TL1:設置波特率為9600bps(以11.0592MHz晶體為基準)
// TR1,RI,TI:啟動T2,清除TI、RI標志
// REN,SM0,SM1:使能串口接收,1位起始8位數(shù)據(jù)1位停止模式
// ES,EA:使能串口中斷,使能總中斷
// RS232_Trn_flag:設置發(fā)送完成標志
// 函數(shù)作者:周大茍
// 創(chuàng)建時間:10/01/2009
// 修改歷程:10/01/2009:創(chuàng)建本函數(shù)
// 10/29/2009:格式規(guī)范
//----------------------------------------------------------
void RS232_Init(void)
{
uchar i;
RS232_Trn_flag = 1;
TMOD &= 0x0f;
TMOD |= 0x20;
TH1 = 0xfd;
TL1 = 0xfd;
TR1 = 1;
REN = 1;
SM0 = 0;
SM1 = 1;
RI = 0;
TI = 0;
EA = 1;
ES = 1;
}
//----------------------------------------------------------
// 函數(shù)名稱:RS232_ISR()
// 函數(shù)功能:串口中斷服務函數(shù)
// 入口參數(shù):無
// 函數(shù)返回:無
// 函數(shù)引用:無
// 變量引用:RI:串口接收標志
// SBUF:串口接收緩沖寄存器
// 變量修改:RI,TI:清除TI、RI標志
// RS232_Rec:接收串口收到的字節(jié)
// RS232_Rec_flag:設置成功接收標志
// RS232_Trn_flag:設置發(fā)送完成標志
// 函數(shù)作者:周大茍
// 創(chuàng)建時間:10/01/2009
// 修改歷程:10/01/2009:創(chuàng)建本函數(shù)
// 10/29/2009:格式規(guī)范
//----------------------------------------------------------
void RS232_ISR(void) interrupt 4
{
if(RI)
{
RS232_Rec = SBUF;
RS232_Rec_flag = 1;
}
else RS232_Trn_flag = 1;
RI = 0;
TI = 0;
}
//----------------------------------------------------------
// 函數(shù)名稱:RS232_Tran_Chr(...)
// 函數(shù)功能:串口單個字符發(fā)送函數(shù)
// 入口參數(shù):chr:待發(fā)送的字符
// 函數(shù)返回:無
// 函數(shù)引用:無
// 變量引用:RS232_Trn_flag,自定義串口發(fā)送成功標志
// 變量修改:
// SBUF:賦值串口發(fā)送緩沖寄存器
// RS232_Trn_flag:清除自定義串口發(fā)送成功標志
// 函數(shù)作者:周大茍
// 創(chuàng)建時間:10/01/2009
// 修改歷程:10/01/2009:創(chuàng)建本函數(shù)
// 10/29/2009:格式規(guī)范,解決發(fā)送偶爾死循環(huán)不返回問題
//----------------------------------------------------------
void RS232_Tran_Chr(uchar chr)
{
uint tryit = 5000;
while((!RS232_Trn_flag) && (tryit--)) ;
RS232_Trn_flag = 0;
SBUF = chr;
}
//----------------------------------------------------------
// 函數(shù)名稱:RS232_Rec_Xmodem()
// 函數(shù)功能:Xmodem協(xié)議接收部分,128字節(jié)緩沖區(qū)
// 入口參數(shù):無
// 函數(shù)返回:無
// 函數(shù)引用:RS232_Tran_Chr(...)
// 變量引用:RS232_Rec_flag:串口收到字符的標志
// RS232_Rec:串口收到的字符
// Xmodem_Buffer[]:Xmodem接收緩沖區(qū)
// Xmodem_Buffer_Ptr:Xmodem緩沖區(qū)指針
// 變量修改:RS232_Rec_flag:串口收到字符的標志
// Xmodem_Buffer_Ptr:Xmodem緩沖區(qū)指針
// Xmodem_Buffer[]:環(huán)形緩沖區(qū)
// 函數(shù)作者:周大茍
// 創(chuàng)建時間:10/01/2009
// 修改歷程:10/01/2009:創(chuàng)建本函數(shù)
// 10/29/2009:格式規(guī)范
// 11/09/2009:修改原因:在包頭部分發(fā)現(xiàn)錯誤,不應該立即發(fā)NAK,而是應該等這個包收完了再發(fā)NAK
// 即將修改:接收過程中應做延時檢查,防止斷線進入死循環(huán)。
//----------------------------------------------------------
// #define SOH 0x01
// #define STX 0x02
// #define EOT 0x04
// #define ACK 0x06
// #define NAK 0x15
// #define CAN 0x18
// #define CTRLZ 0x1A
//enum TXmoden_STate {IDLE, WSTART, START, SEQ, CSEQ, DATA, DEND};
enum TXmoden_STate Xmoden_STate = IDLE;
xdata uchar Xmodem_Buffer[128];
uchar Xmodem_Buffer_Ptr=0;
uchar ChkSum=0;
uchar PSer=1, PT=0;
uchar xerror;
void RS232_Rec_Xmodem(void)
{
if(Xmoden_STate == IDLE) return;
if(RS232_Rec_flag)
{
switch(Xmoden_STate)
{
case WSTART: //當前正等待接收主機發(fā)送起始符號SOH
if(RS232_Rec == SOH) //收到主機發(fā)送的SOH符號
{
Xmoden_STate = START; //進入"SOH已經(jīng)收到"狀態(tài)
xerror=0;
}
else
if(RS232_Rec == EOT) //收到主機發(fā)送的EOT符號
{
RS232_Tran_Chr(ACK);
Xmoden_STate = IDLE; //進入"空閑"狀態(tài)
}
break;
case START://SOH已經(jīng)收到,當前正等待接收期望的包序列號
Xmoden_STate = SEQ; //進入"序列號已經(jīng)收到"狀態(tài)
if(RS232_Rec != PSer) //不是期望的包序列號
xerror=1; //設置出錯標志
break;
case SEQ: //包號已經(jīng)收到,當前正等待接收包號補碼
Xmoden_STate = CSEQ; //進入"包號補碼已收"狀態(tài)
if(RS232_Rec != (0xff-PSer)) //不是期望的包號補碼
xerror=1; //設置出錯標志
break;
case CSEQ: //包號補碼已經(jīng)收到,當前正等待接收數(shù)據(jù)
Xmodem_Buffer[0] = RS232_Rec;
ChkSum = RS232_Rec;
Xmodem_Buffer_Ptr = 1;
Xmoden_STate = DATA;
break;
case DATA: //當前正等待接收數(shù)據(jù)
if(Xmodem_Buffer_Ptr<128)
{
Xmodem_Buffer[Xmodem_Buffer_Ptr++] = RS232_Rec;
ChkSum += RS232_Rec;
if(Xmodem_Buffer_Ptr==128)
Xmoden_STate = DEND;
}
break;
case DEND: //數(shù)據(jù)包接收結(jié)束,當前正等待接收校驗和
if((ChkSum == RS232_Rec)&&(xerror==0))
{
KS108_Disp_uint_Dec(0,0,PSer,0);
Flash_Write(((ulong)(PSer-1+(PT<<8))<<7), Xmodem_Buffer, 128);
PSer++;
if(PSer==0) PT++;
RS232_Tran_Chr(ACK); //給主機正確應答
Xmoden_STate = WSTART;
}
else
{
RS232_Tran_Chr(NAK); //要求主機重發(fā)SOH符號
Xmoden_STate = WSTART;//回到"等待接收SOH"狀態(tài)
}
break;
default:break;
}
RS232_Rec_flag = 0;
}
}
//本函數(shù)的調(diào)用方式如下:
// Xmoden_STate = WSTART;
// RS232_Tran_Chr(NAK);
// while(Xmoden_STate != IDLE) RS232_Rec_Xmodem();
//需要進一步完善/優(yōu)化。已經(jīng)成功用于PC--->51單片機管理下的2M字節(jié)串行Flash芯片AT45DB161D下載16點陣漢字庫。
//每個包都人為設置多個錯誤,測試通過
|
|