首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何写入RP2040上的特定寄存器以退出

如何写入RP2040上的特定寄存器以退出
EN

Stack Overflow用户
提问于 2022-10-22 22:27:56
回答 3查看 100关注 0票数 0

我正在使用Arduino IDE和langauge (C)编写一个Raspberry Pi Pico程序。我有一个项目,使用16x2液晶显示器和按钮来控制它的背光。按钮和其他一切都正常工作,我的问题是,每次我按下开关,背光闪烁,需要按下它的随机时间来保持或关闭,我建议由于反弹。我想清除RP2040的ICSR寄存器中的22位,以便在从中断返回之前清除中断缓冲区中的任何挂起的内容。m0plus (第87页,或页面底部的86页)

到目前为止我的代码是:

代码语言:javascript
复制
#include <Adafruit_BMP280.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
#include "hardware/regs/m0plus.h"
//#include <pico/stdlib.h>
//#include <hardware/pwm.h>

Adafruit_BMP280 bmp; //I2C

hd44780_I2Cexp lcd(0x27, 16, 2);

const uint16_t AirValue = 1023;
const uint16_t WaterValue = 660; //measured fully submerged in water
const uint16_t DarkValue = 0;
const uint16_t LightValue = 1023;
uint16_t soilMoisture;
uint16_t soilMoisturePercent;
uint16_t lightIntensity;
uint16_t lightIntensityPercent;
volatile bool lcdBacklightStatus = false;

byte pressureChar[] = { 0b01000, 0b11110, 0b11100, 0b01000, 0b00011, 0b01111, 0b00000, 0b11110
};

byte moistureChar[] = { 0b00000, 0b00100, 0b01110, 0b11111, 0b11111, 0b11111, 0b01110, 0b00000
};

byte lightIntensityChar[] = { 0b00000, 0b01110, 0b10001, 0b11011, 0b10101, 0b01110, 0b01110, 0b00100
};

byte temperatureChar[] = { 0b01000, 0b10111, 0b10100, 0b11111, 0b11100, 0b11100, 0b11100, 0b01000
};

byte separatorWall[] = { 0b10101, 0b01010, 0b10101, 0b01010, 0b10101, 0b01010, 0b10101, 0b01010
};

byte degreeChar[] = { 0b00111, 0b00101, 0b00111, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000
};

void backlight();

void setup() {
  lcd.begin(0x27, 16, 2);

  lcd.createChar(0, pressureChar);
  lcd.createChar(1, moistureChar);
  lcd.createChar(2, lightIntensityChar);
  lcd.createChar(3, temperatureChar);
  lcd.createChar(4, separatorWall);
  lcd.createChar(5, degreeChar);

  lcd.home();

  pinMode(26, INPUT); //soilMoisture
  pinMode(27, INPUT); //lightIntensity
  pinMode(17, INPUT); //button

  attachInterrupt(digitalPinToInterrupt(17), backlight, RISING);
  
  //Serial.begin(9600);

  bmp.begin(0x76);
  bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,     /* Operating Mode. */
                  Adafruit_BMP280::SAMPLING_X2,     /* Temp. oversampling */
                  Adafruit_BMP280::SAMPLING_X16,    /* Pressure oversampling */
                  Adafruit_BMP280::FILTER_X16,      /* Filtering. */
                  Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */

  lcd.clear();
  lcd.backlight(); //lcd.noBacklight();

  lcd.setCursor(1,0);
  lcd.print("Plant Station");
  lcd.setCursor(6,1);
  lcd.print("V0.8");

  delay(2000);

  lcd.noBacklight();
  lcd.clear();

  lcd.setCursor(0,0);
  lcd.write(byte(3));
  lcd.setCursor(10,0);
  lcd.write(byte(2));
  lcd.setCursor(0,1);
  lcd.write(byte(0));
  lcd.setCursor(10,1);
  lcd.write(byte(1));
  lcd.setCursor(7,0);
  lcd.write(byte(5));
  lcd.setCursor(8,0);
  lcd.print("C");
  lcd.setCursor(15,0);
  lcd.print("%");
  lcd.setCursor(6,1);
  lcd.print("hPa");
  lcd.setCursor(15,1);
  lcd.print("%");
}

void loop() {
  soilMoisture = analogRead(26);
  soilMoisturePercent = map(soilMoisture, AirValue, WaterValue, 0, 100);

  lightIntensity = analogRead(27);
  lightIntensityPercent = map(lightIntensity, DarkValue, LightValue, 0, 100);

  if(soilMoisturePercent >= 100) soilMoisturePercent = 100;
    else if(soilMoisturePercent <= 0) soilMoisturePercent = 0; 

  if(lightIntensityPercent >= 100) lightIntensityPercent = 100;
    else if(lightIntensityPercent <= 0) lightIntensityPercent = 0;

  //Serial.print("Moisture: ");
  //Serial.println(soilMoisture);
  //Serial.print("Percentage: ");
  //Serial.println(soilMoisturePercent);
  //Serial.print("LightIntensity: ");
  //Serial.println(lightIntensity);
  //Serial.print(soilMoisture);
  //Serial.println(soilMoisturePercent);

  //BANNED CURSOR POSITIONS: 0,0  9,0  0,1  9,1  6,0  14,0  7,0  15,0  5,1  15,1

  lcd.setCursor(3,0);
  lcd.print(bmp.readTemperature(),1);
  lcd.setCursor(2,1);
  lcd.print(((bmp.readPressure()/100)),0);
  if(soilMoisturePercent < 10) {
    lcd.setCursor(13,1);
    lcd.print(" ");
    lcd.print(soilMoisturePercent);
  } else if(soilMoisturePercent < 100) {
    lcd.setCursor(13,1);
    lcd.print(soilMoisturePercent);
  } else {
    lcd.setCursor(12,1);
    lcd.print(soilMoisturePercent);
  }
  if(lightIntensityPercent < 10) {
    lcd.setCursor(13,0);
    lcd.print(" ");
    lcd.print(lightIntensityPercent);
  } else if(lightIntensityPercent < 100) {
    lcd.setCursor(13,0);
    lcd.print(lightIntensityPercent);
  } else {
    lcd.setCursor(12,0);
    lcd.print(lightIntensityPercent);
  }

  delay(60000);
}

void backlight() {
  //noInterrupts();
  detachInterrupt(digitalPinToInterrupt(17));
  if(lcdBacklightStatus == true) {
    lcd.noBacklight();
  } else if(lcdBacklightStatus == false) {
    lcd.backlight();
  }
  delayMicroseconds(500000);
  //interrupts();
  attachInterrupt(digitalPinToInterrupt(17), backlight, RISING);
  lcdBacklightStatus = !lcdBacklightStatus;
  //want to clear ICSR register here i guess
}

我可能还不够清楚,如果是这样的话,英语不是我的主要语言。

EN

回答 3

Stack Overflow用户

发布于 2022-10-22 23:00:13

@stark成了我的英雄,我删除了整个中断部分,以及主循环结束时长达60秒的延迟。然后添加了下面的代码,现在当按钮被按下1秒时,lcd背光切换,感应器仍然每60秒检查一次。仍然不知道如何处理注册表来揭穿,所以帖子仍然是开放的。

代码语言:javascript
复制
  for(int i = 0; i < 600; i++) {
    if(digitalRead(17) == 1) trueCount++;
    if(trueCount == 10) {
      lcdBacklightStatus = !lcdBacklightStatus;
      trueCount = 0;
    }
    if(lcdBacklightStatus == false) {
    lcd.noBacklight();
    } else if(lcdBacklightStatus == true) {
    lcd.backlight();
    }
    delay(100);
  }

编辑:

我根据状态机的概念重写了我的整个代码。现在它运行得完美无缺,但我仍然想知道如何处理RP2040芯片上的中断,所以非常感谢您给出的好答案!

代码:

代码语言:javascript
复制
#include <Adafruit_BMP280.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>

Adafruit_BMP280 bmp;
hd44780_I2Cexp lcd(0x27, 16, 2);

const uint8_t moistureSensorPin = 26;
const uint8_t lightSensorPin = 27;
const uint8_t buttonPin = 17;

const uint16_t moistureSensorInterval = 60000;
const uint16_t lightSensorInterval = 60000;
const uint16_t temperatureSensorInterval = 60000;
const uint16_t pressureSensorInterval = 60000;
const uint16_t buttonInterval = 500;
const uint16_t lcdUpdateInterval = 60000;

const uint32_t backlightDuration = 300000;

const uint16_t AirValue = 1023;
const uint16_t WaterValue = 660;
const uint16_t DarkValue = 0;
const uint16_t LightValue = 1023;


uint16_t soilMoisture;
uint16_t soilMoisturePercent;
uint16_t lightIntensity;
uint16_t lightIntensityPercent;
float temperature;
uint32_t pressure;

byte soilMoist = LOW;
byte soilHalfMoist = LOW;
byte soilDry = LOW;
byte buttonState = LOW;
byte lcdBacklightStatus = LOW;
byte buttonPreviouslyPressed = LOW;


uint32_t currentMillis = 0;
uint32_t previousMoistureSensorMillis = 60000;
uint32_t previousLightSensorMillis = 60000;
uint32_t previousTemperatureMillis = 60000;
uint32_t previousPressureMillis = 60000;
uint32_t previousButtonMillis = 0;
uint32_t previousLCDMillis = 0;

byte pressureChar[] = { 0b01000, 0b11110, 0b11100, 0b01000, 0b00011, 0b01111, 0b00000, 0b11110
};

byte moistureChar[] = { 0b00000, 0b00100, 0b01110, 0b11111, 0b11111, 0b11111, 0b01110, 0b00000
};

byte halfMoistureChar[] = { 0b00000, 0b00100, 0b01010, 0b10001, 0b11111, 0b11111, 0b01110, 0b00000
};

byte emptyMoistureChar[] = { 0b00000, 0b00100, 0b01010, 0b10001, 0b10001, 0b10001, 0b01110, 0b00000
};

byte lightIntensityChar[] = { 0b00000, 0b01110, 0b10001, 0b11011, 0b10101, 0b01110, 0b01110, 0b00100
};

byte temperatureChar[] = { 0b01000, 0b10111, 0b10100, 0b11111, 0b11100, 0b11100, 0b11100, 0b01000
};

byte separatorWall[] = { 0b10101, 0b01010, 0b10101, 0b01010, 0b10101, 0b01010, 0b10101, 0b01010
};

byte degreeChar[] = { 0b00111, 0b00101, 0b00111, 0b00000, 0b00000, 0b00000, 0b00000, 0b00000
};

byte painChar[] = { 0b00000, 0b00000, 0b11011, 0b11011, 0b00000, 0b01110, 0b10001, 0b00000
};

void setup() {
  pinMode(moistureSensorPin, INPUT);
  pinMode(lightSensorPin, INPUT);
  pinMode(buttonPin, INPUT);

  
  bmp.begin(0x76);
  bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,     /* Operating Mode. */
                  Adafruit_BMP280::SAMPLING_X2,     /* Temp. oversampling */
                  Adafruit_BMP280::SAMPLING_X16,    /* Pressure oversampling */
                  Adafruit_BMP280::FILTER_X16,      /* Filtering. */
                  Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */
  
  
  lcd.begin(0x27, 16, 2);

  lcd.createChar(0, pressureChar);
  lcd.createChar(1, painChar);
  lcd.createChar(2, lightIntensityChar);
  lcd.createChar(3, temperatureChar);
  lcd.createChar(4, moistureChar);
  lcd.createChar(5, halfMoistureChar);
  lcd.createChar(6, emptyMoistureChar);
  lcd.createChar(7, degreeChar);

  lcd.home();
  lcd.clear();
  lcd.backlight(); //lcd.noBacklight();

  lcd.setCursor(1,0);
  lcd.print("Plant Station");
  lcd.setCursor(6,1);
  lcd.print("V1.0");

  delay(2000);

  lcd.noBacklight();
  lcd.clear();

  lcd.setCursor(0,0);
  lcd.write(byte(3));
  lcd.setCursor(10,0);
  lcd.write(byte(2));
  lcd.setCursor(0,1);
  lcd.write(byte(0));
  lcd.setCursor(10,1);
  lcd.write(byte(4));
  lcd.setCursor(7,0);
  lcd.write(byte(7));
  lcd.setCursor(8,0);
  lcd.print("C");
  lcd.setCursor(15,0);
  lcd.print("%");
  lcd.setCursor(6,1);
  lcd.print("hPa");
  lcd.setCursor(15,1);
  lcd.print("%");
}

void loop() {
  currentMillis = millis();

  readMoistureSensor();
  readLightSensor();
  readTemperature();
  readPressure();
  readButtonState();
  updateBacklight();
  updateLCD();
}

void readMoistureSensor() {
    if(currentMillis - previousMoistureSensorMillis >= moistureSensorInterval) {
        soilMoisture = analogRead(26);
        soilMoisturePercent = map(soilMoisture, AirValue, WaterValue, 0, 100);

        if(soilMoisturePercent >= 100) soilMoisturePercent = 100;
            else if(soilMoisturePercent <= 0) soilMoisturePercent = 0;

        previousMoistureSensorMillis += moistureSensorInterval;
    }
}

void readLightSensor() {
    if(currentMillis - previousLightSensorMillis >= lightSensorInterval) {
        lightIntensity = analogRead(27);
        lightIntensityPercent = map(lightIntensity, DarkValue, LightValue, 0, 100);

        if(lightIntensityPercent >= 100) lightIntensityPercent = 100;
            else if(lightIntensityPercent <= 0) lightIntensityPercent = 0;

        previousLightSensorMillis += lightSensorInterval;
    }
}

void readTemperature() {
    if(currentMillis - previousTemperatureMillis >= temperatureSensorInterval) {
        temperature = bmp.readTemperature();

        previousTemperatureMillis += temperatureSensorInterval;
    }
}

void readPressure() {
    if(currentMillis - previousPressureMillis >= pressureSensorInterval) {
        pressure = (bmp.readPressure()/100);

        previousPressureMillis += pressureSensorInterval;
    }
}

void readButtonState() {
    if(currentMillis - previousButtonMillis >= buttonInterval)  {
        buttonState = digitalRead(buttonPin);
    
        if(buttonState == HIGH) {
            lcdBacklightStatus = !lcdBacklightStatus;
        }

        previousButtonMillis += buttonInterval;
    }
}

void updateBacklight() {
    if(lcdBacklightStatus == HIGH) {
        lcd.backlight();
    } else {
        lcd.noBacklight();
    }
}

void updateLCD() {
    if(currentMillis - previousLCDMillis >= lcdUpdateInterval) {
        if(soilMoisturePercent >= 50) {
            lcd.setCursor(10,1);
            lcd.write(byte(4));
        } else if(soilMoisturePercent >= 25) {
            lcd.setCursor(10,1);
            lcd.write(byte(5));
        } else {
            lcd.setCursor(10,1);
            lcd.write(byte(6));
        }

        if(pressure > 1007) {
            lcd.setCursor(0,1);
            lcd.write(byte(0));
        } else {
            lcd.setCursor(0,1);
            lcd.write(byte(1));
        }

        lcd.setCursor(3,0);
        lcd.print(temperature,1);
        lcd.setCursor(2,1);
        lcd.print(pressure);
        if(soilMoisturePercent < 10) {
            lcd.setCursor(13,1);
            lcd.print(" ");
            lcd.print(soilMoisturePercent);
        } else if(soilMoisturePercent < 100) {
            lcd.setCursor(13,1);
            lcd.print(soilMoisturePercent);
        } else {
            lcd.setCursor(12,1);
            lcd.print(soilMoisturePercent);
        }
        if(lightIntensityPercent < 10) {
            lcd.setCursor(13,0);
            lcd.print(" ");
            lcd.print(lightIntensityPercent);
        } else if(lightIntensityPercent < 100) {
            lcd.setCursor(13,0);
            lcd.print(lightIntensityPercent);
        } else {
            lcd.setCursor(12,0);
            lcd.print(lightIntensityPercent);
        }

        previousLCDMillis += lcdUpdateInterval;
    }
}
票数 0
EN

Stack Overflow用户

发布于 2022-10-23 17:13:52

RP2040没有一个打开按钮的功能,您只需将其写到某个寄存器的某个位置即可打开。

您将不得不执行多个数字读数,并使用一个定时功能,如millis(),以检测什么时候按钮已按住或释放了足够长的时间。您可以使用Pololu中的按钮,按钮库来完成该操作,或者将其代码作为参考来阅读,这样您就可以了解如何实现自己的删除。

您还可以考虑使用PIO状态机读取按钮,并只向主CPU发送新闻/发布事件。

票数 0
EN

Stack Overflow用户

发布于 2022-10-27 04:24:08

在示例代码中,LCD初始化存在一些问题。begin()的API是

代码语言:javascript
复制
begin(cols, rows, [dotsize]);

其中dotsize是可选的,但用于在5x8或5x10字体大小之间进行选择。你很幸运,用过的东西能起作用:

代码语言:javascript
复制
lcd.begin(0x27, 16, 2);

这会将列设置为39列,将行设置为16 (这不是正确的几何形状),并根据库代码的工作方式,使用2表示点大小(这不是有效的参数),最后将字体大小设置为5x10。但由于该字体大小仅适用于单行显示,因此默认为5x8字体。

此外,您还应该考虑使用自动配置构造函数,因此不需要指定i2c地址。有关详细信息,请参阅所包含的文档。类似于API文档和wiki,获得关于hd44780_I2Cexp i/o类的更多文档。

https://github.com/duinoWitchery/hd44780/wiki

I2Cexp

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74167514

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档