xz19921230 发表于 2013-1-22 15:34:38

关于使用两片ATMEGA128实现UART单线半双工通信

准备使用128做双机通信,使用半双工模式,电路原理图如图所示
单片机1的TXD 和RXD与单片机2的TXD和RXD分别用继电器切换,传输使用一条信道,我编的程序总是有问题,求大神指点···
这是单片机一的程序:
#include<iom128v.h>
#include<macros.h>
#define uchar unsigned char
#define uint unsigned int
#define data_1602_DDR DDRA
#define data_1602_PORT PORTA
#define control_1602_DDR DDRB
#define control_1602_PORT PORTB
#define CON_DDR DDRF
#define CON_PORT PORTF                          
#pragma interrupt_handler ADD:2
#pragma interrupt_handler UART_receive:19
#pragma interrupt_handler UART_transmit0:21
uchar flag=0,rdata,tdata=0;
//***************************************
void init_1602()
{
data_1602_DDR=0XFF;
control_1602_DDR=0XFF;
control_1602_PORT&=~BIT(2);

write_com(0x38);
delay(5);
write_com(0x01);
delay(5);
write_com(0x0c);
delay(5);
write_com(0x06);
delay(5);
}
//****************************************
void write_dat(uchar dat)
{
control_1602_PORT|=BIT(0);
control_1602_PORT&=~BIT(1);
data_1602_PORT=dat;
control_1602_PORT|=BIT(2);
delay(1);
control_1602_PORT&=~BIT(2);
}
//*************************************
void write_com(uchar com)
{
control_1602_PORT&=~BIT(0);
control_1602_PORT&=~BIT(1);
data_1602_PORT=com;
control_1602_PORT|=BIT(2);
delay(1);
control_1602_PORT&=~BIT(2);
}
//*************************************
void show_1602(uint x)
{

   uchar table1[]="receive:";
   
   uchar ASCII[]={48,49,50,51,52,53,54,55,56,57,114,115,47,46,32,118,100,66};//0 1 2 3 4 5 6 7 8 9 r s . /   
   uchar m1,n1,m2,n2,k;
   
write_com(0x80+0x01);
delay(5);
for(n1=0;n1<8;n1++)
   {
    write_dat(table1);
    delay(1);
   }
   
   write_com(0x80+0x09);
   delay(5);
    write_dat(ASCII);
    delay(1);
   
}
//***************************************
void delay(uint ms)
{
    uint i,j;
        for(i=0;i<ms;i++)
        {
       for(j=0;j<1141;j++);
    }
}
//****************************************
void UART_init()
{
UCSR0B=0X00;
UCSR0A=0X00;//控制和状态寄存器清零
UCSR0B=(1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0)|(1<<TXCIE0);//接收结束中断使能,接收、发送使能
UCSR0C=(1<<UCSZ01)|(1<<UCSZ00);//八个数据位,一个停止位
UBRR0H=0;
UBRR0L=51;//设置波特率为9600
DDRE|=BIT(1);//PE1口输出 即TXD0为输出
DDRE&=~BIT(0);//PE0口输入 即RXD0为输入
SEI();//开全局中断
}
//***********************************
void UART_transmit(uchar data)//发送数据
{
while(!(UCSR0A&(1<<UDRE0)));//等待发送缓冲器为空
UDR0=data;//将数据放入缓冲期,发送数据
while(!(UCSR0A&(1<<TXC0)));//等待数据发送结束
UCSR0A|=BIT(TXC0);//对TXC0位写1,清除标志
}
//***********************************
void UART_receive()//接收结束中断
{

UCSR0B&=~BIT(RXCIE0);
flag=1;
CON_PORT|=BIT(0);
rdata=UDR0;
UCSR0B|=BIT(RXCIE0);
}
void UART_transmit0()//发送结束中断
{
UCSR0B&=~BIT(TXCIE0);
UDR0=0;
CON_PORT&=~BIT(0);
UCSR0B|=BIT(TXCIE0);

}

//***********************************
void ADD()
{

tdata=tdata+1;
if(tdata==10)
{
    tdata=0;
}
}
//***********************************
int main(void)
{
CON_DDR|=BIT(0);
CON_PORT&=~BIT(0);
DDRD&=~BIT(0);
EIMSK|=BIT(0);
EICRA=0X00;
SEI();
init_1602();
UART_init();
while(1)
{
   UART_transmit(tdata);
       if(flag==1)
       {
           flag=0;
          
       }show_1602(rdata);
}

}
单片机2的程序:
#include<iom128v.h>
#include<macros.h>
#define uchar unsigned char
#define uint unsigned int
#define data_1602_DDR DDRA
#define data_1602_PORT PORTA
#define control_1602_DDR DDRB
#define control_1602_PORT PORTB
#define CON_DDR DDRF
#define CON_PORT PORTF       
#pragma interrupt_handler ADD:2
#pragma interrupt_handler UART_receive:19
#pragma interrupt_handler UART_transmit0:21
uchar flag=0,rdata,tdata=0,flag1=0;
//***************************************
void init_1602()
{
data_1602_DDR=0XFF;
control_1602_DDR=0XFF;
control_1602_PORT&=~BIT(2);

write_com(0x38);
delay(5);
write_com(0x01);
delay(5);
write_com(0x0c);
delay(5);
write_com(0x06);
delay(5);
}
//****************************************
void write_dat(uchar dat)
{
control_1602_PORT|=BIT(0);
control_1602_PORT&=~BIT(1);
data_1602_PORT=dat;
control_1602_PORT|=BIT(2);
delay(1);
control_1602_PORT&=~BIT(2);
}
//*************************************
void write_com(uchar com)
{
control_1602_PORT&=~BIT(0);
control_1602_PORT&=~BIT(1);
data_1602_PORT=com;
control_1602_PORT|=BIT(2);
delay(1);
control_1602_PORT&=~BIT(2);
}
//*************************************
void show_1602(uint x)
{

   uchar table1[]="receive:";
   
   uchar ASCII[]={48,49,50,51,52,53,54,55,56,57,114,115,47,46,32,118,100,66};//0 1 2 3 4 5 6 7 8 9 r s . /   
   uchar m1,n1,m2,n2,k;
   
   
   

write_com(0x80+0x01);
delay(5);
for(n1=0;n1<8;n1++)
   {
    write_dat(table1);
    delay(1);
   }
   
   write_com(0x80+0x09);
   delay(5);
   
    write_dat(ASCII);
       delay(1);
}
//***************************************
void delay(uint ms)
{
    uint i,j;
        for(i=0;i<ms;i++)
        {
       for(j=0;j<1141;j++);
    }
}
//****************************************
void UART_init()
{
UCSR0B=0X00;
UCSR0A=0X00;//控制和状态寄存器清零
UCSR0B=(1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0)|(1<<TXCIE0);//接收结束中断使能,接收、发送使能
UCSR0C=(1<<UCSZ01)|(1<<UCSZ00);//八个数据位,一个停止位
UBRR0H=0;
UBRR0L=51;//设置波特率为9600
DDRE|=BIT(1);//PE1口输出 即TXD0为输出
DDRE&=~BIT(0);//PE0口输入 即RXD0为输入
SEI();//开全局中断
}
//***********************************
void UART_transmit(uchar data)
{
while(!(UCSR0A&(1<<UDRE0)));//等待发送缓冲器为空
UDR0=data;//将数据放入缓冲期,发送数据
while(!(UCSR0A&(1<<TXC0)));//等待数据发送结束
UCSR0A|=BIT(TXC0);//对TXC0位写1,清除标志
UDR0=0;
}
//***********************************
void UART_receive()
{

UCSR0B&=~BIT(RXCIE0);
flag=1;
CON_PORT&=~BIT(0);
rdata=UDR0;
UCSR0B|=BIT(RXCIE0);

}
void UART_transmit0()
{

UCSR0B&=~BIT(TXCIE0);
CON_PORT|=BIT(0);
UDR0=0;
UCSR0B|=BIT(TXCIE0);


}
//***********************************
void ADD()
{
tdata=tdata+1;
if(tdata==10)
{
    tdata=0;
}
}
//***********************************
int main(void)
{
CON_DDR|=BIT(0);
CON_PORT&=~BIT(0);
DDRD&=~BIT(0);
EIMSK|=BIT(0);
EICRA=0X00;
SEI();
init_1602();
UART_init();
while(1)
{
   UART_transmit(tdata);
       
       if(flag==1)
       {
           flag=0;
           show_1602(rdata);
       }
}

}
求大神指点啊···如何实现单线半双工

MiniCat 发表于 2013-1-23 09:11:23

切换用继电器?你的继电器没有开关次数限制?

xz19921230 发表于 2013-1-23 09:42:11

MiniCat 发表于 2013-1-23 09:11 static/image/common/back.gif
切换用继电器?你的继电器没有开关次数限制?

那我该杂办····

MiniCat 发表于 2013-1-23 14:22:24

xz19921230 发表于 2013-1-23 09:42 static/image/common/back.gif
那我该杂办····

硬件可以考虑用三极管 光耦 MOS等等做切换
页: [1]
查看完整版本: 关于使用两片ATMEGA128实现UART单线半双工通信