以下代码利用ESP8266做MicroSeconds级的硬件定时器,并使用单定时器进行多ISR操作。这算什么?AVR平台的TIMER_ONE库搬运到ESP8266?我是一个爱水的搬运工。
代码修改自K.Hoang的GITHUB文件,并且基本沿用了上一篇博客里的代码部分。
OLED屏幕还没到,到了之后再把OLED显示部分代码补上。上了示波器后发现效果还不错。
2022年2月25日,把OLED代码段补上了。
后面可能会再加上WIFI联网。(那要不然用ESP8266做什么?)
//以下代码利用ESP8266做MicroSeconds级的硬件定时器,并使用单定时器进行多ISR操作。这算什么?AVR平台的TIMER_ONE库搬运到ESP8266?我是一个爱水的搬运工
//代码来自K.Hoang的GITHUB文件,https://github.com/khoih-prog/ESP8266TimerInterrupt
#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);
#if !defined(ESP8266)
#error This code is designed to run on ESP8266 and ESP8266-based boards! Please check your Tools->Board setting.
#endif
// These define's must be placed at the beginning before #include "ESP8266TimerInterrupt.h"
// _TIMERINTERRUPT_LOGLEVEL_ from 0 to 4
// Don't define _TIMERINTERRUPT_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system.
#define TIMER_INTERRUPT_DEBUG 0
#define _TIMERINTERRUPT_LOGLEVEL_ 0
// Select a Timer Clock
#define USING_TIM_DIV1 false // for shortest and most accurate timer
#define USING_TIM_DIV16 false // for medium time and medium accurate timer
#define USING_TIM_DIV256 true // for longest timer but least accurate. Default
#include "ESP8266TimerInterrupt.h"
#ifndef LED_BUILTIN
#define LED_BUILTIN 2 // Pin D4 mapped to pin GPIO2/TXD1 of ESP8266, NodeMCU and WeMoS, control on-board LED
#endif
#define TIMER_INTERVAL_MS 100 //10MicroSecond,可以用于控制TIMER_INTERVAL_MS的改动步长,因为我打算用TIMER_INTERVAL_MS*Factor来改变定时器长度
volatile uint32_t TimerCount = 0; //定时器计数
int Factor=100;
bool ca=0;//定义两个标志位,ca=change,ca=1,表示按键按下;ca=0,表示无事发生,同时禁用lh标志位
bool lh=1;//lh=Lower or Higher,lh=1,表示间隔时间加长;lh=0,表示间隔时间减少
unsigned long interval = 200;
const int intA=1;
const int intB=2;
static word gy=0;
// Init ESP8266 timer 1
ESP8266Timer ITimer;
/*void printResult(uint32_t currTime)
{
Serial.print(F("Time = ")); Serial.print(currTime);
Serial.print(F(", TimerCount = ")); Serial.println(TimerCount);
}*/
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
pinMode(12,INPUT_PULLUP);
pinMode(14,INPUT_PULLUP);
Serial.begin(115200);
//while (!Serial);//这里在调试完成后要注释掉
u8g2.begin();
delay(300);
Serial.print(F("\nStarting Change_Interval on ")); Serial.println(ARDUINO_BOARD);
Serial.println(ESP8266_TIMER_INTERRUPT_VERSION);
Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz"));//输出当前开发板状态
// Interval in microsecs
if (ITimer.attachInterruptInterval(TIMER_INTERVAL_MS*Factor, TimerHandler))//每10MS执行一次定时器,代表计时开始
{
//Serial.print(F("Starting ITimer OK, millis() = ")); Serial.println(millis());//输出当前系统实时时间
IntervalPrint();
}
else
Serial.println(F("Can't set ITimer. Select another freq. or timer"));
}
void loop()
{
if(ca==1)
{
if(lh==1) {ca=0;Factor+=10;}
else
{
if(Factor<=30){ca=0;return;}
ca=0;Factor-=10;}
IntervalChange();
}
oledPrint();
}
void TimerHandler()
{
++gy; // 注意: 这 gy 是全局变量(Global variable)
if( gy % intA == 0) Toggle( ); // gy 除以 intA 的余数是 0
if( gy % intB == 0) PinRead( );
IntervalPrint();
}
void IntervalPrint()
{
Serial.println(F("Now the Interval is MS="));Serial.println(TIMER_INTERVAL_MS*Factor/1000);
}
void oledPrint()
{
u8g2.clearBuffer(); // clear the internal memory
float v=TIMER_INTERVAL_MS*Factor*0.0001;
u8g2.setFont(u8g2_font_9x15_t_symbols); // choose a suitable font
u8g2.drawStr(0,10,"Now a Circul");
u8g2.drawStr(0,26,"need");// write something to the internal memory
u8g2.setCursor(40,26);
u8g2.print(v);
u8g2.drawStr(0,40,"Sec");//第一个值是横坐标,第二个单位是纵坐标
u8g2.sendBuffer(); // transfer internal memory to the display
}
void IntervalChange()
{
ITimer.setInterval(TIMER_INTERVAL_MS*Factor, TimerHandler);
}
void Toggle()
{
digitalWrite(2,digitalRead(2)^1);//说实话我已经看不懂自己当时写的是什么J8了 ^表示位异或
}
void PinRead()
{
if(!digitalRead(12)){ca=1;lh=1;}
if(!digitalRead(14)){ca=1;lh=0;}
}