蓝桥杯单片机开发及应用-基础模块08-定时器的应用

一、先前知识

  1. 定时器/计数器

定时器和计数器最基本的工作原理就是计数。作为定时器时,计数信号的来源选择周期性的内部时钟脉冲;用作计数器时,计数信号的来源选择非周期的外部输入信号。不管是定时器还是计数器,本质上都是计数器。

51单片机有两个定时器/计数器T0和T1,为16位加法器,由低八位TL和高八位TH两个寄存器构成,所有的工作模式中最大计数值为65535个计数脉冲。

该加1计数器的计数脉冲来源有2个:

①系统时钟震荡输出的12分频;

②T0或T1引脚输入的外部脉冲信号。

每接收到一个计数脉冲,计数器就会加1,当计数值累计至全为1时(8位255,13位8191,16位65535),再输入一个计数脉冲,计数器便会溢出回零,并且计数器的溢出是TCON寄存器的TF0或TF1位置1,同时向内核提出中断请求。如果定时器/计数器工作于定时模式,则表示间隔定时时间到;如果工作于计数模式,则表示计数值已满。

以定时器0工作模式1为例,定时10ms,把计算得到的初值写入TH0和TL0寄存器即可:

TH0 = 0xdb;或者TH0 = (65535-10000)/256;

TL0 = 0xef;或者TL0 = (65535-10000)%256;

这里我们一般使用后面的表示方法,因为比较直观而且不用我们再算成16进制。对于这里的“/256和%256”,其实就跟我们平时使用的10进制数一样,低位取余“%”,高位取商“/”。256就是2^16。

那么如果为工作模式0(13位定时器),则应该除以(取余)2^5=32,先满足高八位填满,再填剩下的。

  1. 定时器定时初值的计算

该计算公式是以定时器工作模式1为例(2^16),不同的工作模式定时最大值不同,工作模式是几位定时器,就是2的多少次方。根据所需要的不超过最大定时值的定时时间来计算要给的初值。

图一、定时器定时初值的计算

  1. 定时器中断用到的寄存器

每个中断源都对应着一个固定的入口地址,也就是中断向量,它们分别是:

0 0x0003: INT0

1 0x000B: TF0

2 0x0013: INT1

3 0x001B: TF1

4 0x0023: RI/TI

图二、IE寄存器

图三、IP寄存器

图四、TCON寄存器

图五、SCON寄存器

图六、TMOD寄存器

总开关,总中断EA,只有当总中断EA接上之后,同时相应的中断EX0、ET0等也接上,外部中断才能控制内核。

图七、中断寄存器的顺序

  1. 关于定时器中断服务函数程序的编写(与外部中断服务函数类似,框架一样,只是函数里面的内容不一样)

一般情况下,中断的处理函数有两个,其一为中断初始化函数,其二为中断服务函数。

初始化函数就是一个普通的函数,而中断服务函数有着特殊的格式:

①中断函数没有返回值,也不能对其输入参数;

②函数名后面要跟一个关键字“interrupt”,说明这是一个中断服务函数;

③在关键字“interrupt”后面要跟上中断号,说明这个中断服务函数是为哪个中断服务的

例如:

void 函数名() interrupt 中断号

以上关于定时器中断的介绍并不像书上以及老师们讲的那么专业,都只是本人学习过程中的理解总结而已。如果读者想要了解的更完整、更精细,可以查看相关方面的书和资料。也欢迎各位给我提出意见。

二、模块控制实现过程简述

要控制LED模块,就需要先往74HC138译码器中写入二进制数100(十进制数为4),输出就是Y4为低电平,经过一个或非门输出的Y4C就为高电平,再输入74HC573锁存器。然后控制LED灯的点亮。然后用定时器设置初值时间控制LED灯的闪烁。

三、所要实现的功能

用定时器T0的模式一,定时实现每1秒L1指示灯闪烁一下,即周期为2。每5秒L8指示灯闪烁一下,即周期为10。程序循环实现上述功能。

四、代码实现

①参数以及引脚定义

// LED灯引脚定义
sbit L1 = P0^0;
sbit L8 = P0^7;

// 参数定义
unsigned char count = 0;    // 定时器0计数

②138译码器通道选择函数

// 通道选择
void HC138_Init( unsigned char channel )
{
    switch( channel )
    {
        case 0:
            P2 = ( P2 & 0x1f ) | 0x00;    // 0
        break;
        case 4:
            P2 = ( P2 & 0x1f ) | 0x80;    // Y4C
        break;
        case 5:
            P2 = ( P2 & 0x1f ) | 0xa0;    // Y5C
        break;
        case 6:
            P2 = ( P2 & 0x1f ) | 0xc0;    // Y6C
        break;
        case 7:
            P2 = ( P2 & 0x1f ) | 0xe0;    // Y7C
        break;
    }
}

③初始化系统-关闭目前不需要的蜂鸣器和继电器

// 系统初始化
void System_Init(void)
{
    // 关闭LED灯
    HC138_Init( 4 );
    P0 = 0xff;
    
    // 关闭蜂鸣器和继电器
    HC138_Init( 5 );
    P0 = 0xaf;          // 1010 1111
    
    HC138_Init( 0 );    // 关闭通道选择
    P0 = 0xff;          // 初始化P0的值
}

④定时器0初始化函数

// 定时器0初始化函数
void Timer0_Init(void)
{
    TMOD = 0x01;    // 使用定时器0工作模式1
    ET0 = 1;
    TR0 = 1;
    EA = 1;
    
    // 计数初值
    TH0 = ( 65535 - 50000 ) / 256;
    TL0 = ( 65535 - 50000 ) % 256;
    
}

⑤定时器0服务函数

// 定时器0服务函数
void Timer0() interrupt 1
{
    // 由于是不能自动重装载的,所以要再次赋初值
    TH0 = ( 65535 - 50000 ) / 256;
    TL0 = ( 65535 - 50000 ) % 256;
    
    HC138_Init( 4 );
    count++;
    if( count % 20 == 0 )    // 一秒翻转一次电平
    {
        L1 = ~L1;
    }
    if( count == 100 )       // 五秒翻转一次电平
    {
        L8 = ~L8;
        count = 0;
    }
}

⑥整个函数展示


#include <STC15F2K60S2.H>


// LED灯引脚定义
sbit L1 = P0^0;
sbit L8 = P0^7;

// 参数定义
unsigned char count = 0;    // 定时器0计数


// 通道选择
void HC138_Init( unsigned char channel )
{
    switch( channel )
    {
        case 0:
            P2 = ( P2 & 0x1f ) | 0x00;    // 0
        break;
        case 4:
            P2 = ( P2 & 0x1f ) | 0x80;    // Y4C
        break;
        case 5:
            P2 = ( P2 & 0x1f ) | 0xa0;    // Y5C
        break;
        case 6:
            P2 = ( P2 & 0x1f ) | 0xc0;    // Y6C
        break;
        case 7:
            P2 = ( P2 & 0x1f ) | 0xe0;    // Y7C
        break;
    }
}


// 系统初始化
void System_Init(void)
{
    // 关闭LED灯
    HC138_Init( 4 );
    P0 = 0xff;
    
    // 关闭蜂鸣器和继电器
    HC138_Init( 5 );
    P0 = 0xaf;          // 1010 1111
    
    HC138_Init( 0 );    // 关闭通道选择
    P0 = 0xff;          // 初始化P0的值
}


// 定时器0初始化函数
void Timer0_Init(void)
{
    TMOD = 0x01;    // 使用定时器0工作模式1
    ET0 = 1;
    TR0 = 1;
    EA = 1;
    
    // 计数初值
    TH0 = ( 65535 - 50000 ) / 256;
    TL0 = ( 65535 - 50000 ) % 256;
    
}


// 定时器0服务函数
void Timer0() interrupt 1
{
    // 由于是不能自动重装载的,所以要再次赋初值
    TH0 = ( 65535 - 50000 ) / 256;
    TL0 = ( 65535 - 50000 ) % 256;
    
    HC138_Init( 4 );
    count++;
    if( count % 20 == 0 )    // 一秒翻转一次电平
    {
        L1 = ~L1;
    }
    if( count == 100 )       // 五秒翻转一次电平
    {
        L8 = ~L8;
        count = 0;
    }
}




int main(void)
{
    System_Init();    // 系统初始化
    Timer0_Init();    // 定时器0初始化
    while(1);
}

五、运行图片

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
单片机原理、接口及应用-嵌入式系统技术基础 是一本涵盖了单片机原理、接口以及应用的电子书。单片机是嵌入式系统的重要组成部分,它是一种集成电路,包含了处理器、内存和外设等功能模块单片机通过内部程序控制各个模块之间的协作,实现复杂的功能和任务。 这本电子书从基础单片机原理开始介绍,包括单片机的架构、指令系统、断和定时器等方面。读者可以了解单片机内部的组成和工作原理,为后续的学习打下坚实基础。 接着,在介绍完单片机原理后,电子书重点关注了单片机的接口技术。接口是单片机与外部设备之间进行数据和信号交换的桥梁。电子书详细介绍了并行口、串行口、模拟接口和总线接口等常见的单片机接口,并给出了实际电路和程序设计的案例。通过学习这些接口技术,读者可以掌握如何与外部设备进行数据通信和控制。 最后,电子书还介绍了嵌入式系统单片机应用。嵌入式系统是一种特定功能的计算机系统,广泛应用于家电、通信、汽车等领域。通过学习单片机应用,读者可以了解到嵌入式系统在实际生活和工业应用案例,从而更加深入地理解单片机技术的实际价值和应用前景。 总的来说,这本电子书通过系统全面的介绍单片机原理、接口和应用,可以帮助读者建立起对嵌入式系统技术的基础理论和实践能力。无论是初学者还是有一定基础的读者,都可以从获得丰富的知识和经验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汽小迪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值