任务8 使用终端来实现快速按键切屏(arduino程序)

什么是中断
​       中断(Interrupt)是一种在计算机中被广泛应用的一种重要的技术,它是一种CPU事件处理机制。其本质是一个电信号,这个信号由某个硬件或软件产生并由处理器处理。当处理器接收到中断信号时会暂停当前任务,跳到一个叫中断服务例程(ISR)的一段程序中处理中断,当中断被处理完成后,CPU将回到原来的任务继续工作。与中断相对的事件处理机制是轮询,顾名思义就是不断的询问相关的硬件是否做好准备。
​       中断的一个比较常见的例子是磁盘读写。我们都知道,磁盘的速度与CPU的速度不在一个数量级上面(ms和ns的区别),当CPU希望从磁盘上面拷贝一个或多个扇区到内存时,如果采用轮询的方法,CPU需要在这个过程中不断的将数据从磁盘读入寄存器,再从寄存器写入到内存中。需要注意的是CPU与磁盘的速度有着巨大的差异,两者相差将近6个数量级,这样会使得CPU在把大部分的时间都花在等待磁盘响应上面,这无疑是一种浪费——在磁盘读写期间CPU完全可以进行其他的运算,却浪费在了无意义的等待上面。而如果使用中断的方法,CPU将会把磁盘请求发送给一个叫DMA控制器的硬件,然后把当前任务挂起,先执行其他任务。DMA会“接管”这个工作,有它负责代替CPU完成轮询的工作,并通过总线直接将数据写到内存上面。复制完成后,它会触发一个中断通知CPU已经复制完成,CPU响应后就可以继续执行请求磁盘读写的任务。这样一来,CPU就不再需要等待拖拉的磁盘了。事实上,现代计算机都离不开中断,我们对计算机的任何的一个操作(包括鼠标或键盘),都会触发相应的中断,系统调用也需要通过中断完成(起码经典过程是如此)。
​        根据中断的来源,我们可以把中断分为软中断和硬中断,顾名思义他们分别就是由软件和硬件触发的中断。


在Arduino中使用中断
​       Arduino中主要有时钟中断和外部中断,本文所说的中断指的是外部中断。Arduino中的外部中断通常是由Pin口(数字Pin口,不是模拟口)电平改变触发的。

      开发板    可以用来注册中断的Pin口
      Uno, Nano, Mini, other 328-based    2, 3
      注册中断主要是通过attachInterrupt()函数实现的,其原型为:

      void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode);
      第一个参数为中断号,Arduino上每个可以注册中断的Pin口都会被分配一个中断号,这里需要传入的是中断号而不是Pin口号。但是不同的Arduino开发板上面的中断号分配并不完全一样。各个      开发板的Pin口号和中断号对应关系如下:
      Uno, Ethernet    PIN 2    PIN 3  

另一种方法:             

      attachInterrupt(digitalPinToInterrupt(pin), ISR, mode); 
      这种方式来注册中断号。

      第二个参数是中断服务例程(ISR)的函数指针,在C/C++中直接写该函数的函数名即可。在触发时,该函数将会被调用。该函数必须没有任何的参数也没有任何的返回值。

      第三个参数是中断触发条件,由几个可选的值:

LOW 当中断所在Pin口处于低电平时触发

CHANGE 当中断所在Pin口电平改变时触发

RISING 当中断所在Pin口从低电平变为高电平(上升沿)时触发

FALLING 当中断所在Pin口从高电平变为低电平(下降沿)时触发


在Arduino中使用中断需要注意的问题
      1、由于中断会打断正常代码的运行,因此ISR的应该尽可能快地执行完毕。
      2、在ISR中修改的全局变量要用volatile修饰符修饰以防止编译器优化
      3、在ISR中不能使用其他用中断实现的函数,如millis() delay() 等。延时可以使用 delayMicroseconds(),它不是用中断实现的。


最终程序:

/*********************************************************
 * 功能:四个项目使用外部中断快速切换
 * 引脚接线:DHT11:6
 *          WS2812b:9
 *          DS18b20:7
 *          MQ-3:A0
 *          DS3231:IIC
 * 
 ********************************************************/
#include "U8glib.h"
#include <FastLED.h>
#include <Wire.h>
#include <DallasTemperature.h>
#include <OneWire.h>
#include "DHT.h"
#include <DS3231.h>
#define button1 3               //触摸按键接口定义
#define ONE_WIRE_BUS 7          //DS18b20
#define DHTPIN 6                //DHT11
#define DHTTYPE DHT11

#define NUM_LEDS 2             // LED灯珠数量
#define DATA_PIN 9              // Arduino输出控制信号引脚
#define LED_TYPE WS2812         // LED灯带型号
#define COLOR_ORDER GRB         // RGB灯珠中红色、绿色、蓝色LED的排列顺序

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);
uint8_t max_bright = 128;       // LED亮度控制变量,可使用数值为 0 ~ 255, 数值越大则光带亮度越高
 
CRGB leds[NUM_LEDS];            // 建立光带leds

uint8_t openState = 3;
uint8_t c = 0;
float TempC = 0;
float h;
float t;

const int analogInPin = A0;
int sensorValue = 0;        // value read from the pot
int outputValue = 0;
int ppm = 0;

uint8_t openState2 = 20;    //酒精ppm阈值
uint8_t openState3 = 20;    //天数

uint8_t cishu = 0;
uint8_t val, flag=0;

DS3231 Clock;
//uint8_t h;
bool Century=false;
bool h12;
bool PM;
byte ADay, AHour, AMinute, ASecond, ABits;
bool ADy, A12h, Apm;

int second,minute,hour,date,month,year,temperature;

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DHT dht(DHTPIN, DHTTYPE);

static unsigned char deng[] U8G_PROGMEM = {0x00,0x00,0x7E,0x3E,0x40,0x22,0x40,0x12,0x42,0x12,0x24,0x0A,0x28,0x12,0x10,0x12,
0x10,0x22,0x28,0x22,0x28,0x22,0x44,0x16,0x42,0x0A,0x01,0x02,0x00,0x02,0x00,0x02,/*"邓",0*/};
static unsigned char zhao[] U8G_PROGMEM = {0x00,0x00,0xBE,0x3F,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x29,0xBE,0x10,0x22,0x3F,
0x22,0x21,0x22,0x21,0x22,0x21,0x3E,0x3F,0x00,0x00,0x12,0x11,0x22,0x22,0x21,0x22,/*"照",1*/};
static unsigned char quan[] U8G_PROGMEM = {0x08,0x00,0xC8,0x3F,0x88,0x20,0x88,0x20,0xBF,0x20,0x08,0x11,0x0C,0x11,0x1C,0x11,
0x2A,0x0A,0x2A,0x0A,0x09,0x04,0x08,0x04,0x08,0x0A,0x08,0x11,0x88,0x20,0x68,0x40,/*"权",2*/};
static unsigned char nian[] U8G_PROGMEM = {0x08,0x00,0x08,0x00,0xF8,0x3F,0x04,0x01,0x04,0x01,0x02,0x01,0xF8,0x1F,0x08,0x01,
0x08,0x01,0x08,0x01,0xFF,0x7F,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,/*"年",0*/};
static unsigned char yue[] U8G_PROGMEM = {0x00,0x00,0xF8,0x1F,0x08,0x10,0x08,0x10,0x08,0x10,0xF8,0x1F,0x08,0x10,0x08,0x10,
0x08,0x10,0xF8,0x1F,0x08,0x10,0x08,0x10,0x04,0x10,0x04,0x10,0x02,0x14,0x01,0x08,/*"月",1*/};
static unsigned char ri[] U8G_PROGMEM = {0x00,0x00,0xF8,0x0F,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0xF8,0x0F,
0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0xF8,0x0F,0x08,0x08,/*"日",2*/};
static unsigned char zhou[] U8G_PROGMEM = {0x00,0x00,0xFC,0x1F,0x84,0x10,0x84,0x10,0xF4,0x17,0x84,0x10,0x84,0x10,0xFC,0x1F,
0x04,0x10,0xE4,0x13,0x24,0x12,0x24,0x12,0xE4,0x13,0x02,0x10,0x02,0x14,0x01,0x08,/*"周",0*/};
static unsigned char si[] U8G_PROGMEM = {0x00,0x00,0x00,0x00,0xFE,0x3F,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,
0x12,0x22,0x12,0x3C,0x0A,0x20,0x06,0x20,0x02,0x20,0xFE,0x3F,0x02,0x20,0x00,0x00,/*"四",1*/};

void button_State(void) //中断回调函数一定要是无返回无参数的函数void
{ 
//A
//  if(!digitalRead(button1)){ //检测按键是否按下
     openState++;
//  }
//   while(digitalRead(button1));
//  Serial.println("进入中断");
}

void wendu_Jiance(void)
{
  h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  t = dht.readTemperature();
  sensors.requestTemperatures();
  TempC = sensors.getTempCByIndex(0);
  
  if(TempC >= 30)
  {
    leds[0] = CRGB::Red;
    FastLED.show();
  }
  else if(TempC <= 26)
  {
    leds[0] = CRGB::Green;
    FastLED.show();
  }
  delay(50);
  if(h >= 90)
  {
    leds[1] = CRGB::Red;
    FastLED.show();
  }
  else if(h <= 85)
  {
    leds[1] = CRGB::Green;
    FastLED.show();
  }  
}

void jiuJin(void)
{
  sensorValue = analogRead(analogInPin);
  outputValue = map(sensorValue, 0, 1023, 0, 5000);
  ppm = outputValue/100-8;
  
  if(ppm<0)
    ppm = 0;
  Serial.print("output = ");
  Serial.println(ppm);

  if(ppm>openState2)
    digitalWrite(LED_BUILTIN, HIGH);
  else
    digitalWrite(LED_BUILTIN, LOW);  
}

void ws2812_Show(void)
{
  if(cishu == 3)
      cishu = 0;
  if(cishu == 0){
    leds[0] = CRGB::Red;          // 设置光带中第一个灯珠颜色为红色,leds[0]为第一个灯珠,leds[1]为第二个灯珠
    FastLED.show();
    delay(100);
    leds[1] = CRGB::Red;
    FastLED.show();
  }
  if(cishu == 1){
    leds[0] = CRGB::Blue;          // 设置光带中第一个灯珠颜色为红色,leds[0]为第一个灯珠,leds[1]为第二个灯珠
    FastLED.show();
    delay(100);
    leds[1] = CRGB::Blue;
    FastLED.show();
  }
  if(cishu == 2){
    leds[0] = CRGB::Yellow;          // 设置光带中第一个灯珠颜色为红色,leds[0]为第一个灯珠,leds[1]为第二个灯珠
    FastLED.show();
    delay(100);
    leds[1] = CRGB::Yellow;
    FastLED.show();
  }
}

void ReadDS3231()
{
  second=Clock.getSecond();
  minute=Clock.getMinute();
  hour=Clock.getHour(h12, PM);
  date=Clock.getDate();
  month=Clock.getMonth(Century);
  year=Clock.getYear();
  
  temperature=Clock.getTemperature();

//  mode_0();
}

void draw0(void) {//DS18b20
  u8g.drawXBMP( 0, 0, 16, 16, deng);
  u8g.drawXBMP( 16, 0, 16, 16, zhao);
  u8g.drawXBMP( 32, 0, 16, 16, quan);
  u8g.setFont(u8g_font_unifont);
//  u8g.drawStr( 0, 45, "DengZhaoquan:");
//  u8g.drawStr( 0, 12, "190306238");
  u8g.setPrintPos(70,15);
  u8g.print("NO:1");


//  sensors.requestTemperatures();
//  TempC = sensors.getTempCByIndex(0);
  
  u8g.setPrintPos(0,30);
  u8g.print("DS18B20:");
  u8g.print(TempC);
  u8g.print(" C");
}

void draw1(void) {
  u8g.drawXBMP( 0, 0, 16, 16, deng);
  u8g.drawXBMP( 16, 0, 16, 16, zhao);
  u8g.drawXBMP( 32, 0, 16, 16, quan);
  u8g.setPrintPos(70,15);
  u8g.print("NO:2");
  u8g.setPrintPos(0,30);
  u8g.print("DHT11:");
  u8g.setPrintPos(0,45);
  u8g.print("h= ");
  u8g.print(h);
  u8g.print("%");
  u8g.setPrintPos(0,60);
  u8g.print("t = ");
  u8g.print(t);
  u8g.print(" C");

  u8g.setFont(u8g_font_unifont);
  u8g.drawStr( 61, 30, "Numb:");
  u8g.setPrintPos(100,30);
  u8g.print(c++);
}

void draw2(void) {
  u8g.setFont(u8g_font_unifont);
//  u8g.drawStr( 0, 45, "DengZhaoquan:");
//  u8g.drawStr( 0, 12, "190306238");
  u8g.drawXBMP( 16, 0, 16, 16, deng);
  u8g.drawXBMP( 32, 0, 16, 16, zhao);
  u8g.drawXBMP( 48, 0, 16, 16, quan);
  u8g.setPrintPos(70,15);
  u8g.print("NO:3");
  
  u8g.setPrintPos(10,29);
  u8g.print("sensor = ");
  u8g.print(sensorValue);
  
  u8g.setPrintPos(10,43);
  u8g.print("output = ");
  u8g.print(outputValue);
  u8g.print("mv");

  u8g.setPrintPos(10,58);
  u8g.print("MQ3_PPM = ");
  u8g.print(ppm);
}

void draw3(void) {
  u8g.drawXBMP( 16, 0, 16, 16, deng);
  u8g.drawXBMP( 32, 0, 16, 16, zhao);
  u8g.drawXBMP( 48, 0, 16, 16, quan);
  u8g.setPrintPos(70,15);
  u8g.print("NO:4");

  u8g.setPrintPos(0,30);
  u8g.print("Time:");
  
  u8g.setPrintPos(0,45);
  u8g.print("20");
  u8g.print(year,DEC);
  u8g.drawXBMP( 32, 32, 16, 16, nian);
  u8g.setPrintPos(48,45);
  u8g.print(month);
  u8g.drawXBMP( 66, 32, 16, 16, yue);
  u8g.setPrintPos(82,45);
  u8g.print(date);
  u8g.drawXBMP( 98, 32, 16, 16, ri);
  
  u8g.setPrintPos(0,60);
  u8g.print(hour);
  u8g.print(":");
  u8g.print(minute);
  u8g.print(":");
  u8g.print(second);
}

void mode_0()
{
  u8g.firstPage();  
  do {
    draw0();
  } while( u8g.nextPage() );  
}

void mode_1()
{
  u8g.firstPage();  
  do {
    draw1();
  } while( u8g.nextPage() );  
}

void mode_2()
{
  u8g.firstPage();  
  do {
    draw2();
  } while( u8g.nextPage() );  
}

void mode_3()
{
  u8g.firstPage();  
  do {
    draw3();
  } while( u8g.nextPage() );  
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
//  pinMode(button1, INPUT);
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(button1, INPUT_PULLUP);
  pinMode(4, OUTPUT);
  digitalWrite(4, LOW);
  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);
  delay(100);
  dht.begin();
  LEDS.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS);  // 初始化光带 
  FastLED.setBrightness(max_bright);                            // 设置光带亮度
  Wire.begin();
        Clock.setSecond(50);//Set the second 
        Clock.setMinute(25);//Set the minute 
        Clock.setHour(15);  //Set the hour 
        Clock.setDoW(4);    //Set the day of the week
        Clock.setDate(openState3);  //Set the date of the month
        Clock.setMonth(5);  //Set the month of the year
        Clock.setYear(21);  //Set the year (Last two digits of the year)
  attachInterrupt(digitalPinToInterrupt(button1), button_State, FALLING);
//  attachInterrupt(11, button, CHANGE);
}

void loop() {
  // put your main code here, to run repeatedly:
  wendu_Jiance();                     //温湿度判断改变灯带颜色
  jiuJin();                           //酒精检测函数
//  ws2812_Show();                      //LED显示函数
  ReadDS3231();                       //读取时间
  switch (openState)
  {
    case 0:
//      openState = 0;
      mode_0();     //
      break;
    case 1:
      mode_1();     //
      break;
    case 2:
      mode_2();     //
      break;
    case 3:
      mode_3();     //
      break;
    case 4:
//      mode_4();     //
      break;
    default:

      break;
  }
  if(openState >= 4) openState = 0;
  Serial.println(openState);
}


/*
 * 附:attachInterrupt()函数的语法介绍
attachInterrupt( digitalPinToInterrupt(pin) , function, mode)

digitalPinToInterrupt(pin) :取得引脚pin的中断号 
function:中断发生时调用的函数,此函数必须不带参数和不返回任何值。该函数称为中断服务程序。 
mode:定义何时发生中断以下四个contstants预定有效值:

LOW 当引脚为低电平时,触发中断
CHANGE 当引脚电平发生改变时,触发中断
RISING 当引脚由低电平变为高电平时,触发中断
FALLING 当引脚由高电平变为低电平时,触发中断.
————————————————
 */

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值