📄 io_com.c
字号:
/*****************************************************/
/* 虚拟串口通讯程序 */
/* MCU 型号: Winbond STC89C516RD+ */
/* 开发环境: Keil C51 V8.05 */
/* 开发日期: 2007.11.24 */
/* 程序编写: liu90091 */
/* 时钟频率: 22.1184 MHz */
/*****************************************************/
#include <reg52.h>
#include <stdio.h>
#include <stdarg.h>
#include "define.h"
#include "interface.h"
//#ifdef SYSCLK221184 // 系统时钟 22.1184 MHz
//=
//=65536-22118400 /12/9600 = 0xff40
//9600
#define SU_TH2 0xFF // 重装值 (2^16-0xff40)*12/22.1184*10^(-6)
#define SU_TL2 0x40 // = 104.167us(1/9600) (22.1184MHz)
#define DELAY_TH2 0xff
#define DELAY_TL2 0xc0
//4800
//#define SU_TH2 0xFe // 重装值 (2^16-0xfe80)*12/22.1184*10^(-6)
//#define SU_TL2 0x80 // = 2* 104.167us(1/4800) (22.1184MHz)
//#define DELAY_TH2 0xff
//#define DELAY_TL2 0x80
uchar RxCnt; // 模拟接收计数器及标志(0~3:计数器; 4:允许接收; 5:接收完成)
uchar TxCnt; // 模拟发送计数器及标志(0~3:计数器; 4:允许发送; 5:发送完成; 6:起始位未发送)
/* NEWCA */
uchar RXBUF; // 模拟串行接收缓冲
uchar TXBUF; // 模拟串行发送缓冲
//uchar uParity; // 校验计算字节
#define BUSYMSK 0x10 // 模拟串口忙标志掩蔽位
#define OVERMSK 0x20 // 模拟串口完成标志掩蔽位
#define OUTBUFFERSIZE 256 // 发送缓冲区大小
uchar xdata OutBuffer[OUTBUFFERSIZE]; // 发送缓冲区
uchar tin; // 发送缓冲区入指针
uchar tout; // 发送缓冲区出指针
#define INBUFFERSIZE 256 // 接收缓冲区大小
uchar xdata InBuffer[INBUFFERSIZE]; // 接收缓冲区
uchar rin; // 接收缓冲区入指针
uchar rout; // 接收缓冲区出指针
uchar RxCmdBuf[32];
uchar TxCmdBuf[32];
uchar rcount = 0;
uchar tcount = 0;
uchar TxIndex = 0;
bit TxCommand = 0;
bit RxCommand = 0; //收到命令包的个数
bit Synflag = 0;
bit sendfull=0; // 发送缓冲区满标志
bit sendactive=0; // 正在发送标志
bit bIsPacket=0;
code uchar TOASC[16]=
{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
//***************************************************************************/
// su_init: initialize simulator uart interface */
//***************************************************************************/
void SU_Init(void)
{
FEEDDOG();
tin = 0;
tout = 0;
rin = 0;
rout = 0;
RxCnt = 0;
TxCnt = 0;
//9600,n,8,1
//接收时钟设置
T2CON = 0x00; // 16 Bit Auto-Reload Mode
RCAP2H = SU_TH2; // 9600bps定时 (22.1184MHz)
RCAP2L = SU_TL2;
ET2 = 1; // 定时器 2 中断允许
//接收中断设置
IE0 = 0; //清中断标志
//IP &= 0xfd; //T0 低优先级
PT0 = 0;
IP |= 0x20;
//PT2 = 1;
IPH = 0x21;
TCON |= 0x01; // 外部中断 0 为边沿触发
方式
EX0 = 1; // 外部中断 0 允许
EN485 = 0;
EA = 1;
}
//***************************************************************************/
// su_rcv_int: receive start bit interrupt 0 */
//***************************************************************************/
void su_rcv_int1() interrupt 0
{
//uchar data i;
if(!(RxCnt & BUSYMSK)) // 如允许接收
{ // 起始位
FEEDDOG();
//i=DELAY_TIMES;
//while(i--); // 延时 (23*4+4)*12/22.1184 = 52.083 us (22.1184MHz)
//if(!RXD1) // 检测起始位
{
EX0 = 0; // 外部中断 0 不允许
RxCnt = 0x00 | BUSYMSK;
TH2 = DELAY_TH2;
TL2 = DELAY_TL2;
TR2 = 1; // 定时器 2 启动
}
}
}
//*****************************************************************************
/
// su_timer: timer2 interrupt
*/
//*****************************************************************************
/
void Recieve_timer() interrupt 5 using 3
{
TF2 = 0; // 中断标志清除( Timer2 必须软件清除!)
FEEDDOG();
if(RxCnt & BUSYMSK) // 接收
{
if((RxCnt & 0x0f) == 0x00) //起始位
{
if(RXD1)
{
RxCnt = 0x00;
EX0 = 1; // 外部中断
0 允许
TR2 = 0;
}
else
{
RXBUF = 0x00;
RxCnt++;
}
}
else if((RxCnt & 0x0f) < 0x09)
{
RXBUF >>= 1;
if(RXD1)RXBUF |= 0x80;
RxCnt++;
}
else // 收到1个字符
{
// if(RXD1)//停止位有效
GLED = ~GLED;
// InBuffer[rin++ & (INBUFFERSIZE-1)] = RXBUF; // 数据存入缓冲区
//if(rcount > 3){RxCommand = 1;}
if(RXBUF == '@')
{
bIsPacket = 1;
rcount = 0;
//InBuffer[rin++ & (INBUFFERSIZE-1)] = RXBUF; // 数据存入缓冲区
RxCmdBuf[rcount++] = RXBUF;
}
else if(RXBUF == '#')
{
//InBuffer[rin++ & (INBUFFERSIZE-1)] = RXBUF; // 数据存入缓冲区
RxCmdBuf[rcount++] = RXBUF;
RxCommand = 1; GLED = ~GLED;
bIsPacket = 0;
}
else if(bIsPacket)
{
//InBuffer[rin++ & (INBUFFERSIZE-1)] = RXBUF; // 数据存入缓冲区
//rcount++;
RxCmdBuf[rcount++] = RXBUF;
}
//接受数据处理
RxCnt = 0x00; // 收到1个字符
EX0 = 1; // 外部中断 0 允许
TR2 = 0;
//EN485 = 1;
//TxCnt = BUSYMSK;
//TXBUF = RXBUF; // 写SBUF
}
}
else if(TxCnt & BUSYMSK) // 发送
{
uchar tmp;
tmp = TxCnt & 0x0f;
if(tmp == 0x00) // 若还未发送起始位
{
TXD1 = 0; // 发送起始位
TxCnt++;
}
else if(tmp < 0x09)
{
TXD1 = (bit)(TXBUF & 0x01);
TXBUF = TXBUF >> 1;
TxCnt++;
}
else if(tmp == 0x09)
{
TXD1 = 1; // 发送停止位
TxCnt++;
}
else
{
TXD1=1;
sendfull = 0; // 清除发送缓冲区满标志
//TxIndex++;
//if(tcount > TxIndex)
if(tin != tout)
{ // 若缓冲区有字符
TXBUF = OutBuffer[tout++ & (OUTBUFFERSIZE-1)];
//TxCmdBuf[TxIndex]; // 发送1个字符
TxCnt = BUSYMSK;
}
else
{
sendactive = 0; // 若发送完, 清除正在发送标志
TxCnt = 0x00;
TR2=0; //停止发送
EX0 = 1;
EN485 = 0;
GLED = ~GLED;
TxCommand = 1;
}
}
}
// if(RxCnt || TxCnt == 0x00)TR2 = 0;
}
//发送一个字节
void putbuf(uchar c)
{
FEEDDOG();
if(!sendfull)
{ // 发送缓冲区未满才发送
if(!sendactive)
{ // 若当前未发送
sendactive = 1;
TxCnt = BUSYMSK;
TXBUF = c; // 写SBUF
EX0 = 0;
TXD1 = 1;
EN485 = 1;
TH2 = SU_TH2;
TL2 = SU_TL2;
TR2 = 1; // 定时器 2 启动
}
else
{ // 若正在发送
OutBuffer[tin++ & (OUTBUFFERSIZE-1)] = c; // 将字符放入发送缓冲区
if(((tin ^ tout) & (OUTBUFFERSIZE-1)) == 0)
{
sendfull = 1; // 置发送缓冲区满标志
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -