Bootstrap

STC8H系列—8.串口通信控制教程

一、概述:

    STC8H系列是带有多个串口的单片机,关于单片机串口的通信原理,不在本文的探讨的范围,本文重点讨论串口8位可变波特率模式的使用。8位可变波特率要正常工作需要使用一个定时器产生波特率,而且每个串口对应的定时器是有一规定的,当然通常定时器T2作为专用波特率发生器,4个串口都能使用。关于串口的使用,串口的端口不是完全固定的,比如说串口1默认与USB共用一个输入端,在使用串口时可能PSW1寄存器改变默认端口,每个串口都一套独立的寄存器,相关之间无串扰,当然在一定条件下可以共用一个波特率发生器T2。以下的例程,设置串口1从P36、P37输出、串口2从P46、P47输出,两个串口共用T2作为波特率发生器,实现串口1发送数据从串口2输出,串口2发送数据从串口1输出。

二、知识链接:

1、串口1控制器SCON

SM0和SM1控制串口1的工作方式:

与PC通信,8位数据可变波特率,无数据校验,选用模式1。

REN位置1允许接收控制位。

2、串口1辅助寄存器AUXR

其中S1ST2位:置0表示选用T1作为波特率发生器,置1选用T2作为波特率发生器,这里我们选t2作波特率发生器。

3、串口2控制器S2CON

S2SM0控制串口2的工作方式,当选用0时工作在8位数据可变波特率,无数据校验。S2REN,位置1允许串口2接收控制位。串口2默认使用T2作为波特率发生器。

三、实验平台搭建:

   1、MCU:STC-打狗棒系列核心实验板 V2.3

   2、实验板平台:德飞莱LY-51s

   3、硬件连接表:

     K1------>P20    发送字符

      LED1----->P00   指示灯1,按键K1按钮键指示

      LED2----->P01   指示灯2,串口收发指示

      串口1----->P46、P47   串口1

      串口2----->P36、P37   串口2

四、测试源代码:

#include <STC8H.h>

#include "intrins.h"

typedef     unsigned char   u8;

typedef     unsigned int    u16;

typedef     unsigned long   u32;

sbit Led1=P0^0;

sbit Led2=P0^1;

sbit Led3=P0^2;

sbit Led4=P0^3;

u8  TX1_Cnt;    //U1发送计数

u8  RX1_Cnt;    //U1接收计数

bit B_TX1_Busy; //U1发送忙标志

u8  RX1_Buffer[16]; //u1接收缓冲

u8  TX2_Cnt;    //U2发送计数

u8  RX2_Cnt;    //U2接收计数

bit B_TX2_Busy; //U2发送忙标志

u8  RX2_Buffer[16]; //u2接收缓冲

void Delay1ms(unsigned char x);//当主时钟频率为12M,1ms延时为基准

void init_IO();//初始化IO

void init_Uart1();//串口1初始化

void init_Uart2();//串口2初始化

void Uart1Send(char dat);

void Uart2Send(char dat);

void Uart1SendStr(char *puts);//发送数据

void Uart2SendStr(char *puts);//发送数据

void main()

{

      P_SW2 |= 0x80;  //扩展寄存器XFR访问使能

      init_IO();

     init_Uart1(); 

      init_Uart2();

     

      EA=1;

     Uart1SendStr("STC8H TEST!");

     Uart2SendStr("STC8H TEST!");

  

   while(1)

    {

   

       if(P20==0)

       {

          Delay1ms(1);

         if(P20==0)

         {

              Uart2SendStr("STC8H TEST!");

          Uart1SendStr("STC8H TEST!");            

            Led1=~Led1;

         }

       }

       

   }

}

void init_IO()

{

   RSTCFG=0x50;  //开启RST键进入ISP模式

   P0M1 = 0x00;   P0M0 = 0x00;   //设置P0口为准双向口

   P1M1 = 0x00;   P1M0 = 0x00;   //设置P0口为准双向口

   P2M1 = 0x00;   P2M0 = 0x00;   //设置P1口为准双向口

   P3M1 = 0x00;   P3M0 = 0x00;   //设置P3口为准双向口

   P4M1 = 0x00;   P4M0 = 0x00;   //设置P4口为准双向口

   P5M1 = 0x00;   P5M0 = 0x00;   //设置P5口为准双向口

  

   //P4M1=0xc0;P4M0=0x00;//设置P47和46高阻

  

}

void init_Uart1()//波特率11.0592

{

      P_SW1|=0x40;//将串口1的引脚切换至P36、P37

      SCON=0x50;//模式1,8位可变

      T2L = 0xE8;   //设置定时初始值

     T2H = 0xFF;    //设置定时初始值

     AUXR|=0x04;   //开启T1定时器1T工作模式

     AUXR|=0x10;   //开启T1定时器T1R=1

     AUXR|=0x01;  //Uart1使用模式1时,指定T2波特率发生器

     ES=1;

    

     B_TX1_Busy = 0;//忙检测

     TX1_Cnt = 0;//发送计数

    RX1_Cnt = 0;//接收计数

     

}

void init_Uart2()//波特率11.0592

{

    S2CON=0x10;   //打开允许接收

     T2L = 0xE8;    //设置定时初始值

     T2H = 0xFF;    //设置定时初始值

     AUXR|=0x04;   //开启T2定时器1T工作模式

     AUXR|=0x10;   //开启T2定时器T2R=1

       

    

     IE2|=0x01;//开启ES=1

      P_SW2|=0x01;//串口2脚位切换,将串口2脚位切换到P46、P47,默认P10、P11

    

     B_TX2_Busy = 0;//忙检测

     TX2_Cnt = 0;//发送计数

    RX2_Cnt = 0;//接收计数

}

void Uart2Send(char dat)//u2发送单字符

{

      while(B_TX2_Busy);

      B_TX2_Busy=1;

      S2BUF=dat;

}

void Uart1Send(char dat)//U1发送单字符

{

      while(B_TX1_Busy);

      B_TX1_Busy=1;

      SBUF=dat;

}

void Delay1ms(unsigned char x)    //@12.000MHz

{

   unsigned char i, j;

   i = 16;

   j = 147;

   while(x--)

   {

      do

      {

        while (--j);

      } while (--i);

   } 

}

void Uart2SendStr(char *puts)//U2发送字符串

{

     while(*puts)

      {

        Uart2Send(*puts++);

      }

}

void Uart1SendStr(char *puts)//U1发送字符串

{

     while(*puts)

      {

        Uart1Send(*puts++);

      }

}

void UART2_isr (void) interrupt 8//Uart2串口中断入口

{

   Led2=~Led2;

    if((S2CON & 1) != 0)

    {

        S2CON &= ~1;    //Clear Rx flag

        RX2_Buffer[RX2_Cnt++] = S2BUF;

        RX2_Cnt&=0x0f;

          SBUF=S2BUF;//发送至串口2

    }

    if((S2CON & 2) != 0)

    {

        S2CON &= ~2;    //Clear Tx flag

        B_TX2_Busy = 0;

    }

}

void UART1_isr (void) interrupt 4//Uart2串口中断入口

{

   Led2=~Led2;

    if((SCON & 1) != 0)

    {

        SCON &= ~1;    //Clear Rx flag

        RX1_Buffer[RX1_Cnt++] = SBUF;

        RX1_Cnt&=0x0f;

          S2BUF=SBUF;//发送至串口1

    }

    if((SCON & 2) != 0)

    {

        SCON &= ~2;    //Clear Tx flag

        B_TX1_Busy = 0;

    }

}

;