C语言——时基
- 创业
- 2025-08-27 20:45:02

上图中,每一个小格代表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。
//为了保证该程序的通用性,在这里定义成一个八位的变量 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取反一次,按照平时的思路写出的代码如下:
//延时函数 void D100ms(void){ uint16_t i = 0; for (i=0;i<60000;i++){ } } while(1){ P1 = ~P1;//取反 D100ms();//通过调用延时函数来实现延时100ms }如果运用我们上面所写的时基,则可以写成:
//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位。
#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标志 }上一篇
V4L2驱动之UVC