|
本帖最后由 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;
//----------------------------------------------------------
// 函数名称 RS232_Init()
// 函数功能 串口初始化,设置默认通信速率为9600bps
// 单片机主振频率11.0592MHz,主频为其它值时
// 通信速率按比例变化。
// 入口参数:无
// 函数返回:无
// 函数引用:无
// 变量引用:无
// 变量修改:TMOD:设置T1为串口波特率发生器
// TH1,TL1:设置波特率为9600bps(以11.0592MHz晶体为基准)
// TR1,RI,TI:启动T2,清除TI、RI标志
// REN,SM0,SM1:使能串口接收,1位起始8位数据1位停止模式
// ES,EA:使能串口中断,使能总中断
// RS232_Trn_flag:设置发送完成标志
// 函数作者:周大苟
// 创建时间:10/01/2009
// 修改历程:10/01/2009:创建本函数
// 10/29/2009:格式规范
//----------------------------------------------------------
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;
}
//----------------------------------------------------------
// 函数名称:RS232_ISR()
// 函数功能:串口中断服务函数
// 入口参数:无
// 函数返回:无
// 函数引用:无
// 变量引用:RI:串口接收标志
// SBUF:串口接收缓冲寄存器
// 变量修改:RI,TI:清除TI、RI标志
// RS232_Rec:接收串口收到的字节
// RS232_Rec_flag:设置成功接收标志
// RS232_Trn_flag:设置发送完成标志
// 函数作者:周大苟
// 创建时间:10/01/2009
// 修改历程:10/01/2009:创建本函数
// 10/29/2009:格式规范
//----------------------------------------------------------
void RS232_ISR(void) interrupt 4
{
if(RI)
{
RS232_Rec = SBUF;
RS232_Rec_flag = 1;
}
else RS232_Trn_flag = 1;
RI = 0;
TI = 0;
}
//----------------------------------------------------------
// 函数名称:RS232_Tran_Chr(...)
// 函数功能:串口单个字符发送函数
// 入口参数:chr:待发送的字符
// 函数返回:无
// 函数引用:无
// 变量引用:RS232_Trn_flag,自定义串口发送成功标志
// 变量修改:
// SBUF:赋值串口发送缓冲寄存器
// RS232_Trn_flag:清除自定义串口发送成功标志
// 函数作者:周大苟
// 创建时间:10/01/2009
// 修改历程:10/01/2009:创建本函数
// 10/29/2009:格式规范,解决发送偶尔死循环不返回问题
//----------------------------------------------------------
void RS232_Tran_Chr(uchar chr)
{
uint tryit = 5000;
while((!RS232_Trn_flag) && (tryit--)) ;
RS232_Trn_flag = 0;
SBUF = chr;
}
//----------------------------------------------------------
// 函数名称:RS232_Rec_Xmodem()
// 函数功能:Xmodem协议接收部分,128字节缓冲区
// 入口参数:无
// 函数返回:无
// 函数引用:RS232_Tran_Chr(...)
// 变量引用:RS232_Rec_flag:串口收到字符的标志
// RS232_Rec:串口收到的字符
// Xmodem_Buffer[]:Xmodem接收缓冲区
// Xmodem_Buffer_Ptr:Xmodem缓冲区指针
// 变量修改:RS232_Rec_flag:串口收到字符的标志
// Xmodem_Buffer_Ptr:Xmodem缓冲区指针
// Xmodem_Buffer[]:环形缓冲区
// 函数作者:周大苟
// 创建时间:10/01/2009
// 修改历程:10/01/2009:创建本函数
// 10/29/2009:格式规范
// 11/09/2009:修改原因:在包头部分发现错误,不应该立即发NAK,而是应该等这个包收完了再发NAK
// 即将修改:接收过程中应做延时检查,防止断线进入死循环。
//----------------------------------------------------------
// #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: //当前正等待接收主机发送起始符号SOH
if(RS232_Rec == SOH) //收到主机发送的SOH符号
{
Xmoden_STate = START; //进入"SOH已经收到"状态
xerror=0;
}
else
if(RS232_Rec == EOT) //收到主机发送的EOT符号
{
RS232_Tran_Chr(ACK);
Xmoden_STate = IDLE; //进入"空闲"状态
}
break;
case START://SOH已经收到,当前正等待接收期望的包序列号
Xmoden_STate = SEQ; //进入"序列号已经收到"状态
if(RS232_Rec != PSer) //不是期望的包序列号
xerror=1; //设置出错标志
break;
case SEQ: //包号已经收到,当前正等待接收包号补码
Xmoden_STate = CSEQ; //进入"包号补码已收"状态
if(RS232_Rec != (0xff-PSer)) //不是期望的包号补码
xerror=1; //设置出错标志
break;
case CSEQ: //包号补码已经收到,当前正等待接收数据
Xmodem_Buffer[0] = RS232_Rec;
ChkSum = RS232_Rec;
Xmodem_Buffer_Ptr = 1;
Xmoden_STate = DATA;
break;
case DATA: //当前正等待接收数据
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: //数据包接收结束,当前正等待接收校验和
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); //要求主机重发SOH符号
Xmoden_STate = WSTART;//回到"等待接收SOH"状态
}
break;
default:break;
}
RS232_Rec_flag = 0;
}
}
//本函数的调用方式如下:
// Xmoden_STate = WSTART;
// RS232_Tran_Chr(NAK);
// while(Xmoden_STate != IDLE) RS232_Rec_Xmodem();
//需要进一步完善/优化。已经成功用于PC--->51单片机管理下的2M字节串行Flash芯片AT45DB161D下载16点阵汉字库。
//每个包都人为设置多个错误,测试通过
|
|