1. Optimize compatibility definition

This commit is contained in:
onexs-xsi
2026-01-08 14:53:16 +08:00
parent 979547ec82
commit 4a3041b4e6
3 changed files with 479 additions and 25 deletions
+342
View File
@@ -0,0 +1,342 @@
/*
* SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
*
* SPDX-License-Identifier: MIT
*/
/*
* M5IOE1 引脚测试示例
* M5IOE1 Pin Test Example
*
* 本示例展示 M5IOE1 库的核心功能
* This example demonstrates the core features of M5IOE1 library
*
* 硬件连接 / Hardware Connections:
* - M5IOE1 SDA -> GPIO 38, SCL -> GPIO 39
* - IO1 -> 按钮 (Button, active LOW to GND)
* - IO3 -> LED (through 220Ω to GND)
* - IO2 -> 电位器 / Potentiometer (ADC Channel 1, 0-3.3V)
* - IO9 -> LED (PWM Channel 0, through 220Ω to GND)
*/
#include <M5IOE1.h>
// ============================
// 配置 / Configuration
// ============================
#define I2C_SDA_PIN 38
#define I2C_SCL_PIN 39
#define I2C_FREQ 400000
#define I2C_ADDR M5IOE1_DEFAULT_ADDR
// ============================
// 引脚定义 / Pin Definitions
// ============================
// IO1 (Pin 0) - 数字输入,按钮 / Digital input, button
#define PIN_BUTTON M5IOE1_PIN_1 // IO1
// IO3 (Pin 2) - 数字输出,LED / Digital output, LED
#define PIN_LED M5IOE1_PIN_3 // IO3
// IO2 (Pin 1) - ADC 输入,电位器 / ADC input, potentiometer (ADC Channel 1)
#define PIN_ADC M5IOE1_PIN_2 // IO2 -> ADC_CH1
// IO9 (Pin 8) - PWM 输出,LED / PWM output, LED (PWM Channel 0)
#define PIN_PWM M5IOE1_PIN_9 // IO9 -> PWM_CH1
// ============================
// 全局变量 / Global Variables
// ============================
M5IOE1 ioe1;
volatile int buttonPressCount = 0;
uint8_t pwmValue = 0;
int pwmDirection = 1;
// ============================
// 中断回调函数 / Interrupt Callback
// ============================
void IRAM_ATTR buttonPressed() {
buttonPressCount++;
}
// ============================
// 辅助函数 / Helper Functions
// ============================
void printSeparator(const char* title) {
Serial.println("\n========================================");
Serial.println(title);
Serial.println("========================================\n");
}
void testDigitalWrite() {
printSeparator("测试 digitalWrite() / Testing digitalWrite()");
Serial.println("Blinking LED on IO3 (3 cycles)...\n");
for (int i = 0; i < 3; i++) {
Serial.print("Cycle ");
Serial.print(i + 1);
Serial.println(": HIGH -> LOW");
ioe1.digitalWrite(PIN_LED, HIGH);
delay(500);
ioe1.digitalWrite(PIN_LED, LOW);
delay(500);
}
Serial.println("digitalWrite() test completed!\n");
}
void testDigitalRead() {
printSeparator("测试 digitalRead() / Testing digitalRead()");
Serial.println("Reading button on IO1 (active LOW) for 8 seconds...");
Serial.println("Press the button to test!\n");
unsigned long startTime = millis();
int lastState = -1;
while (millis() - startTime < 8000) {
int currentState = ioe1.digitalRead(PIN_BUTTON);
if (currentState != lastState) {
Serial.print("State: ");
Serial.println(currentState == LOW ? "LOW (pressed)" : "HIGH (released)");
lastState = currentState;
}
delay(50);
}
Serial.println("\ndigitalRead() test completed!\n");
}
void testPinMode() {
printSeparator("测试 pinMode() / Testing pinMode()");
Serial.println("Testing pin modes on IO3:\n");
// OUTPUT + 闪烁测试 / OUTPUT + Blink test
Serial.println("1. OUTPUT mode");
ioe1.pinMode(PIN_LED, OUTPUT);
for (int i = 0; i < 2; i++) {
ioe1.digitalWrite(PIN_LED, HIGH);
delay(200);
ioe1.digitalWrite(PIN_LED, LOW);
delay(200);
}
Serial.println(" -> Blink test OK\n");
// INPUT + 读取测试 / INPUT + Read test
Serial.println("2. INPUT mode (floating)");
ioe1.pinMode(PIN_LED, INPUT);
int val = ioe1.digitalRead(PIN_LED);
Serial.print(" -> Read: ");
Serial.println(val == HIGH ? "HIGH" : "LOW");
Serial.println(" -> OK\n");
// INPUT_PULLUP + 读取测试 / INPUT_PULLUP + Read test
Serial.println("3. INPUT_PULLUP mode");
ioe1.pinMode(PIN_LED, INPUT_PULLUP);
val = ioe1.digitalRead(PIN_LED);
Serial.print(" -> Read: ");
Serial.println(val == HIGH ? "HIGH (pulled up)" : "LOW");
Serial.println(" -> OK\n");
// 恢复输出模式 / Restore OUTPUT mode
ioe1.pinMode(PIN_LED, OUTPUT);
Serial.println("pinMode() test completed!\n");
}
void testAnalogRead() {
printSeparator("测试 analogRead() / Testing analogRead()");
Serial.println("Reading ADC Channel 1 (IO2) for 8 seconds...");
Serial.println("Rotate potentiometer to test!\n");
unsigned long startTime = millis();
unsigned long lastPrint = 0;
while (millis() - startTime < 8000) {
uint16_t adcValue;
if (ioe1.analogRead(1, &adcValue)) {
if (millis() - lastPrint > 500) {
float voltage = (adcValue * 3300.0f) / 4095.0f;
Serial.print("Value: ");
Serial.print(adcValue);
Serial.print(" (");
Serial.print((int)voltage);
Serial.println(" mV)");
// 简单的条形图 / Simple bar graph
int bars = map(adcValue, 0, 4095, 0, 20);
Serial.print("[");
for (int i = 0; i < 20; i++) {
Serial.print(i < bars ? "=" : " ");
}
Serial.println("]\n");
lastPrint = millis();
}
}
delay(50);
}
Serial.println("analogRead() test completed!\n");
}
void testAnalogWrite() {
printSeparator("测试 analogWrite() / Testing analogWrite()");
Serial.println("PWM breathing on IO9 (Channel 0)...\n");
ioe1.setPwmFrequency(5000);
Serial.println("PWM frequency: 5000 Hz\n");
unsigned long startTime = millis();
while (millis() - startTime < 8000) {
if (ioe1.analogWrite(0, pwmValue)) {
if (pwmValue % 25 == 0) {
float duty = (pwmValue * 100.0f) / 255.0f;
Serial.print("PWM value: ");
Serial.print(pwmValue);
Serial.print(" (");
Serial.print((int)duty);
Serial.println("%)");
}
}
// 呼吸效果 / Breathing effect
pwmValue += pwmDirection * 5;
if (pwmValue >= 255) {
pwmValue = 255;
pwmDirection = -1;
} else if (pwmValue <= 0) {
pwmValue = 0;
pwmDirection = 1;
}
delay(20);
}
ioe1.analogWrite(0, 0);
Serial.println("\nPWM turned off.\n");
Serial.println("analogWrite() test completed!\n");
}
void testAttachInterrupt() {
printSeparator("测试 attachInterrupt() / Testing attachInterrupt()");
Serial.println("Configuring button with interrupt (FALLING edge)...\n");
ioe1.pinMode(PIN_BUTTON, INPUT_PULLUP);
buttonPressCount = 0;
ioe1.attachInterrupt(PIN_BUTTON, buttonPressed, FALLING);
Serial.println("Interrupt attached! Press button for 8 seconds...\n");
unsigned long startTime = millis();
int lastCount = 0;
while (millis() - startTime < 8000) {
if (buttonPressCount != lastCount) {
Serial.print("Button press detected! Count: ");
Serial.println(buttonPressCount);
lastCount = buttonPressCount;
}
delay(50);
}
Serial.print("\nTotal presses: ");
Serial.println(buttonPressCount);
ioe1.detachInterrupt(PIN_BUTTON);
Serial.println("Interrupt detached.\n");
Serial.println("attachInterrupt() test completed!\n");
}
// ============================
// Arduino setup() / loop()
// ============================
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("\n\n######################################");
Serial.println("# M5IOE1 Pin Test Example #");
Serial.println("######################################\n");
// 设置日志级别 / Set log level
M5IOE1::setLogLevel(M5IOE1_LOG_LEVEL_WARN);
// 初始化 M5IOE1 / Initialize M5IOE1
Serial.println("Initializing M5IOE1...");
if (!ioe1.begin(&Wire, I2C_ADDR, I2C_SDA_PIN, I2C_SCL_PIN, I2C_FREQ)) {
Serial.println("ERROR: Failed to initialize M5IOE1!");
Serial.println("Please check I2C connections and power supply.");
while (1) { delay(1000); }
}
Serial.println("M5IOE1 initialized successfully!\n");
// 读取设备信息 / Read device info
uint16_t uid;
uint8_t version;
if (ioe1.getUID(&uid)) {
Serial.println("Device UID: 0x" + String(uid, HEX));
}
if (ioe1.getVersion(&version)) {
Serial.println("Firmware Version: " + String(version));
}
Serial.println();
// 初始化测试引脚 / Initialize test pins
Serial.println("Initializing test pins...");
ioe1.pinMode(PIN_BUTTON, INPUT_PULLUP);
ioe1.pinMode(PIN_LED, OUTPUT);
ioe1.digitalWrite(PIN_LED, LOW);
Serial.println("Test pins ready!\n");
delay(2000);
}
void loop() {
static int testStep = 0;
switch (testStep) {
case 0:
testPinMode();
break;
case 1:
testDigitalWrite();
break;
case 2:
testDigitalRead();
break;
case 3:
testAnalogRead();
break;
case 4:
testAnalogWrite();
break;
case 5:
testAttachInterrupt();
break;
default:
Serial.println("\n\n######################################");
Serial.println("# All tests completed! #");
Serial.println("# Restarting in 5 seconds... #");
Serial.println("######################################\n");
delay(5000);
testStep = -1;
break;
}
testStep++;
if (testStep != 0) {
Serial.println("Next test starting in 2 seconds...\n");
delay(2000);
}
}
+66 -4
View File
@@ -910,28 +910,30 @@ void M5IOE1::pinMode(uint8_t pin, uint8_t mode) {
if (!_readReg16(M5IOE1_REG_GPIO_DRV_L, &drvReg)) return;
switch (mode) {
case INPUT:
case INPUT: // 0x01
modeReg &= ~(1 << pin);
puReg &= ~(1 << pin);
pdReg &= ~(1 << pin);
_pinStates[pin].isOutput = false;
_pinStates[pin].pull = 0;
break;
case INPUT_PULLUP:
case PULLUP: // 0x04 - 仅上拉
case INPUT_PULLUP: // 0x05
modeReg &= ~(1 << pin);
puReg |= (1 << pin);
pdReg &= ~(1 << pin);
_pinStates[pin].isOutput = false;
_pinStates[pin].pull = 1;
break;
case INPUT_PULLDOWN:
case PULLDOWN: // 0x08 - 仅下拉
case INPUT_PULLDOWN: // 0x09
modeReg &= ~(1 << pin);
puReg &= ~(1 << pin);
pdReg |= (1 << pin);
_pinStates[pin].isOutput = false;
_pinStates[pin].pull = 2;
break;
case OUTPUT:
case OUTPUT: // 0x03
// 如果此引脚上启用了 PWM 则禁用
// Disable PWM if enabled on this pin
if (_isPwmPin(pin)) {
@@ -953,6 +955,38 @@ void M5IOE1::pinMode(uint8_t pin, uint8_t mode) {
_pinStates[pin].isOutput = true;
_pinStates[pin].drive = 0;
break;
case OPEN_DRAIN: // 0x10
case OUTPUT_OPEN_DRAIN: // 0x13
// 如果此引脚上启用了 PWM 则禁用
// Disable PWM if enabled on this pin
if (_isPwmPin(pin)) {
uint8_t ch = _getPwmChannel(pin);
uint8_t regL = M5IOE1_REG_PWM1_DUTY_L + ch * 2;
uint16_t pwmData = 0;
if (_readReg16(regL, &pwmData)) {
if (pwmData & ((uint16_t)M5IOE1_PWM_ENABLE << 8)) {
pwmData &= ~((uint16_t)M5IOE1_PWM_ENABLE << 8);
_writeReg16(regL, pwmData);
}
}
}
modeReg |= (1 << pin);
puReg &= ~(1 << pin);
pdReg &= ~(1 << pin);
drvReg |= (1 << pin); // 开漏
// Open-drain
_pinStates[pin].isOutput = true;
_pinStates[pin].drive = 1;
break;
case ANALOG: // 0xC0
// 模拟模式 - 设置为输入,无上拉下拉
// Analog mode - set as input, no pull-up/down
modeReg &= ~(1 << pin);
puReg &= ~(1 << pin);
pdReg &= ~(1 << pin);
_pinStates[pin].isOutput = false;
_pinStates[pin].pull = 0;
break;
default:
M5IOE1_LOG_E(TAG, "Invalid mode: %d", mode);
return;
@@ -1386,6 +1420,34 @@ bool M5IOE1::getPwmDuty12bit(uint8_t channel, uint16_t* duty12, bool* polarity,
return true;
}
// ============================
// Arduino 兼容 analogWrite
// Arduino-compatible analogWrite
// ============================
bool M5IOE1::analogWrite(uint8_t channel, uint8_t value) {
if (channel > 3 || !_initialized) {
M5IOE1_LOG_E(TAG, "Invalid channel or not initialized: ch=%d", channel);
return false;
}
// 值为 0 时关闭 PWM 输出
// Turn off PWM when value is 0
if (value == 0) {
return setPwmDuty12bit(channel, 0, false, false);
}
// 将 8-bit 值 (0-255) 缩放到 12-bit (0-4095)
// Scale 8-bit value (0-255) to 12-bit (0-4095)
// 公式:duty12 = (value * 4095) / 255 = value * 16 + value / 16
// Formula: duty12 = (value * 4095) / 255 = value * 16 + value / 16
uint16_t duty12 = (uint16_t)value * 16 + (uint16_t)value / 16;
// 设置 PWM,默认启用输出,正常极性
// Set PWM with output enabled, normal polarity
return setPwmDuty12bit(channel, duty12, false, true);
}
// ============================
// NeoPixel LED 功能
// NeoPixel LED Functions
+71 -21
View File
@@ -172,43 +172,76 @@ typedef enum {
#define M5IOE1_PWM_CH3 2 // IO11 (pin index 10)
#define M5IOE1_PWM_CH4 3 // IO10 (pin index 9)
// ============================
// GPIO 模式定义(Arduino 兼容)
// GPIO Mode Definitions (Arduino-compatible)
// ============================
#ifndef INPUT
#define INPUT 0x00
#endif
#ifndef OUTPUT
#define OUTPUT 0x01
#endif
#ifndef INPUT_PULLUP
#define INPUT_PULLUP 0x02
#endif
#ifndef INPUT_PULLDOWN
#define INPUT_PULLDOWN 0x03
#endif
// ============================
// GPIO 电平定义
// GPIO Level Definitions
// ============================
#ifndef LOW
#define LOW 0
#define LOW 0x0
#endif
#ifndef HIGH
#define HIGH 1
#define HIGH 0x1
#endif
// ============================
// GPIO 模式定义(Arduino 兼容)
// GPIO Mode Definitions (Arduino-compatible)
// ============================
#ifndef INPUT
#define INPUT 0x01
#endif
#ifndef OUTPUT
#define OUTPUT 0x03
#endif
#ifndef PULLUP
#define PULLUP 0x04
#endif
#ifndef INPUT_PULLUP
#define INPUT_PULLUP 0x05
#endif
#ifndef PULLDOWN
#define PULLDOWN 0x08
#endif
#ifndef INPUT_PULLDOWN
#define INPUT_PULLDOWN 0x09
#endif
#ifndef OPEN_DRAIN
#define OPEN_DRAIN 0x10
#endif
#ifndef OUTPUT_OPEN_DRAIN
#define OUTPUT_OPEN_DRAIN 0x13
#endif
#ifndef ANALOG
#define ANALOG 0xC0
#endif
// ============================
// 中断模式定义
// Interrupt Mode Definitions
// ============================
#ifndef DISABLED
#define DISABLED 0x00
#endif
#ifndef RISING
#define RISING 0x01
#define RISING 0x01
#endif
#ifndef FALLING
#define FALLING 0x02
#define FALLING 0x02
#endif
#ifndef CHANGE
#define CHANGE 0x03
#endif
#ifndef ONLOW
#define ONLOW 0x04
#endif
#ifndef ONHIGH
#define ONHIGH 0x05
#endif
#ifndef ONLOW_WE
#define ONLOW_WE 0x0C
#endif
#ifndef ONHIGH_WE
#define ONHIGH_WE 0x0D
#endif
// ============================
@@ -654,6 +687,23 @@ public:
bool setPwmDuty12bit(uint8_t channel, uint16_t duty12, bool polarity = false, bool enable = true);
bool getPwmDuty12bit(uint8_t channel, uint16_t* duty12, bool* polarity, bool* enable);
/**
* @brief Arduino-compatible analogWrite function (PWM output)
* Arduino analogWrite PWM
* @param channel PWM channel (0-3): M5IOE1_PWM_CH1/CH2/CH3/CH4
* PWM 0-3M5IOE1_PWM_CH1/CH2/CH3/CH4
* CH1=IO9, CH2=IO8, CH3=IO11, CH4=IO10
* @param value PWM duty cycle (0-255, 8-bit Arduino standard)
* PWM 0-2558-bit Arduino
* 0 = 0% duty, 127 = 50% duty, 255 = 100% duty
* @return true if successful
* @note This function scales 8-bit value to 12-bit internally
* 8-bit 12-bit
* @note Value 0 turns off PWM output
* 0 PWM
*/
bool analogWrite(uint8_t channel, uint8_t value);
// ========================
// NeoPixel LED 功能
// NeoPixel LED Functions