51单片机 - 定时器 - 串口通信


“响铃提醒”

04_51单片机 - 定时器 - 串口通信

一、定时器

定时器介绍

  • 定时器介绍∶51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成。
  • 定时器作用︰

    • 用于计时系统,可实现软件计时,或者使程序每隔一固定时间完成一项操作;
    • 替代长时间的Delay,提高CPU的运行效率和处理速度。

STc89C52定时器资源

  • 定时器个数∶3个(T0、T1、T2),T0和T1与传统的51单片机兼容,T2是此型号单片机增加的资源。
  • 注意︰定时器的资源和单片机的型号是关联在一起的,不同的型号可能会有不同的定时器个数和操作方式,但一般来说,T0和T1的操作方式是所有51单片机所共有的。

定时器框图

  • 定时器在单片机内部就像一个小闹钟一样,根据时钟的输出信号,每隔“一秒”,计数单元的数值就增加一,当计数单元数值增加到“设定的闹钟提醒时间"时,计数单元就会向中断系统发出中断申请,产生“响铃提醒”,使程序跳转到中断服务函数中执行。

定时器工作模式

工作模式1框图

定时器时钟

中断程序流程

STC89C52中断资源

  • 注意∶中断的资源和单片机的型号是关联在一起的,不同的型号可能会有不同的中断资源,例如中断源个数不同、中断优先级个数不同等等。

定时器和中断系统

定时器相关寄存器

  • 寄存器是连接软硬件的媒介。
  • 在单片机中寄存器就是一段特殊的RAM存储器,一方面,寄存器可以存储和读取数据,另一方面,每一个寄存器背后都连接了一根导线,控制着电路的连接方式。
  • 寄存器相当于一个复杂机器的“操作按钮”。

二、按键控制LED流水灯模式&定时器时钟

按键控制LED流水灯模式

项目结构

代码

  • Delay.c/h代码通用,略。

main.c

#include <REGX52.H>
#include "Timer0.h"
#include "Key.h"
#include <INTRINS.H>

unsigned char KeyNum,LEDMode;

void main()
{
    P2=0xFE;
    Timer0Init();
    while(1)
    {
        KeyNum=Key();        //获取独立按键键码
        if(KeyNum)            //如果按键按下
        {
            if(KeyNum==1)    //如果K1按键按下
            {
                LEDMode++;    //模式切换
                if(LEDMode>=2)LEDMode=0;
            }
        }
    }
}

void Timer0_Routine() interrupt 1
{
    static unsigned int T0Count;
    TL0 = 0x18;        //设置定时初值
    TH0 = 0xFC;        //设置定时初值
    T0Count++;        //T0Count计次,对中断频率进行分频
    if(T0Count>=500)//分频500次,500ms
    {
        T0Count=0;
        if(LEDMode==0)            //模式判断
            P2=_crol_(P2,1);    //LED输出
        if(LEDMode==1)
            P2=_cror_(P2,1);
    }
}

Timer0.c

#include <REGX52.H>

/**
  * @brief  定时器0初始化,1毫秒@12.000MHz
  * @param  无
  * @retval 无
  */
void Timer0Init(void)
{
    TMOD &= 0xF0;        //设置定时器模式
    TMOD |= 0x01;        //设置定时器模式
    TL0 = 0x18;        //设置定时初值
    TH0 = 0xFC;        //设置定时初值
    TF0 = 0;        //清除TF0标志
    TR0 = 1;        //定时器0开始计时
    ET0=1;
    EA=1;
    PT0=0;
}

Timer0.h

#ifndef __TIMER0_H__
#define __TIMER0_H__

void Timer0Init(void);

#endif

Key.c

#include <REGX52.H>
#include "Delay.h"

/**
  * @brief  获取独立按键键码
  * @param  无
  * @retval 按下按键的键码,范围:0~4,无按键按下时返回值为0
  */
unsigned char Key()
{
    unsigned char KeyNumber=0;
    
    if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
    if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
    if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
    if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}
    
    return KeyNumber;
}

Key.h

#ifndef __KEY_H__
#define __KEY_H__

unsigned char Key();

#endif

定时器时钟

项目结构

代码

main.c

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "Timer0.h"

unsigned char Sec=55,Min=59,Hour=23;

void main()
{
    LCD_Init();
    Timer0Init();
    
    LCD_ShowString(1,1,"Clock:");    //上电显示静态字符串
    LCD_ShowString(2,1,"  :  :");
    
    while(1)
    {
        LCD_ShowNum(2,1,Hour,2);    //显示时分秒
        LCD_ShowNum(2,4,Min,2);
        LCD_ShowNum(2,7,Sec,2);
    }
}

void Timer0_Routine() interrupt 1
{
    static unsigned int T0Count;
    TL0 = 0x18;        //设置定时初值
    TH0 = 0xFC;        //设置定时初值
    T0Count++;
    if(T0Count>=1000)    //定时器分频,1s
    {
        T0Count=0;
        Sec++;            //1秒到,Sec自增
        if(Sec>=60)
        {
            Sec=0;        //60秒到,Sec清0,Min自增
            Min++;
            if(Min>=60)
            {
                Min=0;    //60分钟到,Min清0,Hour自增
                Hour++;
                if(Hour>=24)
                {
                    Hour=0;    //24小时到,Hour清0
                }
            }
        }
    }
}

测试

三、串口通信

串口介绍

  • 串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信。
  • 单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大的扩展了单片机的应用范围,增强了单片机系统的硬件实力。
  • 51单片机内部自带UART (Universal Asynchronous ReceiverTransmitter,通用异步收发器),可实现单片机的串口通信。

硬件电路

  • 简单双向串口通信有两根通信线(发送端EXD和接收端RXD)。
  • TXD与RXD要交叉连接。
  • 当只需单向的数据传输时,可以直接一根通信线。
  • 当电平标准不一致时,需要加电平转换芯片。

电平标准

接口及引脚定义

常见通信接口比较

  • 此外还有∶ CAN、USB等。

相关术语

  • 全双工:通信双方可以在同一时刻互相传输数据。
  • 半双工:通信双方可以互相传输数据,但必须分时复用一根数据线。
  • 单工:通信只能有一方发送到另一方,不能反向传输。
  • 异步:通信双方各自约定通信速率。
  • 同步:通信双方靠一根时钟线来约定通信速率。
  • 总线:连接各个设备的数据传输线路(类似于一条马路,把路边各住户连接起来,使住户可以相互交流)。

51单片机的UART

串口参数及时序图

  • 波特率:串口通信的速率(发送和接收各数据位的间隔时间)。
  • 检验位:用于数据验证。
  • 停止位:用于数据帧间隔。

串口模式图

  • SBUF:串口数据缓存寄存器,物理上是两个独立的寄存器,但占用相同的地址。写操作时,写入的是发送寄存器,读操作时,读出的是接收寄存器。

串口和中断系统

串口相关寄存器

四、串口向电脑发送数据&电脑通过串口控制LED

串口向电脑发送数据

代码

#### main.c

#include <REGX52.H>
#include "Delay.h"
#include "UART.h"

unsigned char Sec;

void main()
{
    UART_Init();            //串口初始化
    while(1)
    {
        UART_SendByte(Sec);    //串口发送一个字节
        Sec++;                //Sec自增
        Delay(1000);        //延时1秒
    }
}

Delay.c

void Delay(unsigned int xms)
{
    unsigned char i, j;
    while(xms--)
    {
        i = 2;
        j = 239;
        do
        {
            while (--j);
        } while (--i);
    }
}

Delay.h

#ifndef __DELAY_H__
#define __DELAY_H__

void Delay(unsigned int xms);

#endif

UART.h

#ifndef __UART_H__
#define __UART_H__

void UART_Init();
void UART_SendByte(unsigned char Byte);

#endif

UART.c(串口初始化)

#include <REGX52.H>

/**
  * @brief  串口初始化,4800bps@12.000MHz
  * @param  无
  * @retval 无
  */
void UART_Init()
{
    SCON=0x40;
    PCON |= 0x80;
    TMOD &= 0x0F;        //设置定时器模式
    TMOD |= 0x20;        //设置定时器模式
    TL1 = 0xF3;        //设定定时初值
    TH1 = 0xF3;        //设定定时器重装值
    ET1 = 0;        //禁止定时器1中断
    TR1 = 1;        //启动定时器1
}

/**
  * @brief  串口发送一个字节数据
  * @param  Byte 要发送的一个字节数据
  * @retval 无
  */
void UART_SendByte(unsigned char Byte)
{
    SBUF=Byte;
    while(TI==0);
    TI=0;
}

电脑通过串口控制LED

HEX模式

文本模式

数据显示模式

  • HEX模式/十六进制模式/二进制模式:以原始数据的形式显示。
  • 文本模式/字符模式:以原始数据编码后的形式显示。

改造原有main.c

#include <REGX52.H>
#include "Delay.h"
#include "UART.h"

void main()
{
    UART_Init();        //串口初始化
    while(1)
    {
        
    }
}

void UART_Routine() interrupt 4
{
    if(RI==1)                    //如果接收标志位为1,接收到了数据
    {
        P2=~SBUF;                //读取数据,取反后输出到LED
        UART_SendByte(SBUF);    //将受到的数据发回串口
        RI=0;                    //接收标志位清0
    }
}

改造原有UART.C

#include <REGX52.H>

/**
  * @brief  串口初始化,4800bps@12.000MHz
  * @param  无
  * @retval 无
  */
void UART_Init()
{
    SCON=0x50;
    PCON |= 0x80;
    TMOD &= 0x0F;        //设置定时器模式
    TMOD |= 0x20;        //设置定时器模式
    TL1 = 0xF3;        //设定定时初值
    TH1 = 0xF3;        //设定定时器重装值
    ET1 = 0;        //禁止定时器1中断
    TR1 = 1;        //启动定时器1
    EA=1;
    ES=1;
}

/**
  * @brief  串口发送一个字节数据
  * @param  Byte 要发送的一个字节数据
  * @retval 无
  */
void UART_SendByte(unsigned char Byte)
{
    SBUF=Byte;
    while(TI==0);
    TI=0;
}

/*串口中断函数模板
void UART_Routine() interrupt 4
{
    if(RI==1)
    {
        
        RI=0;
    }
}
*/

声明:三二一的一的二|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - 51单片机 - 定时器 - 串口通信


三二一的一的二