基于AT89C52和串口通信助手的串口通信

我们要实现的功能是在程序运行的时候通过单片机的串口向串口调试助手发送一个字符串诸如“hello world”,串口通信助手接收到字符串之后显示并由用户反馈回去一个长度为4的字符串并显示到数码管上

来看一下效果

这里写图片描述

首先是串口通信电路的配置和借助VSPD、串口通信助手对相关串口的设置

  • 通过VSPD创建两个可以相互通信的虚拟串口,如COM1和COM2。点击添加端口按钮后,可以看到左边栏中的虚拟端口处看到你新创建的两个虚拟端口。
  • 打开串口调试助手V2.2,对其进行配置,将串口改为COM2端口,波特率设为9600,校验位选择NONE,数据位为8位,停止位为1位
  • 电路图中的配置:首先将晶振改为11.0592MHZ,再将AT89C52芯片中的晶振也改为11.0592MHZ。再配置串口,将物理端口设置为COM1,物理波特率设置为9600,物理数据位数设为8位,物理奇偶校验位设置为NONE,下面的虚拟波特率、虚拟数据位数和虚拟奇偶校验位与上面相同。
  • 接下来上电路图

    这里写图片描述

    用VSPD创建两个虚拟端口

    这里写图片描述

    可以通过设备管理器来查看串口是否创建成功

    这里写图片描述

    AT89C52的相关配置

    这里写图片描述

    对COMPIM的相关配置

    这里写图片描述

    一些端口的设置

    这里写图片描述

    硬件配置的差不多了,接下来我们看看如何在Keil里编写代码实现,这里仅摘录一些比较重要的代码片段,感兴趣的可以[下载代码](http://download.csdn.net/detail/lrwwll/9720330)

    /*数码管显示函数,利用74HC595实现串行输入并行输出*/
    void ser_inout(uchar datas)      
    {
        uchar i;                                                //循环控制变量
        STCP = 0;                                                 //P2.6引脚置0
        for(i = 0 ; i < 8 ; i++)                                //for循环,从高位到低位,依次传送数据
        {
            SHCP = 0;                                             //P2.7引脚置0
            if( (datas & 0x80) == 0)                              //如果最高位数据等于0
            {
                DS = 0;                                             //传递数据0给P2.5引脚
            }
            else
            {
                DS = 1;                                             //如果最高位数据不等于0,传递数据1给P2.5引脚
            }
            datas <<= 1;                                          //将传输的8位数据左移一位
            SHCP = 1;                                             //P2.7引脚置1,产生上升沿,将P2.5引脚上的数据传入74HC595
        }
        STCP = 1;                                               //P2.6置1,产生上升沿,送八位数据
    }
    /*动态显示函数,数码管动态显示数据*/
    void Display()
    { 
        uint i = 0;                                            //i是循环控制变量 
      while( i!=900 )                                        //while循环,循环90次,让数码管动态显示数据约1.5S
        {
          ser_inout(table[show[0]]);                            //将最高位数据送入数码管
        wx0 = 0;                                              //选中第一个数码管,低电平有效  
        delay_ms(1);                                          //延时1ms
        wx0 = 1;                                              //取消位选
    
          ser_inout(table[show[1]]);                            //将第二位数据送入数码管  
        wx1 = 0;                                                //选中第二个数码管,低电平有效
        delay_ms(1);                                          //延时1ms
        wx1 = 1;                                              //取消位选
    
          ser_inout(table[show[2]]);                            //将第三位数据送入数码管
        wx2 = 0;                                                //选中第三个数码管,低电平有效 
          delay_ms(1);                                          //延时1ms
        wx2 = 1;                                              //取消位选
    
        ser_inout(table[show[3]]);                            //将第四位数据送入数码管
        wx3 = 0;                                                //选中第四个数码管,低电平有效 
          delay_ms(1);                                          //延时1ms
        wx3 = 1;                                              //取消位选  
          i++;                                                  //i加1
        }       
    }
    
    /*输出函数,通过数码管显示相应数据*/
    void printf(uchar dat[])                                    //dat存储要显示的数据
    {
        uint i = 0;                                            //循环控制变量
        for(i = 4;i > 0;i--)                                    //循环4次,将要显示的数据存储在show数组中
        {
            show[4-i]=dat[4-i];
      }
        Display();                                              //调用动态显示函数,让数码管动态显示数据
    }
    /*串口通信相关初始化*/
    void init()
    {
        TMOD=0X20;                                              //设置定时器1方式2
        TH1=0XFD;                                               //设置波特率为9600
        TL1=0XFD;                                               //同上
        SCON=0X50;                                              //将串行口控制寄存器设置为串行口工作方式1并允许中断接收数据
        PCON&=0XEF;                                             //波特率不倍增
        TR1=1;                                                  //启动定时器1
        IE=0X0;                                                 //禁止任何中断
    }
    /*单片机串口发送一个字符*/
    void send(uchar txd)
    {
        SBUF=txd;
        while(!TI);
        TI=0;
    }
    
    /*单片机串口发送一个字符串*/
    void send_buf(uchar dat[])
    {
        uint i=0;
        while(dat[i]!='\0')
        {
            send(dat[i]);
            i++;
        }
    }

    一些解释

  • SCON=0x50:
    SCON是串行口控制寄存器,0x50为16进制,转换成二进制是01010000,对应下附表各位,即将串行口控制寄存器设置为串行口工作方式1并允许中断接收数据.
    附:scon寄存器结构表
    SCON SM0 SM1 SM2 REN TB8 RB8 TI RI
    位地址 9FH 9EH 8DH 9CH 9BH 9AH 99H 98H
  • TMOD=0x20: TMOD是定时/计数器方式控制寄存器,所以TMOD=0x20是将定时/计数器1设置为工作方式2.
  • TH1=0xE8,TL1=0xE8:
    给定时/计数器1装初值,即确定定时时长,具体时间与晶振有关.
  • TI=1,TR=1:
    由上附表可得,TI和RI是SCON寄存器的最低两位.TI:发送中断标志位 ,RI:接收中断标志位. TI=1表示帧发送结束,RI=1表示帧接收完成.
  • 猜你喜欢

    转载自blog.csdn.net/lrwwll/article/details/53861369