单片机学习小组
直播中

颜立歆

9年用户 1033经验值
擅长:控制/MCU
私信 关注

如何去实现一种单片机通过串口方式1进行全双工数据通信的设计呢

如何去实现一种单片机通过串口方式1进行全双工数据通信的设计呢?其设计思路是怎样的?

回帖(1)

王雷

2022-1-26 15:19:22
思考题:
设计两个单片机通过串口方式1进行全双工数据通信,要求将波特率设置为2400,晶振频率为11.0592MHz,请分别编写发送程序和接收程序,接收端需使用液晶屏幕显示接收内容,发送端可循环发送一个字符串(自己定义一个字符串,例如“Welcome to Wuhan”)。

(1)电路图如下:

(2)设计思路:
1、电路:
两个单片机都是用P0口连接LCD1602数据线的0~7位,P20连接寄存器选择位RS,P21连接读写选择位RW,P2^2连接使能位E。然后甲机的RXD连乙机的TXD,甲机的TXD连乙机的RXD。需要注意的是:P0口,P2作为I/O口输出的时候时输出低电平为0输出高电平为高组态(并非5V,相当于悬空状态)。也就是说不能真正的输出高电平,给所接的负载提供电流,因此必须接上拉电阻。
2、程序:
波特率2400,晶振频率为11.0592MHZ,T1工作在方式1,由公式X=256-(fosc/12)(2^SMOD/(322400)),可以算出初值TH1=TL1=244=0xf4。有关LCD1602的相关函数此处就略了!!
2.1甲机发送数据程序说明:
串口首先要初始化,选择方式1,REN允许接收位置1,即SCON=0x50;T1工作在方式2,即TMOD=0x20;波特率不加倍,即PCON=0x00;设置初值TH1=TL1=0xf4;启动T1,即TR1=1。
然后串口发送数据,CPU将数据写入SBUF,即SBUF=dat;再搞一个陷阱while(!TI)来判断是否发完,下一步TI置0;
调用LCD1602的单字符显示函数dis_char(address++,dat) (address刚开始为0x00)发送下一个数据时地址++,(发送完一个数据 就显示一个数据);显示完第一行 就显示第二行;显示完第二行 清屏后又显示第一行;发送完一帧数据 地址就归零 清屏 从头再来。
注意这里清屏之前要延时一下 ,等前面发送的数据显示完了,再清屏!具体请看代码!!!
2.2乙机接收数据程序说明:
首先也是串口的初始化 ,跟楼上甲机是一样的!
然后是串口接收数据,这里是通过串口中断来接收数据的(interrupt 4)。但是有个不足就是得事先知道发送数据的第一个字符;判断当SBUF==发送数据的第一个字符时,这就说明刚接收完一帧数据或者马上开始接收数据,那这时就将地址address置0并将屏幕清屏;然后读SBUF中的数据,调用LCD1602的单字符显示函数dis_char(address++,receive_char) ;再将RI软件置0。最后同发送的显示格式一样,显示完第一行 就显示第二行;显示完第二行 清屏后又显示第一行;接收完一帧数据 地址就归零 清屏 从头再来。
(3)发送程序代码:

/** 功能描述: 甲机发数据!”**/
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define lcd_out P0


/***********端口定义********************************/
***it rs=P2^0;
***it rw=P2^1;
***it e=P2^2;
/***********函数申明***********************************/
void UART_Init(void);
void UART_SendData(uchar dat);
void UART_SendString(uchar *p);
void delay(uint j);


void check_busy(void);
void write_command(uchar com);
void write_data(uchar dat);
void LCD_initial(void);
void dis_char(uchar ad, uchar input);


/***********变量定义********************************/
uchar address=0x00;   //显示地址


uchar sting[]="Welcome to Sichuan for hot pot!";
void main(void)
{
    LCD_initial();                             //LCD1602 初始化
          UART_Init();                 //串口初始化
        while(1)
        {
                UART_SendString(sting);           //发送字符串
        address=0x00;   //发送完数据 地址就归零 从头再来
                delay(1000);
                write_command(0x01);  //发送完一帧数据 清屏        
    }
}


//串口初始化
void UART_Init(void)
{
        SCON=0x50;
    TMOD=0x20;
        PCON=0x00;
    TH1 =0xf4;
        TL1 =0xf4;  //预置初值,设波特率为2400
        TR1 =1;       
}


//串口发送一个字节的数据
void UART_SendData(uchar dat)
{
        SBUF=dat;      //发送数据
        while(!TI);  //判断是否发送完
        TI=0;    //软件清0
        delay(100);
        dis_char(address++,dat);  //发送完一个数据 显示一个数据
        if(address==0x10) address=0x40;//显示完第一行 就显示第二行
        if(address==0x50){
       write_command(0x01);
           address=0x00;//显示完第二行  清屏后又显示第一行
         }
}


//串口发送多字节数据
void UART_SendString(uchar *p)
{
  while(*p!='')
  {
   UART_SendData(*p);
   p++;
  }
}


//1ms延时程序
void delay(uint j)
{
        uchar i=250;
        for(;j>0;j--)
        {
                while(--i);
                i=249;
                while(--i);
                i=250;
        }
}
//查忙程序
void check_busy(void)
{
        uchar dt;
        do
        {
                dt=0xff;
                e=0;
                rs=0;       
                rw=1;
                e=1;
                dt=lcd_out;
        }while(dt&0x80);
        e=0;
}       
//写控制指令
void write_command(uchar com)
{
        check_busy();
        e=0;
        rs=0;
        rw=0;
        lcd_out=com;
        e=1;
        _nop_();
        e=0;
        delay(1);
}
//写数据指令
void write_data(uchar dat)
{
        check_busy();
        e=0;
        rs=1;
        rw=0;
        lcd_out=dat;
        e=1;
        _nop_();
        e=0;
        delay(1);       
}
//液晶屏初始化
void LCD_initial(void)
{
        write_command(0x38);//8位总线,双行显示,5X7的点阵字符
        write_command(0x0C);//开整体显示,光标关,无黑块
        write_command(0x06);//光标右移
        write_command(0x01);//清屏
        delay(1);
}


// 输出字符


void dis_char(uchar ad, uchar input)


{
        write_command(ad+0x80);//ad是显示位置信息
   
        write_data(input);


        delay(10);


}
       
(4)接受程序代码:

/** 功能描述: 乙机收数据!”**/
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define lcd_out P0


/***********端口定义********************************/
***it rs=P2^0;
***it rw=P2^1;
***it e=P2^2;
/***********函数申明***********************************/
void UART_Init(void);
void delay(uint j);


void check_busy(void);
void write_command(uchar com);
void write_data(uchar dat);
void LCD_initial(void);
void dis_char(uchar ad, uchar input);


/***********变量定义********************************/
uchar address=0x00;   //显示地址
uchar receive_char;   //接收的数据


void main(void)
{
    LCD_initial();                             //LCD1602 初始化
          UART_Init();                 //串口初始化
    ES=1;//打开串口中断开关
    EA=1;//打开中断总开关
        while(1)
        {
     if(address==0x10) address=0x40; //显示完第一行 就显示第二行
         if(address==0x50){
       write_command(0x01);
           address=0x00;//显示完第二行  清屏后又显示第一行
         }
    }
}
//利用串口中断来接收数据 并用LCD显示信息
void inter (void) interrupt 4
  {
    if(SBUF=='W'){    //不足就是 得事先知道发送数据的第一个字符
     write_command(0x01);//接收完一帧就清屏
         address=0x00;  //地址也归零 从头再来
         }
     receive_char=SBUF;
     dis_char(address++, receive_char);//接收一个数据显示一个数据
     RI=0;      //软件清0
  }




//串口初始化
void UART_Init(void)
{
        SCON=0x50;
    TMOD=0x20;
        PCON=0x00;
    TH1 =0xf4;
        TL1 =0xf4;  //预置初值,设波特率为2400
        TR1 =1;       
}




//1ms延时程序
void delay(uint j)
{
        uchar i=250;
        for(;j>0;j--)
        {
                while(--i);
                i=249;
                while(--i);
                i=250;
        }
}
//查忙程序
void check_busy(void)
{
        uchar dt;
        do
        {
                dt=0xff;
                e=0;
                rs=0;       
                rw=1;
                e=1;
                dt=lcd_out;
        }while(dt&0x80);
        e=0;
}       
//写控制指令
void write_command(uchar com)
{
        check_busy();
        e=0;
        rs=0;
        rw=0;
        lcd_out=com;
        e=1;
        _nop_();
        e=0;
        delay(1);
}
//写数据指令
void write_data(uchar dat)
{
        check_busy();
        e=0;
        rs=1;
        rw=0;
        lcd_out=dat;
        e=1;
        _nop_();
        e=0;
        delay(1);       
}
//液晶屏初始化
void LCD_initial(void)
{
        write_command(0x38);//8位总线,双行显示,5X7的点阵字符
        write_command(0x0C);//开整体显示,光标关,无黑块
        write_command(0x06);//光标右移
        write_command(0x01);//清屏
        delay(1);
}


// 输出字符


void dis_char(uchar ad, uchar input)


{
        write_command(ad+0x80);//ad是显示位置信息


        write_data(input);


        delay(10);


}
       
举报

更多回帖

发帖
×
20
完善资料,
赚取积分