定时器——时基
一、时基的介绍
如下图,每一个标志(Flag_1ms)就代表一个时基,在不同的时基下可以做不同的事情。
以下是对不同时基的处理,通过1ms进而生成1s的时基。
// 1ms处理
if( Flag_1ms ){ // 1ms标志==1 1ms的时间到了
Flag_1ms = 0; // 标志清零
Cnt_1ms++;
if( Cnt_1ms >= 10 ){ // 计数够10次
Cnt_1ms = 0; // 计数器清零
Flag_10ms = 1; // 置10ms的标志
}
}// 1ms处理结束
// 10ms处理
if( Flag_10ms ){ // 10ms标志==1 10ms的时间到了
Flag_10ms = 0; // 标志清零
Cnt_10ms++;
if( Cnt_10ms >= 10 ){ // 计数够10次
Cnt_10ms = 0; // 计数器清零
Flag_100ms = 1; // 置100ms的标志
}
}// 10ms处理结束
// 100ms处理
if( Flag_100ms ){ // 100ms标志==1 100ms的时间到了
Flag_100ms = 0; // 标志清零
Cnt_100ms++;
if( Cnt_100ms >= 10 ){ // 计数够10次
Cnt_100ms = 0; // 计数器清零
Flag_1s = 1; // 置1s的标志
}
// 指示灯的 左移 右移 输出函数
// 每100ms调用一次
funLED(); //
}// 100ms处理结束
// 1s处理
if( Flag_1s ){ // 1s标志==1 1s的时间到了
Flag_1s = 0; // 标志清零
Cnt_1s++;
Cnt_mode++;
if( Cnt_mode >= 10 ){
Cnt_mode = 0;
mode = ~mode;
}
}// 1s处理结束
二、时基的应用
这种情况下的延时,CPU是不能做其他事情的。
但是如果放到时基里面去,每100ms执行一次,然后可以继续进行不同的事情。因此,用时基也可以达到软件延时一样的效果。
三、应用实例
/*======================================================================
功能需求
1、P1.5-P1.0指示灯左移或右移控制
2、模式可随时切换 或 外部可修改 工作模式
======================================================================*/
/*======================================================================
时基
1、时基的基本概念
2、时基下实现时序控制的方法
3、任务拆解或打散
4、控制接口实现的方法
======================================================================*/
#include "STC12C5A60S2.H"
#include "c51_stdint.h"
// 输出表
uint8_t code LED_TAB[ ] = { // 右移表 索引号加 // 索引号减 左移
(uint8_t)(1 << 5), // 0
(uint8_t)(1 << 4), // 1
(uint8_t)(1 << 3), // 2
(uint8_t)(1 << 2), // 3
(uint8_t)(1 << 1), // 4
(uint8_t)(1 << 0) // 5
};
// 索引号
uint8_t Index = 0;
// 模式 // 10秒切换一次
uint8_t mode = 0; // 0:右移
// 1:左移
uint8_t Cnt_mode = 0;
uint8_t Cnt_LED = 0;
// 指示灯的 左移 右移 输出函数
// 每100ms调用一次
void funLED( void ){
P1 = ~LED_TAB[ Index ];
Cnt_LED++;
if( Cnt_LED >= 5 ){
Cnt_LED = 0;
if( mode ){ // 左移
Index--; // 0-1 = 255 Index是无符号的数
if( Index > 5 ){ // 越界处理
Index = 5; //
}
}
else{ // 右移
Index++;
if( Index > 5 ){ // 越界处理
Index = 0;
}
}
}
}
延时
//void D100ms( void ){
// uint16_t i = 0;
// for( i = 0; i < 60000; i++ ){
//
// }
//}
uint8_t Flag_1ms = 0;
uint8_t Cnt_1ms = 0;
uint8_t Flag_10ms = 0;
uint8_t Cnt_10ms = 0;
uint8_t Flag_100ms = 0;
uint8_t Cnt_100ms = 0;
uint8_t Flag_1s = 0;
uint8_t Cnt_1s = 0;
void Timer0_Init(void) //1000微秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x20; //设置定时初始值
TH0 = 0xD1; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
// 主程序
void main(void){
// 调用 定时器0 初始化
Timer0_Init();
// 开定时器T0 的中断
ET0 = 1;
// 开总中断
EA = 1;
while(1){
// 1ms处理
if( Flag_1ms ){ // 1ms标志==1 1ms的时间到了
Flag_1ms = 0; // 标志清零
Cnt_1ms++;
if( Cnt_1ms >= 10 ){ // 计数够10次
Cnt_1ms = 0; // 计数器清零
Flag_10ms = 1; // 置10ms的标志
}
}// 1ms处理结束
// 10ms处理
if( Flag_10ms ){ // 10ms标志==1 10ms的时间到了
Flag_10ms = 0; // 标志清零
Cnt_10ms++;
if( Cnt_10ms >= 10 ){ // 计数够10次
Cnt_10ms = 0; // 计数器清零
Flag_100ms = 1; // 置100ms的标志
}
}// 10ms处理结束
// 100ms处理
if( Flag_100ms ){ // 100ms标志==1 100ms的时间到了
Flag_100ms = 0; // 标志清零
Cnt_100ms++;
if( Cnt_100ms >= 10 ){ // 计数够10次
Cnt_100ms = 0; // 计数器清零
Flag_1s = 1; // 置1s的标志
}
// 指示灯的 左移 右移 输出函数
// 每100ms调用一次
funLED(); //
}// 100ms处理结束
// 1s处理
if( Flag_1s ){ // 1s标志==1 1s的时间到了
Flag_1s = 0; // 标志清零
Cnt_1s++;
Cnt_mode++;
if( Cnt_mode >= 10 ){
Cnt_mode = 0;
mode = ~mode;
}
}// 1s处理结束
}
}
// 中断服务程序 T0的
// 关键字 中断号 关键字 工作寄存器组
void ISR_T0( void ) interrupt 1 using 0
{
Flag_1ms = 1; // 置1ms标志
}
提示:
!和~均表示取反,这两个的区别在于:
! :代表逻辑取反,即:把非0的数值变为0,0变为1;
~ :表示按位取反,即在数值的二进制表示方式上,将0变为1,将1变为0;