ESP8266_06---------------定时器

一、软件定时器:

1.软件定时器:
        是用程序模拟出来的定时器,它的特点是不会受到我们硬件资源不足的限制,在你的 CPU 和内存足够的情况下可以设置成百上千个软件定时器,但是它的缺点就是做不到特 别的准确,因为他是软件模拟的,当我们的 CPU 被别的事情抢占,如中断发生 等,会导致定时时间的不稳定性,因此不能使用在我们对时间要求特别严格的场合。
2.要用到的函数:
 1.关闭软件定时器:
void os_timer_disarm (os_timer_t *ptimer)
//ptimer 为 os_timer_t 类型结构体,需要我们提前定义
2.注册定时器回调函数:
void os_timer_setfn(os_timer_t *ptimer,os_timer_func_t *pfunction,void *parg)
//os_timer_t *ptimer:定时器结构体
//os_timer_func_t *pfunction:定时回调函数
//void *parg:回调函数的参数
3.使能毫秒定时器:
void os_timer_arm(os_timer_t *ptimer, uint32_t milliseconds, bool repeat_flag)
//os_timer_t *ptimer:定时器结构体
//uint32_t milliseconds:定时时间,单位:ms
//如未调用 system_timer_reinit,可支持范围 5 ~ 0x68D7A3
//如调用了 system_timer_reinit,可支持范围 100 ~ 0x689D0
//bool repeat_flag:定时器是否重复 0:不重复定时器 1:重复定时
4.  当需要使用微秒定时器时需要重新初始化定时器:
void system_timer_reinit(void)
//注意 system_timer_reinit 需要在程序最开始调用, user_init 的第一句。
5.  使能微秒定时器(不建议使用):
void os_timer_arm_us (os_timer_t *ptimer, uint32_t microseconds, bool repeat_flag)
//os_timer_t *ptimer:定时器结构体
//uint32_t microseconds:定时时间,单位 us,最小 0x64,最大 0xFFFFFFF
//bool repeat_flag:是否重复定时,0:不重复定时,1:重复定时

3.程序的编写:

我们程序的功能是:每隔500ms打印"hello"

我们需要自己编写软件定时器的驱动文件os_timer.c和os_timer.h,然后将他们分别添加到app/driverapp/include/driver下,刷新工程。

1.os_timer.h:

#ifndef __OS_TIMER_H
#define __OS_TIMER_H

#include "ets_sys.h"
#include "osapi.h"   //系统函数
#include "user_interface.h"

void OS_Timer_1_Cb(void);
void OS_Timer_Init(uint32_t ms,bool repeat_flag);

#endif /* OS_TIMER_H */

2.os_timer.c:

#include "./driver/os_timer.h"

os_timer_t os_timer_1;//定义软件定时器结构体变量

//软件定时器回调函数
void OS_Timer_1_Cb(void)
{
	os_printf("hello\n");
}

//软件定时器配置初始化
void OS_Timer_Init(uint32_t ms,bool repeat_flag)
{
	os_timer_disarm(&os_timer_1);//关闭软件定时器
	os_timer_setfn(&os_timer_1,(os_timer_func_t*)OS_Timer_1_Cb,NULL);//注册软件定时器回调函数
	os_timer_arm(&os_timer_1,ms,repeat_flag);//打开软件定时器,设置定时周期,设置是否自动重装


}

3.user_main.c:

#include "ets_sys.h"
#include "user_config.h"//用户配置
#include "eagle_soc.h"//GPIO函数,宏定义
#include "c_types.h" //变量类型
#include "osapi.h"   //系统函数
#include "user_interface.h"
#include "./driver/os_timer.h"//软件定时器


/******************************************************************************
 * FunctionName : user_rf_cal_sector_set
 * Description  : SDK just reversed 4 sectors, used for rf init data and paramters.
 *                We add this function to force users to set rf cal sector, since
 *                we don't know which sector is free in user's application.
 *                sector map for last several sectors : ABCCC
 *                A : rf cal
 *                B : rf init data
 *                C : sdk parameters
 * Parameters   : none
 * Returns      : rf cal sector
*******************************************************************************/
uint32 ICACHE_FLASH_ATTR
user_rf_cal_sector_set(void)
{
    enum flash_size_map size_map = system_get_flash_size_map();
    uint32 rf_cal_sec = 0;

    switch (size_map) {
        case FLASH_SIZE_4M_MAP_256_256:
            rf_cal_sec = 128 - 5;
            break;

        case FLASH_SIZE_8M_MAP_512_512:
            rf_cal_sec = 256 - 5;
            break;

        case FLASH_SIZE_16M_MAP_512_512:
            rf_cal_sec = 512 - 5;
            break;
        case FLASH_SIZE_16M_MAP_1024_1024:
            rf_cal_sec = 512 - 5;
            break;

        case FLASH_SIZE_32M_MAP_512_512:
            rf_cal_sec = 1024 - 5;
            break;
        case FLASH_SIZE_32M_MAP_1024_1024:
            rf_cal_sec = 1024 - 5;
            break;

        case FLASH_SIZE_64M_MAP_1024_1024:
            rf_cal_sec = 2048 - 5;
            break;
        case FLASH_SIZE_128M_MAP_1024_1024:
            rf_cal_sec = 4096 - 5;
            break;
        default:
            rf_cal_sec = 0;
            break;
    }

    return rf_cal_sec;
}

void ICACHE_FLASH_ATTR
user_rf_pre_init(void)
{
}

//毫秒延时函数
void ICACHE_FLASH_ATTR
delay_ms(u32 ms)
{
	for(;ms>0;ms--){
		os_delay_us(1000);//1ms
	}
}
/******************************************************************************
 * FunctionName : user_init
 * Description  : entry of user application, init user function here
 * Parameters   : none
 * Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_init(void)
{
  uart_init(9600,9600);
  os_printf("\r\nESP8266软件定时器\r\n");
  OS_Timer_Init(500,1);//500ms,重装载
}

4.运行结果:

二、硬件定时器 :

1.硬件定时器:
      全名为硬件中断定时器,它不像软件定时器由程序模拟实现,而是由我们的 ESP8266 上的硬件模块实现,也是就说在厂家设计 ESP8266 这一款芯片的时候就已经将我们的硬件定时器设计到芯片内部了,同时,我们的硬件定时器由中断触发,保证了定时器的准确性。
2.使用时的注意事项:
     1.我们的硬件定时器中断使用的是哪种中断源?如果我们使用的是 NMI 中断源,那么我们的硬件定时器将为最高优先级,可打断其他中断;如果我们使用的是 FRC1 中断源,那么该定时器将无打断其他中断。
     2.  如果我们的硬件定时器使用 NMI 中断源,且设置为自动重装载,也就是 重复定时,那么我们在使能硬件定时器的时候设置的定时时间必须大于100(也就是 hw_timer_arm() 函数的参数必须大于 100 )。
     3.  我们的硬件定时器不可以和 PWM 驱动同时使用,因为二者使用的是同一个硬件定时器。
     4.为 了 保 证 中 断 服 务 函 数 快 速 响 应 , 中 断 服 务 函 数 不 要 ICACHE_FLASH_ATTR 宏修饰。
     5.使用硬件定时器时,请勿调用 wifi_set_sleep_type(LIGHT_SLEEP);开启自动睡眠模式,因为在睡眠期间 CPU 会停止运行,将导致不能响应 NMI中断。
3.要用到的函数:
   1.初始化硬件定时器:
   
void hw_timer_init (FRC1_TIMER_SOURCE_TYPE source_type,u8 req)
//FRC1_TIMER_SOURCE_TYPE source_type:中断源设置。
//0:FRC1_SOURCE:使用 FRC1 中断源;
//1:NMI_SOURCE:使用 NMI 中断源。
//u8 req:设置是否重装载。
//0:不自动重装载;
//1:自动重装载。
   2.注册定时器中断服务函数:
void hw_timer_set_func(void(* user_hw_timer_cb_set)(void))
//void (* user_hw_timer_cb_set)(void):定时器回调函数(中断服务函数)
  3.使能硬件中断定时器:
void hw_timer_arm(uint32 val)
//uint32_t val:定时时间
/*
注意:在自动重装载模式,如果是 NMI 中断源,取值范围:
100-0x199999μs(100us - 1,677,721us)如果是 FRC1中断源,
取值范围:50-0x199999μs(50us-1,677,721us)。在非自动重装载模式, 
取值范围:10 - 0x199999μs
*/

4.程序的编写:
    程序的功能:每隔500ms打印"hello HWTimer"
将driver_lib/driver中的 hw_timer.c 添加到 app/driver 下,我们需要使用这里的函数创建自己的硬件驱动 hw_timer_driver.c hw_timer_driver.h ,然后将他们分别添加到 app/driver 和 app/include/driver下,刷新工程。

1.hw_timer_driver.h:

#ifndef __HW_TIMER_DRIVER_H
#define __HW_TIMER_DRIVER_H

#include "ets_sys.h"
#include "osapi.h"   //系统函数
#include "user_interface.h"

void HW_Timer_Interrupt(void);
void HW_Timer_Init(uint32_t us);

#endif

2.hw_timer_driver.c:

#include "./driver/hw_timer_driver.h"

//硬件定时器中断服务函数
void HW_Timer_Interrupt(void)
{
	os_printf("hello HWTimer\n");
}

//硬件定时器初始化配置函数
void HW_Timer_Init(uint32_t us)
{
	if(us<100 || us>1677721)
	{
		os_printf("us<100 || us>1677721\n");
	}
	hw_timer_init(1,1);//硬件定时器初始化,使用NMI中断源,重复定时
	hw_timer_set_func(HW_Timer_Interrupt);//注册硬件定时器中断服务函数
	hw_timer_arm(us);//使能中断定时器并设置定时时间
	os_printf("HW_Timer OK !\n");
}

3.user_main.c:


#include "ets_sys.h"
#include "user_config.h"//用户配置
#include "eagle_soc.h"//GPIO函数,宏定义
#include "c_types.h" //变量类型
#include "osapi.h"   //系统函数
#include "user_interface.h"
#include "./driver/hw_timer_driver.h"


/******************************************************************************
 * FunctionName : user_rf_cal_sector_set
 * Description  : SDK just reversed 4 sectors, used for rf init data and paramters.
 *                We add this function to force users to set rf cal sector, since
 *                we don't know which sector is free in user's application.
 *                sector map for last several sectors : ABCCC
 *                A : rf cal
 *                B : rf init data
 *                C : sdk parameters
 * Parameters   : none
 * Returns      : rf cal sector
*******************************************************************************/
uint32 ICACHE_FLASH_ATTR
user_rf_cal_sector_set(void)
{
    enum flash_size_map size_map = system_get_flash_size_map();
    uint32 rf_cal_sec = 0;

    switch (size_map) {
        case FLASH_SIZE_4M_MAP_256_256:
            rf_cal_sec = 128 - 5;
            break;

        case FLASH_SIZE_8M_MAP_512_512:
            rf_cal_sec = 256 - 5;
            break;

        case FLASH_SIZE_16M_MAP_512_512:
            rf_cal_sec = 512 - 5;
            break;
        case FLASH_SIZE_16M_MAP_1024_1024:
            rf_cal_sec = 512 - 5;
            break;

        case FLASH_SIZE_32M_MAP_512_512:
            rf_cal_sec = 1024 - 5;
            break;
        case FLASH_SIZE_32M_MAP_1024_1024:
            rf_cal_sec = 1024 - 5;
            break;

        case FLASH_SIZE_64M_MAP_1024_1024:
            rf_cal_sec = 2048 - 5;
            break;
        case FLASH_SIZE_128M_MAP_1024_1024:
            rf_cal_sec = 4096 - 5;
            break;
        default:
            rf_cal_sec = 0;
            break;
    }

    return rf_cal_sec;
}

void ICACHE_FLASH_ATTR
user_rf_pre_init(void)
{
}

//毫秒延时函数
void ICACHE_FLASH_ATTR
delay_ms(u32 ms)
{
	for(;ms>0;ms--){
		os_delay_us(1000);//1ms
	}
}
/******************************************************************************
 * FunctionName : user_init
 * Description  : entry of user application, init user function here
 * Parameters   : none
 * Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_init(void)
{
  uart_init(9600,9600);
  os_printf("\r\nESP8266硬件定时器\r\n");
  HW_Timer_Init(500000);//500ms
}

5.运行结果:

如需源码请在评论区留下邮箱地址!!! 

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值