📄 mega16软件模拟2个串口程序.c
字号:
cnt = 0;
number = 0;
status = SDATA;
}
break;
case SDATA:
if(vmRS232SBUF & 0x01)
{
SET_VM232_TX();
}
else
{
CLR_VM232_TX();
}
if(++cnt > 3)
{
cnt = 0;
if(++number < 8)
{
vmRS232SBUF >>= 1;
}
else
{
//number = 0;
status = STOP;
}
}
break;
case STOP:
SET_VM232_TX();
if(++cnt > 3)
{
cnt = 0;
status = START;
flgVmRs232tx = 0;
// 在这模拟的发送中断,不太实用
}
break;
default:
SET_VM232_TX();
cnt = 0;
status = START;
flgVmRs232tx = 0;
break;
}
}
}
void vm_rs485_tx(void) // 模拟485发送函数
{
static U8 status = START;
static U8 cnt = 0;
static U8 number = 0;
if(flgVmRs485tx)
{
switch(status)
{
case START:
CLR_VM485_TX();
if(++cnt > 3)
{
cnt = 0;
number = 0;
status = SDATA;
}
break;
case SDATA:
if(vmRS485SBUF & 0x01)
{
SET_VM485_TX();
}
else
{
CLR_VM485_TX();
}
if(++cnt > 3)
{
cnt = 0;
if(++number < 8)
{
vmRS485SBUF >>= 1;
}
else
{
//number = 0;
status = STOP;
}
}
break;
case STOP:
SET_VM485_TX();
if(++cnt > 3)
{
cnt = 0;
status = START;
flgVmRs485tx = 0;
// 在这模拟的发送中断,不太实用
}
break;
default:
SET_VM485_TX();
cnt = 0;
status = START;
flgVmRs485tx = 0;
break;
}
}
}
// 波特率都是2400BIT/S ,416US/BIT
// 5中取3 ,每104US抽样(也可以3中取2)
// 52US中断交替采样2个模拟串口
//TIMER2 initialize - prescale:8
// WGM: Normal
// desired value: 52uSec
// actual value: 52.000uSec (0.0%)
void timer2_init(void)
{
TCCR2 = 0x00; //stop
ASSR = 0x00; //set async mode
TCNT2 = 0xd3; //setup
OCR2 = 0x34;
TCCR2 = 0x02; //start
}
#pragma interrupt_handler timer2_ovf_isr:5
void timer2_ovf_isr(void) // 最高优先级中断 在中断里面接收、发送数据
{
static bool sw = 0; // 模拟串口交替使用定时器开关,实现104US采样
volatile U8 vmRS232, vmRS485; // 记录2模拟串口接收脚的高低电平
TCNT2 = 0xd3; //reload counter value
// 在这采样接收脚保证不漂移
vmRS232 = GET_VM232_RX(); //宏定义,获取PD0电平值
vmRS485 = GET_VM485_RX(); //宏定义,获取PD2电平值
// 在这增加串口接收检测
if(sw) // 乒乓操作 2个串口交替发送
{
vm_rs232_tx();
vm_rs232_rx(vmRS232);
// 在这增加串口
sw = 0;
}
else
{
vm_rs485_tx();
vm_rs485_rx(vmRS485);
// 在这增加串口
sw = 1;
}
}
/*+++++++++++++++++++++++++++++++++= MAIN =+++++++++++++++++++++++++++++++++++*/
void port_init(void)
{
PORTA = 0xFF;
DDRA = 0xFF;
PORTB = 0xFF;
DDRB = 0xFF;
PORTC = 0xFF;
DDRC = 0xFF;
PORTD = 0xFF;
DDRD = 0B11111010; //PD0 PD2 输入,PD1 PD3 输出
}
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
timer2_init();
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x40; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
void main(void)
{
init_devices();
while(1)
{
if(outRS232!=inRS232) //如果有新的数据输入
{
while(flgVmRs232tx); //判断是否处于发送状态
vmRS232SBUF=vmRS232Buf[outRS232++];//将新接收到的数据存入发送缓冲
if(vmRS232SBUF=='1') //如果接收到的数据是需要的数据
{vmRS232SBUF='K';}
else vmRS232SBUF='0';
flgVmRs232tx=1; //发送标志位置1,准备发送
if(outRS232>=20) //接收、发送都是环型缓冲区
{
outRS232=0;
}
}
}
/*
// 收到什么就回发什么
while(1)
{
if(outRS232 != inRS232)
{
while(flgVmRs232tx);
vmRS232SBUF = vmRS232Buf[outRS232++];
flgVmRs232tx = 1;
if(outRS232 >= 20) // 接收、发送都是环型缓冲区
{
outRS232 = 0;
}
}
if(outRS485 != inRS485)
{
while(flgVmRs485tx);
vmRS485SBUF = vmRS485Buf[outRS485++];
flgVmRs485tx = 1;
if(outRS485 >= 20) // 接收、发送都是环型缓冲区
{
outRS485 = 0;
}
}
} */
}
/*++++++++++++++++++++++++++++++++++=end=+++++++++++++++++++++++++++++++++++++*/
/* 以上是我开始做的2个模拟串口测试全部程序,大家可以按照自己的需要修改使用
而在我的工程中我改成了模拟接收完一帧(MAX 30BYTES)数据才请求处理。发送
则是用了一个50BYTES环型缓冲区实现随意的发送数据,使用起来非常方便。
以上调试中,请大家务必设置好定时器的准确定时。因为实现US级的定时,ICCAVR
的‘应用生成’设置不准!另外,单片机的工作频率尽可能高些!!!
以上只是一个实现的思想,不足之处请大家指点,我不用3中取2,只是想模拟100%
的正确率,在这请大家调试后有什么心得也写出来让大家分享!! */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -