/**********************************************
IO 口模拟232串行异步通讯程序 (占用两个IO口及一个定时器)
本程序使用示波器校正,基本能保证在PC发过来的方波的中间位置进行取样
说明: 1位起始位,9位数据位,1位停止位
问题:1. 如果PC侧连续发数据,并且51侧收到一个字节就响应一个字节到PC,
会出现总是少发一个数据给PC的情况,如PC发 123456789,则51回 13579
但该问题不影响MDB协议的实现,故这里不讨论该问题的解决方法.
2. 如果比指定的定时器中断优先级高的中断进入,并且处理时间比较长,可能会造成接收到的数据不正确(这个问题在硬件串口中不存在)
3. 如果PC连续发数据,51收到一个数据,准备收下一个数据时,随便进入一个中断,并且处理时间过长,将会导致丢失数据或收到错误的数据(这个问题在硬件串口中也存在)
**********************************************/
#include <reg52.h>
#include "uart_sim.h"
sbit BT_REC =P3^0;
sbit BT_SND =P3^1;
sbit P1_0 =P1^0;
#define ETx ET1
#define TRx TR1
#define TFx TF1
#define THx TH1
#define TLx TL1
#define PTx PT1
#define StartBitOn() (BT_REC==0)
#define UART_SIM_THx (256-208)
#define UART_SIM_THx_HALF (256-22)
//9600bps 就是 1000000/9600=104.167微秒 执行的
//时间是104.167*11.0592/12 = 96 (补偿数= 原数/2 - (原数/2)*(5/12)=(96/2)-(96/2)*(4/5)=?)
//时间是104.167*24.0/12=208.33=208 (补偿数= 原数/2 - (原数/2)*(5/12)=(208/2)-(208/2)*(4/5)=22) //如果有问题可以将4/5改为3/4或2/3
//时间是104.167*22.1184/12 =192 (补偿数= 原数/2 - (原数/2)*(5/12)=(192/2)-(192/2)*(4/5)=20)
#define UART_SIM_TIMER_ENABLE do{TLx=THx; TRx=1;}while(0)//TRx = 1,启动Timer
#define UART_SIM_TIMER_DISABLE TRx=0
#define UART_SIM_TIMER_THx(x) do{THx = (x);TLx=THx;}while(0)
#define TRUE 1
#define FALSE 0
#define F_SEND 1
#define F_RECV 0
typedef unsigned char UINT8;
typedef bit BOOL;
typedef bit BIT1;
//************** 全局变量 for uart_sim begin
BOOL fSendOrRecv; //F_SEND F_RECV
BOOL fRecvSuccess; //TRUE or FALSE, 如果没有正确的接收到停止位,则置 FALSE
BOOL fRecvStartbit; //TRUE 表示接收起始位, false 表示接收数据位或停止位
UINT8 sendOrRecvLen; //要发送/或接收的数据的BIT数
UINT8 sendOrRecvByte; //要发送/或接收到的字符
BIT1 bitMode;
//************** 全局变量 for uart_sim end
//定时器计数器1的中断
void UART_SIM_TIMER_Interrupt() interrupt 3 //Timer1
{
P1_0 = !P1_0; //输出一个脉冲用于校正取样点
if(fSendOrRecv==F_RECV){
if(fRecvStartbit){
UART_SIM_TIMER_THx(UART_SIM_THx);
fRecvStartbit = FALSE;
return;
}
if(sendOrRecvLen>1){
sendOrRecvByte>>=1;
if(BT_REC)
{
sendOrRecvByte|=0x80;
}
--sendOrRecvLen;
} else if(sendOrRecvLen==0) {
//接收 stop
fRecvSuccess = BT_REC;
//停止定时器
UART_SIM_TIMER_DISABLE;
} else {
//接收 mode
bitMode = BT_REC;
--sendOrRecvLen;
}
} else {
if(fRecvStartbit){
fRecvStartbit=FALSE;
//停止定时器
UART_SIM_TIMER_DISABLE;
return;
}
if(sendOrRecvLen>1){
BT_SND = (bit)(sendOrRecvByte&0x01);
sendOrRecvByte>>=1;
--sendOrRecvLen;
} else if(sendOrRecvLen==0){
//发送 stop
BT_SND = 1;
fRecvStartbit=TRUE;
} else {
//发送 mode
BT_SND = bitMode;
--sendOrRecvLen;
}
}
}
void uart_sim_sendByte(UINT8 b, bit mode){
UART_SIM_TIMER_THx(UART_SIM_THx);
UART_SIM_TIMER_ENABLE; //记数器0启动
BT_SND = 0; //启动位
fSendOrRecv = F_SEND;
fRecvStartbit=FALSE;
sendOrRecvLen = 9;
sendOrRecvByte = b;
bitMode = mode;
while(sendOrRecvLen);
while(TRx);
}
BOOL uart_sim_recvByte(UINT8* pbyte, UINT8* pmode){
while(!StartBitOn());
fSendOrRecv = F_RECV;
fRecvStartbit = TRUE; //置跳过起始位
UART_SIM_TIMER_THx(UART_SIM_THx_HALF);
UART_SIM_TIMER_ENABLE; //记数器0启动
sendOrRecvLen = 9;
while(sendOrRecvLen);
*pbyte = sendOrRecvByte;
*pmode = bitMode;
while(TRx);
return fRecvSuccess;
}
void uart_sim_init(){
//TMOD=0x22; /*定时器1为工作模式2(8位自动重装),0为模式2(8位自动重装) */
//如果使用T0,则应该是 TMOD=(TMOD&0xf0)|0x02;
//如果使用T1,则应该是 TMOD=(TMOD&0x0f)|0x20;
TMOD=(TMOD&0x0f)|0x20;
//PCON=00;
PCON &=0x7F; //SET SMOD=0;
TRx=0; //在发送或接收才开始使用
TFx=0;
THx=UART_SIM_THx;
TLx=THx;
ETx=1;//定时器/记数器T1的溢出中断允许位,ET,允 许中断
PTx = 1; //设定定时器x为高优先级
}
void test_send_nostop(){
while(1){
uart_sim_sendByte(0x55,1);
uart_sim_sendByte(0xaa,1);
uart_sim_sendByte(0xff,1);
uart_sim_sendByte(0x0f,1);
uart_sim_sendByte(0xf0,1);
uart_sim_sendByte(0x00,1);
}
}
void test_send2(){
UINT8 i;
static const char code a[]="#define UART_SIM_TIMER_ENABLE do{TL0=TH0; TR0=1;}while(0);//TR0 = 1";
for(i=0; i<sizeof(a)/sizeof(char); ++i)
uart_sim_sendByte(a[i], 1);
}
UINT8 idata recvbuf[50];
UINT8 idata recvmodebuf[50];
void test_recv2(){
UINT8 * p = recvbuf;
UINT8 * pm = recvmodebuf;
UINT8 i=10;
while(i--){
if(!uart_sim_recvByte(p, pm)){
*p = 0xee;
}
++p;
++pm;
}
i=10;
p=recvbuf;
pm=recvmodebuf;
while(i--){
uart_sim_sendByte(*p,1);
uart_sim_sendByte(*pm,1);
++p;
++pm;
}
}
void test_send_recv(){
UINT8 Getch, mode;
while(1)
{
if(uart_sim_recvByte(&Getch, &mode)){
uart_sim_sendByte(Getch, 1);
} else {
uart_sim_sendByte(0xee, 1);
}
}
}
char code c512[3] _at_ 0x3b;
void main()
{
uart_sim_init();
EA=1;
test_send2();
test_recv2();
test_send_recv();
test_send_nostop();
}
文章是怎么写出来的?
好吧,我承认我想多了
大师受教了,缘来如此。。。
...也许网络安全产业以后会是
此法确实可靠吗?
hello!,I like y
I was suggested
Thanks , I've j