基于C8051F340单片机的定时器0 工作在方式2——8位自动重载定时器程序

一、前言

C8051F340单片的定时器0有4种工作方式,分别是:
方式0——13 位计数器/定时器
方式1——16 位计数器/定时器
方式2——自动重装载的 8 位计数器/定时器
方式3——两个 8 位计数器/定时器
本文介绍工作在方式2——8 位自动重装载计数器/定时器的情况。
方式 2 将定时器 0 配置为具有自动重新装入计数初值能力的 8 位定时
器。TL0 保持计数值,而 TH0 保持重载值。当 TL0 中的计数值发生溢出(从全‘1’到 0x00)时,定时器溢出标志 TF0(TCON.5)被置位,TH0 中的重载值被重新装入到 TL0。如果允许中断,在 TF0 被置位时将产生一个中断。TH0 中的重载值保持不变。为了保证第一次计数正确,必须在允许定时器之前将 TL0 初始化为所希望的计数初值。

二、程序展示

1、程序简介

通过定时器0计时,控制LED灯的闪烁(100ms闪烁一次)。使用单片机内部的12M晶振,进行硬件48分频,并进行软件8分频,目的是为了让计时器能够计100ms级。
X*48 * 8/12000000=0.001(100ms) X=31,也就是计数器需要计31次数,定时器0总共可以计2的8次方次数,也就是256次,因为是从0开始计,最多计导255次,现需要计31次,则计时器的初始值应该为255-31=224次。

2、头文件部分

#include <C8051F340.h>
#define SYSCLK 12000000/8  //软件进行8分频
#define TIMER0_PRESCALE 48  //通过寄存器设置的分频数
#define LED_CHG_RATE 100 //设置LED灯的闪烁频率,100代表100ms
#define TIMER0_TICK_PER_MS  SYSCLK/TIMER0_PRESCALE/1000
#define REG1 TIMER0_TICK_PER_MS
#define REG2 0xFF-REG1
#define RELOAD_HIGH  REG2  // 高位重载
sbit LED1 = P2^2;  //通过P2.2输出驱动LED灯闪烁
void Port_Init (void);  //端口初始化
void Timer0_Init (void);    //定时器0初始化

3、主程序部分

{
   PCA0MD &= ~0x40;    // 关闭看门狗
   Timer0_Init ();     // 定时器0初始化
   Port_Init ();       // 端口初始化
   EA = 1;             // 允许中断

   while (1);       
}

4、端口初始化

void Port_Init (void)
{
   XBR1 = 0x40;
   P2MDOUT = 0x0C;     //设置P2.2推挽输出
}

5、定时器0初始化程序

void Timer0_Init(void)
{
   TH0 = RELOAD_HIGH;
   TL0 = TH0;
   TMOD = 0x02;                        // 设置工作在8位模式
   CKCON = 0x02;                       // 设置系统时钟48分频
   ET0 = 1;                            // 定时器0终端允许
   TCON = 0x10;                        // 定时器0打开
}

6、定时器0中断程序

void Timer0_ISR (void) interrupt 1
{
   static int counter = 0;

   if((counter++) == LED_CHG_RATE) 
   {
      LED = ~LED;             // LED灯闪烁
      counter = 0;
   }
}

8位的计数器最多只能计255488/12000000*1000=8.16ms,前面设置的TH0的值是让其1ms中断一次,通过软件counter++到100次,来达到计时100ms的目的。

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 可以。以下是使用 SN8F5702 单片机定时器0方式2实现 100us 中断的时间片框架示例代码: ``` #include <SN8F5702.h> unsigned int tick = 0; void timer0_isr() interrupt 1 { tick++; TH0 = 0xFC; TL0 = 0x66; } void main() { TMOD = 0x10; // 定时器0工作方式2 TH0 = 0xFC; TL0 = 0x66; ET0 = 1; // 开启定时器0中断 TR0 = 1; // 启动定时器0 while (1) { if (tick % 10 == 0) { // 每隔10个tick执行一次任务 // task1(); } if (tick % 20 == 0) { // 每隔20个tick执行一次任务 // task2(); } } } ``` 注意: - 定时器0的频率是晶振频率的12倍,所以实际中断间隔可能会有误差。 - 定时器0的初始值是0xFC66,则每次计数器值减少1,中断间隔时间就是100us。 - 任务函数 task1() 和 task2() 需要自己实现。 - 使用该程序要确保开启了定时器0中断,并且使能了定时器0。 ### 回答2: 当然可以,以下是一个使用SN8F5702单片机定时器0方式2中断100us实现的时间片框架示例: ```c #include <SN8F5702.h> #define TASK1_INTERVAL 1000 // 任务1执行间隔为1ms #define TASK2_INTERVAL 2000 // 任务2执行间隔为2ms #define TASK3_INTERVAL 5000 // 任务3执行间隔为5ms volatile unsigned int task_counter1 = 0; volatile unsigned int task_counter2 = 0; volatile unsigned int task_counter3 = 0; void T0_ISR(void) interrupt 1 // 定时器0中断服务函数 { if (TF0) // 判断定时器溢出 { TF0 = 0; // 清除溢出标志 TH0 = 0xFF; TL0 = 0x9C; // 设置100us的重载值 } // 任务执行计数递增 task_counter1++; task_counter2++; task_counter3++; // 判断任务执行间隔 if (task_counter1 >= TASK1_INTERVAL) { // 执行任务1 task_counter1 = 0; // ... } if (task_counter2 >= TASK2_INTERVAL) { // 执行任务2 task_counter2 = 0; // ... } if (task_counter3 >= TASK3_INTERVAL) { // 执行任务3 task_counter3 = 0; // ... } } void main() { TMOD = 0x01; // 设置定时器0为工作模式1(16位定时器),使用方式2定时中断 TH0 = 0xFF; TL0 = 0x9C; // 设置100us的重载值 TR0 = 1; // 启动定时器0 ET0 = 1; // 允许定时器0中断 EA = 1; // 允许总中断 while (1) { // 主循环 } } ``` 在上述示例中,通过SN8F5702单片机定时器0方式2中断功能实现了一个简单的时间片框架。其中,通过设置定时器0的重载值为100us,每次中断后,根据任务执行计数,判断是否到达了任务执行间隔,并执行对应的任务函数。任务执行间隔通过设定不同的计数器变量以及对应的宏定义来实现。 需要注意的是,在实际应用中,除了任务执行的时间间隔,在任务执行完成后可能还需进行切换任务的相关操作,以实现多任务协同工作。此处仅提供了一个简单的时间片框架示例,具体的实现还需根据具体需求进行适当调整和扩展。 ### 回答3: 可以的,以下是一个使用SN8F5702单片机定时器0方式2和100us中断的时间片框架示例。 首先,需要定义一个全局变量time_slice,用来表示每个任务占用的时间片数量。 接着,在main函数中使用定时器模块初始化函数和中断使能函数,设置定时器工作方式方式2,中断时间为100us,并启动定时器。 然后,在中断服务函数中,先判断当前时间片是否用完,若用完则重新分配时间片给下一个任务。具体的实现可以使用一个任务列表,每个任务都有一个计数器count,表示该任务剩余可执行的时间片数。当count减为0时,即代表该任务需要被切换出去执行下一个任务。 接下来,使用一个无限循环来不断运行任务。在循环中,先判断当前任务是否仍有剩余时间片,若有则执行当前任务的代码,然后将计数器count减1。若没有剩余时间片,则切换到下一个任务执行。 最后,使用一个任务切换函数来分配时间片给下一个任务。该函数先将当前任务的计数器count重置为time_slice,然后切换到下一个任务。 总结一下,上述时间片框架示例利用SN8F5702单片机定时器0方式2和100us中断来实现多任务的轮流执行。每个任务被分配一个固定的时间片,在时间片用完后自动切换到下一个任务执行。这样就能够实现任务之间的快速切换,提高系统的并发性和实时性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

xll_007

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

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

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

打赏作者

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

抵扣说明:

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

余额充值