C语言——时基

上图中,每一个小格代表1ms时间,每1ms产生1ms的标志Flag_1ms,该标志变为1,Cnt_1ms为计数器,每检测到1ms计数器加1,计数器加1后,1ms的标志清零,直到再经过1ms,Flag_1ms再变成1。

与上述1ms的原理相同,每1ms计数器加1,达到10ms时,10ms的标志变为1,10ms计数器加1,然后10ms的标志清零,经过10次计数后达到100ms,此时100ms的标志变为1,100ms的计数器加1,经过10次计数后达到1s,1s的标志变为1,1s的计数器加1。

cs 复制代码
//为了保证该程序的通用性,在这里定义成一个八位的变量
uint8_t Flag_1ms = 0;//1ms标志的初始值为0
uint8_t Cnt_1ms = 0;//1ms计数器的初始值也为0

uint8_t Flag_10ms = 0;//10ms标志的初始值为0
uint8_t Cnt_10ms = 0;//10ms计数器的初始值也为0

uint8_t Flag_100ms = 0;//100ms标志的初始值为0
uint8_t Cnt_100ms = 0;//100ms计数器的初始值也为0

uint8_t Flag_1s = 0;//1s标志的初始值为0
uint8_t Cnt_1s = 0;//1s计数器的初始值也为0

void main(void){
    while(1){
        //1ms处理
        if(Flag_1ms){    //1ms标志==1 表示1ms时间到了
            Flag_1ms = 0;//1ms标志清零
            Cnt_1ms++;    //计数器加1
            if(Cnt_1ms >= 10){ //计数够10次
                Cnt_1ms = 0;   //计数器清零
                Flag_10ms = 1; //置10ms的标志
            }
        }//1ms处理结束

        //10ms处理
        if(Flag_10ms){    //10ms标志==1 表示10ms时间到了
            Flag_10ms = 0;//10ms标志清零
            Cnt_10ms++;    //计数器加1
            if(Cnt_10ms >= 10){ //计数够10次
                Cnt_10ms = 0;   //计数器清零
                Flag_100ms = 1; //置100ms的标志
            }
        }//10ms处理结束

        //100ms处理
        if(Flag_100ms){    //100ms标志==1 表示100ms时间到了
            Flag_100ms = 0;//100ms标志清零
            Cnt_100ms++;    //计数器加1
            if(Cnt_100ms >= 10){ //计数够10次
                Cnt_100ms = 0;   //计数器清零
                Flag_1s = 1; //置1s的标志
            }
        }//100ms处理结束

        //1s处理
        if(Flag_1s){    //1s标志==1 表示1s时间到了
            Flag_1s = 0;//1s标志清零
            Cnt_1s++;    //计数器加1
        }//1s处理结束
    }
}

上述程序实现了1ms生成10ms的时基,10ms生成100ms的时基,100ms生成1s的时基。

若要实现让1个LED每100ms取反一次,按照平时的思路写出的代码如下:

cs 复制代码
//延时函数
void D100ms(void){
    uint16_t i = 0;
    for (i=0;i<60000;i++){

    }
}

while(1){
    P1 = ~P1;//取反
    D100ms();//通过调用延时函数来实现延时100ms
}

如果运用我们上面所写的时基,则可以写成:

cs 复制代码
//100ms处理
        if(Flag_100ms){    //100ms标志==1 表示100ms时间到了
            Flag_100ms = 0;//100ms标志清零
            Cnt_100ms++;    //计数器加1
            if(Cnt_100ms >= 10){ //计数够10次
                Cnt_100ms = 0;   //计数器清零
                Flag_1s = 1; //置1s的标志
            }
            //P1每100ms取反一次
            P1 = ~P1;
        }//100ms处理结束

**[区别]**如果通过延时函数去进行延时的话,在延时的过程中CPU不能处理其他事情,但是如果放到时基里,在执行完该程序后可以继续执行其他程序。

例题

功能需求:1.P1.5-P1.0指示灯,每0.5秒左移或右移控制

2.模式可以随时切换 或 外部可修改 工作模式

P1.5-P1.0对应LED4-LED9,注意在硬件控制上有一个取反的过程,控制与逻辑相反,低电平-亮 高电平-灭。为了与人的惯性思维保持一致,在编码时,1-亮 0-灭,输出时进行取反即可(也可以在定义时取反)。

图片中 1<<5 表示1左移5位,即0000 0001中的1左移5位。

cs 复制代码
#include "STC12C5A60S2.H"
#include "c51_stdint.h"

//输出表,左移还是右移取决于从表中取下一个数时让索引号加还是减
//索引号加-右移    索引号减-左移
uint8_t code LED_TAB[] = { //uint8_t代表数据类型,code表示数据存放到ROM中,LED_TAB是表的名字
    (uint8_t)(1 << 5),//0    强制类型转换,将其定义为8位的无符号数
    (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;//初始值为0

//模式    //10秒切换一次
uint8_t mode = 0;//0:右移    1:左移

//设置一个模式的计数器
uint8_t Cnt_mode = 0;

//由于没有500ms的时基,所以需要再加一个计数器
uint8_t Cnt_LED = 0;

//指示灯的左移 右移 输出函数
//每100ms调用一次,这样就不必再另外添加延时函数了
void funLED(void){
    P1 = ~LED_TAB[Index];//100ms刷新一次

    Cnt_LED++;
    if(Cnt_LED >= 5){//表示到500ms了
        Cnt_LED = 0;//标志清零
    
    }

    if(mode){    //mode非零-左移
        Index--;//因为Index是无符号数,所以0-1=255
        if(Index > 5){    //越界处理
            Index = 5;
        }
    }
    else{    //右移
        Index++;
        if(Index > 5){    //越界处理
            Index = 0;
        }
    }
}

//为了保证该程序的通用性,在这里定义成一个八位的变量
uint8_t Flag_1ms = 0;//1ms标志的初始值为0
uint8_t Cnt_1ms = 0;//1ms计数器的初始值也为0

uint8_t Flag_10ms = 0;//10ms标志的初始值为0
uint8_t Cnt_10ms = 0;//10ms计数器的初始值也为0

uint8_t Flag_100ms = 0;//100ms标志的初始值为0
uint8_t Cnt_100ms = 0;//100ms计数器的初始值也为0

uint8_t Flag_1s = 0;//1s标志的初始值为0
uint8_t Cnt_1s = 0;//1s计数器的初始值也为0

//利用STC-ISP生成1ms
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){

    //调用定时器初始化
    Timer0_Init();

    //打开定时器T0的中断
    ET0 = 1;
    
    //打开总中断
    EA = 1;
    
    while(1){
        //1ms处理
        if(Flag_1ms){    //1ms标志==1 表示1ms时间到了
            Flag_1ms = 0;//1ms标志清零
            Cnt_1ms++;    //计数器加1
            if(Cnt_1ms >= 10){ //计数够10次
                Cnt_1ms = 0;   //计数器清零
                Flag_10ms = 1; //置10ms的标志
            }
        }//1ms处理结束

        //10ms处理
        if(Flag_10ms){    //10ms标志==1 表示10ms时间到了
            Flag_10ms = 0;//10ms标志清零
            Cnt_10ms++;    //计数器加1
            if(Cnt_10ms >= 10){ //计数够10次
                Cnt_10ms = 0;   //计数器清零
                Flag_100ms = 1; //置100ms的标志
            }
        }//10ms处理结束

        //100ms处理
        if(Flag_100ms){    //100ms标志==1 表示100ms时间到了
            Flag_100ms = 0;//100ms标志清零
            Cnt_100ms++;    //计数器加1
            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;//1s标志清零
            Cnt_1s++;    //计数器加1
            Cnt_mode++;
            if(Cnt_mode >= 10){ //达到10s
                Cnt_mode = 0;//计数器清零
                mode = !mode;//模式取反
            }
        }//1s处理结束
    }
}

//中断服务程序与主程序无关
//interrupt是关键字,1是中断号,using是关键字,0表明用哪一个工作寄存器组
void ISR_T0(void) interrupt 1 using 0
{
    Flag_1ms = 1;//置1ms标志
}

注: 本文出自对bilibili 科大老孟C语言_002_时基 内容的学习笔记。

相关推荐
喜欢吃燃面11 分钟前
C++算法竞赛:位运算
开发语言·c++·学习·算法
传奇开心果编程11 分钟前
【传奇开心果系列】Flet框架实现的家庭记账本示例自定义模板
python·学习·ui·前端框架·自动化
草莓熊Lotso14 分钟前
《详解 C++ Date 类的设计与实现:从运算符重载到功能测试》
开发语言·c++·经验分享·笔记·其他
_Kayo_6 小时前
node.js 学习笔记3 HTTP
笔记·学习
CCCC13101639 小时前
嵌入式学习(day 28)线程
jvm·学习
星星火柴93610 小时前
关于“双指针法“的总结
数据结构·c++·笔记·学习·算法
小狗爱吃黄桃罐头10 小时前
正点原子【第四期】Linux之驱动开发篇学习笔记-1.1 Linux驱动开发与裸机开发的区别
linux·驱动开发·学习
艾莉丝努力练剑11 小时前
【洛谷刷题】用C语言和C++做一些入门题,练习洛谷IDE模式:分支机构(一)
c语言·开发语言·数据结构·c++·学习·算法
武昌库里写JAVA12 小时前
JAVA面试汇总(四)JVM(一)
java·vue.js·spring boot·sql·学习
Cx330❀13 小时前
【数据结构初阶】--排序(五):计数排序,排序算法复杂度对比和稳定性分析
c语言·数据结构·经验分享·笔记·算法·排序算法