打印
[经验分享]

定时器/计数器

[复制链接]
80|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
一、定时器/计数器概述
(1)实现定时功能的几种方法
软件定时:软件定时不占用硬件资源,但占用了CPU时间,降低了CPU的利用率
采用时基电路定时:例如采用555电路
采用可编程电路芯片定时:这种定时芯片的定时值及定时范围很容易用软件来确定和修改,此芯片定时功能强,使用灵活
单片机定时器、扩展定时器芯片:方便、精准
(2)定时器和计数器的区别
计数的概念:假如有一个水杯(1000滴水正好能够装满),初始时已经有了500滴水,还需滴入500滴水才能将其装满,第501滴水时容器溢出。
定时的概念(如果滴入1滴水的时间为1秒):还需500秒时间才能将其装满,第501秒时容器溢出
(3)基本概念
定时器是对周期固定的脉冲信号进行计数(如MCU内部的系统时钟)
计数器是对周期不确定的脉冲信号进行计数:如MCU的I/O引脚所引入的外部脉冲信号
结论:定时器和计数器本质上都是计数器,定时器是计数器的一种特例
二、定时器/计数器相关寄存器
(1)控制寄存器TCON(可位寻址)



(2)工作方式寄存器TMOD(不可位寻址)
TMOD不可位寻址,意味着TMOD只可以进行整体赋值,而不能例如进行GOAT=0进行赋值
自动装载,溢出后重新装置;不可重装载,溢出后停止
(在蓝桥杯的学习中)不涉及终端引脚,所以GOAT位一般设置为0;一般使用定时器,所以C/T位一般设置为0
上电后,默认为0,只需操作控制寄存器即可进行计时



(3)辅助寄存器AUXR
STC15系列单片机是1T(即不存在机器周期)的8051单片机。(之前在使用8051单片机的时候,时钟系统是每12个系统时钟,8051才有一个机器周期)



(4)计数器/定时器-计数(定时)寄存器
用于计数器/定时器的计数或定时
定时器0:TL0定时器0低八位寄存器,TH0定时器0高八位寄存器
定时器1:TL1、YH1是定时/计数器T1的低8位、高8被状态值寄存器
定时器2:T2H、T2L是定时/计数器T2的高八位、低8位状态值寄存器
计时器/定时器的初始值计算:THx,TLx=65536-SYSCLK*T(sysclk是系统时间频率,T是要计时的时间)
(5)中断控制寄存器
开放总中断→开放部分中断(ET1\ET0) 若将ET0置为1,允许T0向CPU申请中断



三、定时器/计数器寄存器配置(使用STC-ISP工具配置定时器)
定时器初始化代码
STC-ISP软件→定时器计算器
选择使用的定时器、定时器模式、定时器时钟
选择系统时钟频率(下载时是什么频率,时钟就设置什么频率)
设置定时长度
生成C代码(注意:此为仅定时器初始化代码且已开始计时,但并没有开启定时器中断允许、也没有开启总中断)



四、定时器例程
(1)例程1:使用中断系统→定时器操作LED流水灯。本例以外部中断0(上升沿中断/上升沿下降沿均可中断)为例,中断产生后将L6灯取反操作。

#include <STC15F2K60S2.H>

unsigned char LED = 1;
unsigned int LED_Refresh=0;

//函数声明区域
void Timer0Init(void);        //1毫秒@11.0592MHz

void main(void)
{
       
        P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
        Timer0Init();
        EA=1;ET0=1;
       
        while(1)
        {
               
        }
       
}

void Timer0(void) interrupt 1
{
       
        if(++LED_Refresh == 1000)
        {
                LED_Refresh = 0;
                P0=~(0X01<<LED);
                if(++LED == 9) LED=0;
        }
       
}

(2)例程2:解决按键时效不稳定的问题。本例以S7按键控制LE200ms为间隔D自动向左移位,S6按键控制LED200ms为间隔自动向右移位S5按键控制LED停止循环移位,S4按键关闭所有LED为例。
#include <STC15F2K60S2.H>
#include<intrins.h>

unsigned char LED = 0 ;
unsigned char S7_Flag = 0, S6_Flag = 0, S5_Flag = 0, S4_Flag = 0 ;
unsigned char LED_Flag = 0 ;
unsigned int LED_tt = 0 ;

void KeyScan(void);
void Timer0Init(void);
void Delay_MS(unsigned int MS);

void main(void)
{
        P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;       
        Timer0Init();
        EA=1;ET0=1;
       
        while(1)
        {
                KeyScan();
       
                if(S7_Flag == 1){ S7_Flag = 0 ; LED_Flag = 1 ; }
                if(S6_Flag == 1){ S6_Flag = 0 ; LED_Flag = 2 ; }
                if(S5_Flag == 1){ S5_Flag = 0 ; LED_Flag = 0 ; }
                if(S4_Flag == 1){ S4_Flag = 0 ; P0 = 0XFF ; }
        }
}

void Timer0(void) interrupt 1
{
        if(LED_Flag == 1)
        {
                if(++LED_tt >= 200)
                {
                        LED_tt = 0 ;
                        P0=~(0X01<<LED);
                        LED++;
                        if(LED >= 8)LED = 0 ;
                }       
        }
       
        if(LED_Flag == 2)
        {
                if(++LED_tt >= 200)
                {
                        LED_tt = 0 ;
                        P0=~(0X80>>LED);
                        LED++;
                        if(LED >= 8)LED = 0 ;
                }                       
        }
}

void Timer0Init(void)                //1毫秒@11.0592MHz
{
        AUXR |= 0x80;                //定时器时钟1T模式
        TMOD &= 0xF0;                //设置定时器模式
        TL0 = 0xCD;                //设置定时初始值
        TH0 = 0xD4;                //设置定时初始值
        TF0 = 0;                //清除TF0标志
        TR0 = 1;                //定时器0开始计时
}


void KeyScan(void)
{
        if(P30==0)
        {
                Delay_MS(10);
                if(P30==0)S7_Flag = 1 ;               
                while(!P30);
        }
        else if(P31==0)
        {
                Delay_MS(10);
                if(P31==0)S6_Flag = 1 ;               
                while(!P31);
        }       
        else if(P32==0)
        {
                Delay_MS(10);
                if(P32==0)S5_Flag = 1 ;               
                while(!P32);
        }       
        else if(P33==0)
        {
                Delay_MS(10);
                if(P33==0)S4_Flag = 1 ;               
                while(!P33);
        }       
}

void Delay_MS(unsigned int MS)
{
        unsigned char i, j;
        while(MS--)
        {
        _nop_();
        i = 2;
        j = 199;
        do
        {
                while (--j);
        } while (--i);
}
}




————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/La_gloire/article/details/137124927

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

28

主题

79

帖子

0

粉丝