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

以下函数产生17KHz以下的可调频率方波,可供驱动电机。并将电机的转速显示在OLED屏幕上。

这里利用TimerOne定时器进行多任务操作的方法借鉴这篇文章:

Arduino中文社区

利用Adafruit_SSD1306库做0.96寸OLED屏幕显示的代码很多,这里就不列出了。

实际上,这个代码在跑起来有3个问题:

1.变量Interval降低到30就不能再降低了,所以产生的方波频率最高只能在17KHz左右

2.由于使用的Interval变量不能定义为const,所以输出的方波实际上会有一点抖动,在0.05KHz左右

3.由于choose和toggle函数公用一个定时器Timer1,所以当Interval较小时,choose访问引脚频率会更高。总结起来就是:Interval调低时,会越调越快。

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <TimerOne.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     13 // 重置引脚
#define SCREEN_ADDRESS 0x3C // OLED 显示屏的地址,固化在芯片上
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // 创建实例
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=100;
static word gy=0;
void setup() 
{
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
    }
  display.clearDisplay(); // 清屏
  delay(100); // 延时 1s
  display.setTextColor(WHITE); // 设置字体颜色为白色
  display.display(); // 显示
  pinMode(13,  OUTPUT);  // Pin 13 has an LED
  pinMode(2,INPUT_PULLUP);
  pinMode(3,INPUT_PULLUP);
  Timer1.initialize( interval ); // 初始化,   interval 以 micro sec 为单位
  Timer1.attachInterrupt(choose); // attach the service routine here
  Serial.begin(9600);
}

void loop()
{ 
 if(ca==1)//因为用错了关系运算符,浪费了至少20分钟
 {
  if(lh==1) {interval+=10;}
  else
  {
    if(interval<=30){return;}
    interval-=10;
  }
  
 }
  ca=0;
  Timer1.initialize( interval );
  Display();
  Serial.println(interval);
}

void choose( )//用于翻转LED显示
{ 
   ++gy;  //  注意:  这 gy 是全局变量(Global variable)
   if( gy % intA == 0) Toggle( );   // gy 除以 intA 的余数是 0
   if( gy % intB == 0) PinRead( );
}

void Display()
{
  display.setTextSize(2); // 设置字体大小
  display.setCursor(0,0); // 设置显示起始位置,根据屏幕大小自己计算
  display.print("1 Cir Need"); // 输出 Hello 字样
  display.setCursor(0,16); 
  display.print(0.01*interval);
  display.setCursor(0,32); // 设置显示起始位置,根据屏幕大小自己计算
  display.print("Second");
  display.display(); // 显示
  display.clearDisplay(); // 刷新
}

void Toggle()
{
  digitalWrite(13,digitalRead(13)^1);
}

void PinRead()
{
  if(!digitalRead(2)){ca=1;lh=1;}
  if(!digitalRead(3)){ca=1;lh=0;}
}

初学者,还请多多指教。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值