05_ESP8266 NONOS_SDK Timer

今天学习三点内容:

                             一是延时函数,

                             二是软件定时器,

                             三是硬件定时器。

软件定时器就是靠里面的任务延时实现的,这样的定时器其实延时不准确。

硬件定时器 就是硬件中断定时器,就像单片机,中断的准确。

 

一、使用os_delay_us 函数

1、os_delay_us函数分析:

功能:      延时函数。最大值 65535 μs

函数定义:  void  os_delay_us(uint16 us)

参数:      uint16       us:延时时间

返回:      无

 

写一个毫秒延时函数(不能延时太久)   // 这种延时不太精确

void ICACHE_FLASH_ATTR  delay_ms(u32 ms_time)
{
      for(;ms_time>0; ms_time--)
      {
        os_delay_us(10000);
       }
}

主函数每隔1s打印一次

 

编译,下载固件,打开串口调试助手,看现象,每隔1s打印一次。

 

 

二、软件定时器

软件定时器由软件实现,定时器的函数在任务中被执行。因为任务可能被中断,或者被其他高优先级的任务延迟,因此软件定时器并不能保证定时器精确执行,如果需要精确的定时,建议用硬件定时器。

先看几个和软件定时器相关的函数:

 

 

 

步骤:

1、先添加头文件

 

2、定义全局变量

os_timer_t OS_Timer;        //定义软件定时器(os_timer_t型结构体)

u8 Led_Flag = 0;            //LED的状态标志位

3、定义软件定时的回调函数

我们在回调函数中实现LED灯的闪烁,输出LED的状态和进入回调函数的提示。

void ICACHE_FLASH_ATTR OS_Timer_cb(void)
{
   Led_Flag = !Led_Flag;  //LED状态翻转
//设置gpio4的输出值,即LED的值 GPIO_OUTPUT_SET(GPIO_ID_PIN(4),Led_Flag);
os_printf(
"\r\nLED的状态为:%d\r\n",Led_Flag); os_printf("\r\n-------------进入回调函数-------------\r\n"); }

4、封装软件定时器初始化函数(ms毫秒)

我们将函数进行封装,以便在初始化的时候直接调用。

(1)首先要关闭定时器,参数是要关闭的定时器

(2)接着设置定时器:

         第一个参数是:需要设置的定时器,

         第二个参数是:回调函数(需要要类型转换)

         第三个参数是:回调函数的参数

         注意:os_timer_setfn必须在软件定时器未使能的情况下调用

(3)使能毫秒定时器:

         第一个参数是:要使能的定时器,

         第二个参数是:定时时间(单位:ms)

         第三个参数是:定时器是否重复。1=重复/0=只一次

void ICACHE_FLASH_ATTR  OS_Timer_Init(u32 time_ms,bool repeat_flag)
{
  //关闭定时器
  os_timer_disarm(&OS_Timer); 

  //设置定时器回调函数
  os_timer_setfn(&OS_Timer, (os_timer_func_t *)OS_Timer_cb,NULL); 
  //os_timer_setfn(&OS_Timer, (ETSTimerFunc *)OS_Timer_cb,NULL);

  //使能毫秒级定时器:
  //OS_Timer:要使能的定时器;
  //time_ms:定时时间(单位:ms);     
  //repeat_flag:1=重复/0=只一次
   os_timer_arm(&OS_Timer, time_ms, repeat_flag); 

  //设置定时器参数并使能定时器
  //【如未调用system_timer_reinit,可支持范围:[5ms ~ 6,870,947ms]】
  //【如果调用system_timer_reinit,可支持范围:[100ms ~ 428,496 ms]】
}

5GPIO初始化函数

void ICACHE_FLASH_ATTR gpio_Init(void)
{
   //将GPIO4设置为IO口
   PIN_FUNC_SELECT( PERIPHS_IO_MUX_GPIO4_U,FUNC_GPIO4);

   //将管脚设为输出模式,并输出高电平
   GPIO_OUTPUT_SET(GPIO_ID_PIN(4),1);
}

6、主函数

void ICACHE_FLASH_ATTR user_init(void)
{
   uart_init(9600,9600);  //初始化串口波特率
   os_delay_us(10000);//等待串口稳定
   gpio_Init();
   os_printf("\r\n----------------------------------------\r\n");
//定时1秒,重复 OS_Timer_Init(1000,1); //隔一秒进入回调函数 //OS_Timer_Init(1000,TRUE);
os_printf("\t SDK version:\t%s", system_get_sdk_version()); os_printf("\r\n----------------------------------------\r\n"); }

效果如下:

 

 

扩展:

上面说的是回调函数不带参数的,那么在设置回调函数的时候,需要(os_timer_func_t *)(回调函数名),进行强制转换。

那如果带参数呢?就需要在定义回调函数的时候,带一个参数xxx。如下:

//1.定义定时器用的回调函数(有参数)
void os_timer_parg(void *parg)
{
    os_printf("parg:%s\n", parg);//打印传过来的参数
Led_Flag = !Led_Flag; //LED状态翻转
// 设置gpio4的输出值,即LED的值 GPIO_OUTPUT_SET(GPIO_ID_PIN(4),Led_Flag); }
注意:
void *XXX 意思是可以接收任意的指针变量
// 2.设置定时器回调函数(带参数Frank1995)
   os_timer_setfn(&OS_Timer,os_timer_parg,"Frank1995");

效果如下:

 

 

三、硬件定时器

 

看相关的三个函数:

 

 

 

步骤:

1、添加文件:

     需要添加hw_timer.c 文件到app/driver 目录下

     

2、硬件定时器回调函数

//硬件定时器回调函数
//1.回调函数前不能添加 ICACHE_FLASH_ATTR 宏定义,中断响应不能存放在 Flash 中。
void HwTimer_cb(void) { Led_Flag = !Led_Flag; //LED状态翻转 //设置gpio4的输出值,即LED的值 GPIO_OUTPUT_SET(GPIO_ID_PIN(4),Led_Flag);
os_printf(
"\r\nLED的状态为:%d\r\n",Led_Flag); os_printf("\r\n--------进入硬件回调函数-----------\r\n"); }

3、封装硬件定时器初始化函数

void ICACHE_FLASH_ATTR Hw_Timer_Init(void)
{
   /* 2.初始化硬件定时器
    * 【参数1:中断源】    NMI_SOURCE=1     FRC1_SOURCE = 0
    * 【参数2:是否重复】  1     自动填装    0    不自动填装   */
hw_timer_init(0, 1); //3.注册硬件定时器中断回调函数 hw_timer_set_func(HwTimer_cb); //4.使能硬件中断定时器 (单位us,参数必须<=1,677,721) hw_timer_arm(1000000); //由于使用的是FRC1 中断源 FRC1_SOURCE,取值范围: 50 ~ 0x199999 μs; }

4、主函数中调用

 

效果如下:

 

 

posted on 2020-03-10 15:42  轨迹1995  阅读(475)  评论(0编辑  收藏  举报