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。

//为了保证该程序的通用性,在这里定义成一个八位的变量
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标志
}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/972767.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【16】思科AireOS:创建使用 LWA 认证的 WLAN

1. 概述 LWA(Local Web Authentication)是一种基于 Web 认证的方式,允许无线客户端在连接 WLAN 后,使用 Web 认证页面进行身份验证。该方法适用于访客网络或需要身份认证的场景。 本指南详细介绍如何在 Cisco AireOS 无线控制器(WLC)上配置 LWA 认证的 WLAN,并确保认证…

用户管理中心---前端页面设计测试登录功能

文章目录 1.前端页面的替换1.1修改页面底部 2.代码的修改2.1删除无关代码2.2修改参数和接口2.3添加请求配置2.4修改代理 3.测试登录功能 1.前端页面的替换 原来的登录页面 1.1修改页面底部 原来的这个页面底部显示的是Ant design pro相关的链接&#xff0c;我们自己做项目&am…

MySQL登录问题总结

不管何种数据库&#xff0c;使用的第一步都是先登录。 MySQL命令行登录语句&#xff1a;mysql -u username -P port -p -D database_name 登录MySQL的报错一般从报错信息都能得到反馈&#xff0c;常见报错原因分析如下&#xff0c;实例中的以test用户为例&#xff0c;登录环境为…

GitCode 助力至善云学:构建智慧教育平台

项目仓库&#xff1a; 前端&#xff1a;https://gitcode.com/Fer_Amiya/vue-ZhiShanYunXue-Client 后端&#xff1a;https://gitcode.com/Fer_Amiya/go-ZhiShanYunXue-Server 突破传统教学困境&#xff0c;探索教育新解法 传统教学的习题讲评环节&#xff0c;教师面临着难以…

保护大数据的最佳实践方案

在当今数字化时代&#xff0c;保障大数据安全的重要性再怎么强调也不为过。 随着科技的迅猛发展以及对数据驱动决策的依赖日益加深&#xff0c;企业必须将保护其宝贵信息置于首位。 我们将深入探讨保障大数据安全的流程&#xff0c;并讨论关键原则、策略、工具及技术&#xf…

Go 之 Windows下 Beego 项目的搭建

一、GO 环境配置 从 Go 1.11 开始&#xff0c;Go 引入了模块&#xff08;Modules&#xff09;的概念&#xff0c;允许你在任何位置创建和管理 Go 项目&#xff0c;而不需要将它们放在 $GOPATH/src 下。Go Modules 使用 go.mod 文件来管理依赖项和版本信息。 查看GOPATH位置 D…

Day6 25/2/19 WED

【一周刷爆LeetCode&#xff0c;算法大神左神&#xff08;左程云&#xff09;耗时100天打造算法与数据结构基础到高级全家桶教程&#xff0c;直击BTAJ等一线大厂必问算法面试题真题详解&#xff08;马士兵&#xff09;】https://www.bilibili.com/video/BV13g41157hK?p4&v…

【分布式理论12】事务协调者高可用:分布式选举算法

文章目录 一、分布式系统中事务协调的问题二、分布式选举算法1. Bully算法2. Raft算法3. ZAB算法 三、小结与比较 一、分布式系统中事务协调的问题 在分布式系统中&#xff0c;常常有多个节点&#xff08;应用&#xff09;共同处理不同的事务和资源。前文 【分布式理论9】分布式…

驱动开发系列37 - Linux Graphics 2D 绘制流程(二)- 画布创建和窗口关联

一:概述 前面介绍Pixmap表示一块画布,是绘制发生的地方,本节看看驱动程序如何为画布分配内存/显存,以及如何与窗口关联的。 二:为画布分配BO 在系统启动时(用户登录系统之后,会重启Xorg),在 Xorg 服务器初始化时,要为屏幕创建根窗口的 Pixmap,并绑定到 GPU framebu…

DeepSeek服务器繁忙 多种方式继续优雅的使用它

前言 你的DeepSeek最近是不是总是提示”服务器繁忙,请稍后再试。”&#xff0c;尝试过了多次重新生成后&#xff0c;还是如此。之前DeepSeek官网连续发布2条公告称&#xff0c;DeepSeek线上服务受到大规模恶意攻击。该平台的对话框疑似遭遇了“分布式拒绝服务攻击”&#xff0…

【Mpx】-环境搭建项目创建(一)

一.概述 官方文档&#xff1a;https://mpxjs.cn/guide/basic/start.html mpxjs/cli文档: https://github.com/mpx-ecology/mpx-cli 二.脚手架安装&创建项目 2.1项目创建 //脚手架安装 npm i -g mpxjs/cli //创建Mpx项目 mpx create mpx-demo(项目名称) //安装依赖 np…

【快速入门】Unity 常用组件(功能块)

欢迎关注 、订阅专栏 【unity 新手教程】谢谢你的支持&#xff01;&#x1f49c;&#x1f49c; 文章目录 Unity 常用组件&#xff08;功能块&#xff09;&#xff1a;Transform - 变换&#xff1a;坐标、朝向、大小Mesh Filter - 加载网格数据Mesh Renderer- 渲染网格Camera - …

python爬虫系列课程2:如何下载Xpath Helper

python爬虫系列课程2:如何下载Xpath Helper 一、访问极简插件官网二、点击搜索按钮三、输入xpath并点击搜索四、点击推荐下载五、将下载下来的文件解压缩六、打开扩展程序界面七、将xpath.crx文件拖入扩展程序界面一、访问极简插件官网 极简插件官网地址:https://chrome.zzz…

Unity性能优化个人经验总结(不定期更新)

字符串 在使用常量或静态变量 Update、LateUpdate、FixedUpdate等每帧调用或调用频率很高的函数内使用字符串时&#xff0c;均使用常量或静态变量处理。 原因解释&#xff1a;除了常量或静态变量的字符串将会在每一次调用时&#xff0c;将会new一个新的字符串&#xff0c;导…

机器学习小项目之加利福尼亚房价数据分析

1. 安装必要的库 首先&#xff0c;确保安装了以下必要的 Python 库&#xff1a; pip install scikit-learn pandas matplotlib2. 导入所需库 在代码中&#xff0c;我们需要导入一些常用的库来处理数据、训练模型和评估结果&#xff1a; import pandas as pd import numpy a…

基于MATLAB的均匀面阵MUSIC算法DOA估计仿真

基于MATLAB的均匀面阵MUSIC算法DOA估计仿真 文章目录 前言一、二维MUSIC算法原理二、二维MUSIC算法MATLAB仿真三、MATLAB源代码总结 前言 \;\;\;\;\; 在波达角估计算法中&#xff0c;MUSIC 算法与ESPRIT算法属于特征结构子空间算法&#xff0c;是波达角估计算法中的基石。在前面…

【SQL】SQL多表查询

多表查询案例联系点击此处 &#x1f384;概念 一般我们说的多表查询都涉及外键和父子表之间的关系。比如一对多:一般前面指的是父表后面指的是子表。 ⭐分类 一对多(多对一) 多对多 一对一 ⭐一对多 &#x1f4e2;案例&#xff1a;部门与员工的关系 &#x1f4e2;关系&…

【架构】分层架构 (Layered Architecture)

一、分层模型基础理论 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/0365cf0bfa754229bdedca6b472bffc7.png 1. 核心定义 分层架构(Layered Architecture)模型是一种常见的软件设计架构,它将软件系统按照功能划分为不同的层次,每个层次都有特定的职责和功能…

2025年02月19日Github流行趋势

项目名称&#xff1a;OmniParser 项目地址url&#xff1a;https://github.com/microsoft/OmniParser 项目语言&#xff1a;Jupyter Notebook 历史star数&#xff1a;12878 今日star数&#xff1a;2153 项目维护者&#xff1a;yadong-lu, ThomasDh-C, aliencaocao, nmstoker, kr…

uni-app发起网络请求的三种方式

uni.request(OBJECT) 发起网络请求 具体参数可查看官方文档uni-app data:请求的参数; header&#xff1a;设置请求的 header&#xff0c;header 中不能设置 Referer&#xff1b; method&#xff1a;请求方法&#xff1b; timeout&#xff1a;超时时间&#xff0c;单位 ms&a…