5 28

一个嵌入式软件定时器的设计

概述

在嵌入式系统里面,相对来说定时器的资源是比较紧缺的,并且定时器是比较精确的,有些时候可能我们需要大量的定时任务,并且并不一定要非常精确的定时器,比如ms级别的定时,s级别的定时器,这个时候我们就需要设计一些软件定时器来做这些需求。

最原始的软件定时器

如果我们现在有一个us定时器,我们还需要一个ms定时器,我们想到最简单的办法就是定义一个变量在中断里面累加,如下代码所示:

uint32_t Timer = 0;;
//main 函数
int main()
{
    //初始化,启动us定时器,
    while(1)
    {}
}
//中断函数
void TIM_IRQ interrupt 0
{
    Timer++; 
    if (Timer == 1000)
    {
        Timer = 0;
        //执行定时任务
    }
}

看上面的一个定时器,这是软件定时器的雏形,就是在中断函数里面不断的累加一个变量到达定时时间之后开始执行中断函数。这也是软件定时器最核心的东西,但是如果大量的定时器都像上面那样写,我们的中断函数里面要写很多的东西,显得很乱,我们希望更多的业务逻辑尽量不要写在中断函数里面,我们对上面的代码改版,出现了下面的代码:


uint32_t Timer = 0;;
//main 函数
int main()
{
    //初始化,启动us定时器,
    Timer = 1000;
    while(1)
    {
        if (Timer <= 0)
        {
            //执行定时任务
        }
    }
}
//中断函数
void TIM_IRQ interrupt 0
{
    if (Timer>0)
    {
        Timer--;    
    }
}

上面的代码看上去稍微好看了一点点,我们把中断处理逻辑移动到了main函数里面处理,现在还是有问题的,我们每启动一个定时器,需要定义一个变量,中断函数里面添加一段逻辑,有时候可能我们的代码是分层写的,驱动和应用是分层写的,于是就出现了一边在写应用层逻辑,一遍还要去中断里面添加定时器,我们设计思路是定义一些定时器,先用着,怎么定义呢,先定义一个定时器数组,看下面代码:


//定义定时器
#define TIME_COUNT  12
int32_t timer[TIME_COUNT] ={-1}; 

//申请一个定时器
int apply_timer(uint32_t time)
{
    //遍历所有定时器,查找未使用定时器
    for(int i = 0;i <TIME_COUNT i++)
    {
        if (timer[i] == -1)//有空闲定时器
        {
            timer[i] = time;
            return i;
        }
    }
    return -1;
}
int read_timer(int id)
{
    return timer[id];
}
//main 函数
int main()
{
    //初始化,启动us定时器,
    int id1 = apply_timer(1000)
    if (id1 == -1)
        printf("apply faild\r\n");
    int id2 = apply_timer(1000)
    if (id2 == -1)
        printf("apply faild\r\n");
    while(1)
    {
        if (read_timer(id1) <= 0)
        {
            //执行定时任务1
        }
        if (read_timer(id2) <= 0)
        {
            //执行定时任务2
        }
    }
}
//中断函数
void TIM_IRQ interrupt 0
{
    for(int i = 0;i <TIME_COUNT i++)
    {
        if (timer[i]>0)
            timer[i]--;
    }
}

上面的代码实现了一个静态的软件定时器,基本分离了驱动层代码和应用层的业务逻辑,但是静态的定时器,静态的定时器我们就不能在程序运行中动态的申请定时器,或者我们预留足够的定时器留给程序中动态申请,但是,资源是紧缺的,我们预留的定时器在一段时间内是不用的,但是同样的还会占用系统资源,我们继续改造定时器,用链表和指针,构造终极定时器,代码见码云:

https://gitee.com/zyzp/codes/ut39rhm61q4vk2yd5bsog46

下次解释代码设计的思路

5 25

码云代码片段链接

码云记载的一些代码片段链接:

1、C语言数据类型转换:https://gitee.com/zyzp/codes/ogurzp3ab0sdh8l2me1fi40
2、C语言打印格式化:https://gitee.com/zyzp/codes/flye34ukgmj2nrv69c5od12
3、C语言软件定时器实现:https://gitee.com/zyzp/codes/ut39rhm61q4vk2yd5bsog46
4、锂电池电量计算:https://gitee.com/zyzp/codes/s0lkgzqywdv6f421xn7cr92
5、C# combobox 选择对应的项:https://gitee.com/zyzp/codes/jsk7g6rvi4wxqpo8mydfe71

5 18

Linux 下面screen命令的用法

最近在使用阿里云的Linux 云服务做毕业设计遇到一些问题,我把java的jar运行程序上传之后,使用java -jar server命令之后程序开始正常运行,但是当我关闭终端的时候程序也随着关闭了,这怎么可以,随后我就百度了一番。发现有一个叫做screen的东西,下面把关于这些内容简单做了个小节,记下来,后面用的到

打开一个screen对话
    screen 
浏览当前的screen对话
    screen -ls
关闭screen对话
    screen  -X -S name quit
恢复上次的screen对话
    screen -r

基本使用了上面的几条指令我的目前够用了

5 16

JAVA 环境变量配置

配置”JAVA_HOME”

变量名:JAVA_HOME
变量值:C:\Program Files (x86)\Java\jdk1.8.0_144
注意:该变量值为java安装路径

配置”path”

变量名:Path
变量值:%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;

配置”CLASSPATH”

变量名:CLASSPATH
变量值:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;

注意事项

1.配置环境变量的位置在 我的电脑右键->管理->高级系统设置->高级->环境变量.
2.如果需要每个用户都使用,需要配置系统环境变量。
3.javahome选择安装的java的路径下面。

以前的