ESP8266产生频率可调方波并外接0.96寸OLED显示

本文介绍了如何将AVR平台的TIMER_ONE库迁移至ESP8266,通过单定时器实现高精度定时和多中断服务请求(ISR)操作。作者分享了使用U8G2 OLED屏幕的示例代码,并计划增加Wi-Fi联网功能,展示了硬件编程的实践与扩展可能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

以下代码利用ESP8266做MicroSeconds级的硬件定时器,并使用单定时器进行多ISR操作。这算什么?AVR平台的TIMER_ONE库搬运到ESP8266?我是一个爱水的搬运工。
代码修改自K.Hoang的GITHUB文件,并且基本沿用了上一篇博客里的代码部分。

https://github.com/khoih-prog/ESP8266TimerInterrupthttps://github.com/khoih-prog/ESP8266TimerInterrupt

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;}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值