Merge branch 'debug/ads1256-reg-issue' into gml670x4/dev
This commit is contained in:
+4
-4
@@ -46,21 +46,21 @@
|
|||||||
|
|
||||||
/ {
|
/ {
|
||||||
aliases {
|
aliases {
|
||||||
ads-cs = &ads_cs_pin;
|
|
||||||
ads-drdy = &ads_drdy_pin;
|
ads-drdy = &ads_drdy_pin;
|
||||||
ads-reset = &ads_reset_pin;
|
ads-reset = &ads_reset_pin;
|
||||||
|
ads-pdwn = &ads_pdwn_pin;
|
||||||
};
|
};
|
||||||
|
|
||||||
ads1256_control {
|
ads1256_control {
|
||||||
compatible = "gpio-keys";
|
compatible = "gpio-keys";
|
||||||
ads_cs_pin: ads_cs {
|
|
||||||
gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
|
|
||||||
};
|
|
||||||
ads_drdy_pin: ads_drdy {
|
ads_drdy_pin: ads_drdy {
|
||||||
gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
|
gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
|
||||||
};
|
};
|
||||||
ads_reset_pin: ads_reset {
|
ads_reset_pin: ads_reset {
|
||||||
gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
|
gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
|
||||||
};
|
};
|
||||||
|
ads_pdwn_pin: ads_pdwn {
|
||||||
|
gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
int button_init(void);
|
int button_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief EMI 自恢复事件指示:点亮 LED1 并在 3 秒后自动熄灭。
|
||||||
|
*
|
||||||
|
* 复用按键反馈所用的 LED1,外部子系统(如 sensor)在检测到 ADS1256
|
||||||
|
* 寄存器被 EMI 干扰并完成恢复后调用,给出可见的故障告警。
|
||||||
|
*
|
||||||
|
* @return 无返回值。
|
||||||
|
*/
|
||||||
|
void button_led_indicate_emi(void);
|
||||||
|
|||||||
+131
-43
@@ -22,15 +22,37 @@ LOG_MODULE_REGISTER(ads1256, LOG_LEVEL_INF);
|
|||||||
#define REG_MUX 0x01
|
#define REG_MUX 0x01
|
||||||
#define REG_ADCON 0x02
|
#define REG_ADCON 0x02
|
||||||
#define REG_DRATE 0x03
|
#define REG_DRATE 0x03
|
||||||
|
#define REG_IO 0x04
|
||||||
|
#define REG_OFC0 0x05
|
||||||
|
#define REG_OFC1 0x06
|
||||||
|
#define REG_OFC2 0x07
|
||||||
|
#define REG_FSC0 0x08
|
||||||
|
#define REG_FSC1 0x09
|
||||||
|
#define REG_FSC2 0x0A
|
||||||
|
|
||||||
#define SPI_OP (SPI_OP_MODE_MASTER | SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_LINES_SINGLE)
|
#define SPI_OP (SPI_OP_MODE_MASTER | SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_LINES_SINGLE)
|
||||||
|
|
||||||
/* --- 硬件资源 --- */
|
/* --- 硬件资源 --- */
|
||||||
static struct spi_config spi_cfg;
|
static struct spi_config spi_cfg;
|
||||||
static const struct device *spi_dev;
|
static const struct device *spi_dev;
|
||||||
static const struct gpio_dt_spec cs_spec = GPIO_DT_SPEC_GET(DT_ALIAS(ads_cs), gpios);
|
static const struct gpio_dt_spec cs_spec = SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(ads1256));
|
||||||
static const struct gpio_dt_spec drdy_spec = GPIO_DT_SPEC_GET(DT_ALIAS(ads_drdy), gpios);
|
static const struct gpio_dt_spec drdy_spec = GPIO_DT_SPEC_GET(DT_ALIAS(ads_drdy), gpios);
|
||||||
static const struct gpio_dt_spec reset_spec = GPIO_DT_SPEC_GET(DT_ALIAS(ads_reset), gpios);
|
static const struct gpio_dt_spec reset_spec = GPIO_DT_SPEC_GET(DT_ALIAS(ads_reset), gpios);
|
||||||
|
static const struct gpio_dt_spec pdwn_spec = GPIO_DT_SPEC_GET(DT_ALIAS(ads_pdwn), gpios);
|
||||||
|
|
||||||
|
struct ads1256_reg_snapshot {
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t mux;
|
||||||
|
uint8_t adcon;
|
||||||
|
uint8_t drate;
|
||||||
|
uint8_t io;
|
||||||
|
uint8_t ofc0;
|
||||||
|
uint8_t ofc1;
|
||||||
|
uint8_t ofc2;
|
||||||
|
uint8_t fsc0;
|
||||||
|
uint8_t fsc1;
|
||||||
|
uint8_t fsc2;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 等待 DRDY 拉低(转换结果可读),带超时保护。
|
* @brief 等待 DRDY 拉低(转换结果可读),带超时保护。
|
||||||
@@ -61,12 +83,10 @@ int ads1256_wait_drdy(uint16_t timeout_ms) {
|
|||||||
*/
|
*/
|
||||||
void ads1256_write_reg(uint8_t reg, uint8_t val) {
|
void ads1256_write_reg(uint8_t reg, uint8_t val) {
|
||||||
ads1256_wait_drdy(50);
|
ads1256_wait_drdy(50);
|
||||||
gpio_pin_set_dt(&cs_spec, 1);
|
|
||||||
uint8_t tx_buf[3] = { CMD_WREG | reg, 0x00, val };
|
uint8_t tx_buf[3] = { CMD_WREG | reg, 0x00, val };
|
||||||
struct spi_buf tx = { .buf = tx_buf, .len = 3 };
|
struct spi_buf tx = { .buf = tx_buf, .len = 3 };
|
||||||
struct spi_buf_set tx_set = { .buffers = &tx, .count = 1 };
|
struct spi_buf_set tx_set = { .buffers = &tx, .count = 1 };
|
||||||
spi_write(spi_dev, &spi_cfg, &tx_set);
|
spi_write(spi_dev, &spi_cfg, &tx_set);
|
||||||
gpio_pin_set_dt(&cs_spec, 0);
|
|
||||||
/* t11: WREG 后至少 4 × tCLKIN ≈ 0.5µs */
|
/* t11: WREG 后至少 4 × tCLKIN ≈ 0.5µs */
|
||||||
k_busy_wait(2);
|
k_busy_wait(2);
|
||||||
}
|
}
|
||||||
@@ -74,25 +94,90 @@ void ads1256_write_reg(uint8_t reg, uint8_t val) {
|
|||||||
/**
|
/**
|
||||||
* @brief 从 ADS1256 读单个寄存器。
|
* @brief 从 ADS1256 读单个寄存器。
|
||||||
*
|
*
|
||||||
|
* ADS1256 RREG 时序要求:命令+数据在同一次 CS 拉低内完成,
|
||||||
|
* 中间需 t6 延时。这里用单次 transceive 保证 CS 不释放。
|
||||||
|
*
|
||||||
* @param reg 目标寄存器地址。
|
* @param reg 目标寄存器地址。
|
||||||
*
|
*
|
||||||
* @return 读取到的寄存器值。
|
* @return 读取到的寄存器值。
|
||||||
*/
|
*/
|
||||||
uint8_t ads1256_read_reg(uint8_t reg) {
|
uint8_t ads1256_read_reg(uint8_t reg) {
|
||||||
ads1256_wait_drdy(50);
|
ads1256_wait_drdy(50);
|
||||||
gpio_pin_set_dt(&cs_spec, 1);
|
/* tx: [RREG|reg, 0x00, dummy_for_t6, dummy_read]
|
||||||
uint8_t tx_buf[2] = { CMD_RREG | reg, 0x00 };
|
* rx: [x, x, x, data] — 前 3 字节是命令+延时期间的垃圾 */
|
||||||
struct spi_buf tx = { .buf = tx_buf, .len = 2 };
|
uint8_t tx_buf[4] = { CMD_RREG | reg, 0x00, 0xFF, 0xFF };
|
||||||
|
uint8_t rx_buf[4] = { 0 };
|
||||||
|
struct spi_buf tx = { .buf = tx_buf, .len = 4 };
|
||||||
struct spi_buf_set tx_set = { .buffers = &tx, .count = 1 };
|
struct spi_buf_set tx_set = { .buffers = &tx, .count = 1 };
|
||||||
spi_write(spi_dev, &spi_cfg, &tx_set);
|
struct spi_buf rx = { .buf = rx_buf, .len = 4 };
|
||||||
/* t6: RREG 后至少 50 × tCLKIN ≈ 6.5µs */
|
|
||||||
k_busy_wait(10);
|
|
||||||
uint8_t rx_val = 0;
|
|
||||||
struct spi_buf rx = { .buf = &rx_val, .len = 1 };
|
|
||||||
struct spi_buf_set rx_set = { .buffers = &rx, .count = 1 };
|
struct spi_buf_set rx_set = { .buffers = &rx, .count = 1 };
|
||||||
spi_read(spi_dev, &spi_cfg, &rx_set);
|
spi_transceive(spi_dev, &spi_cfg, &tx_set, &rx_set);
|
||||||
gpio_pin_set_dt(&cs_spec, 0);
|
return rx_buf[3];
|
||||||
return rx_val;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 连续读取 ADS1256 关键寄存器,形成一次诊断快照。
|
||||||
|
*
|
||||||
|
* @param snapshot 输出快照对象,不能为空。
|
||||||
|
*/
|
||||||
|
static void ads1256_read_snapshot(struct ads1256_reg_snapshot *snapshot) {
|
||||||
|
snapshot->status = ads1256_read_reg(REG_STATUS);
|
||||||
|
snapshot->mux = ads1256_read_reg(REG_MUX);
|
||||||
|
snapshot->adcon = ads1256_read_reg(REG_ADCON);
|
||||||
|
snapshot->drate = ads1256_read_reg(REG_DRATE);
|
||||||
|
snapshot->io = ads1256_read_reg(REG_IO);
|
||||||
|
snapshot->ofc0 = ads1256_read_reg(REG_OFC0);
|
||||||
|
snapshot->ofc1 = ads1256_read_reg(REG_OFC1);
|
||||||
|
snapshot->ofc2 = ads1256_read_reg(REG_OFC2);
|
||||||
|
snapshot->fsc0 = ads1256_read_reg(REG_FSC0);
|
||||||
|
snapshot->fsc1 = ads1256_read_reg(REG_FSC1);
|
||||||
|
snapshot->fsc2 = ads1256_read_reg(REG_FSC2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 仅打印恢复前后发生变化的寄存器。
|
||||||
|
*
|
||||||
|
* @param tag 日志标签,用于区分恢复成功与失败后的变化。
|
||||||
|
* @param before 恢复前寄存器快照。
|
||||||
|
* @param after 恢复后寄存器快照。
|
||||||
|
*/
|
||||||
|
static void ads1256_log_snapshot_delta(
|
||||||
|
const char *tag,
|
||||||
|
const struct ads1256_reg_snapshot *before,
|
||||||
|
const struct ads1256_reg_snapshot *after) {
|
||||||
|
if (before->status != after->status) {
|
||||||
|
LOG_WRN("%s STATUS: 0x%02X -> 0x%02X", tag, before->status, after->status);
|
||||||
|
}
|
||||||
|
if (before->mux != after->mux) {
|
||||||
|
LOG_WRN("%s MUX: 0x%02X -> 0x%02X", tag, before->mux, after->mux);
|
||||||
|
}
|
||||||
|
if (before->adcon != after->adcon) {
|
||||||
|
LOG_WRN("%s ADCON: 0x%02X -> 0x%02X", tag, before->adcon, after->adcon);
|
||||||
|
}
|
||||||
|
if (before->drate != after->drate) {
|
||||||
|
LOG_WRN("%s DRATE: 0x%02X -> 0x%02X", tag, before->drate, after->drate);
|
||||||
|
}
|
||||||
|
if (before->io != after->io) {
|
||||||
|
LOG_WRN("%s IO: 0x%02X -> 0x%02X", tag, before->io, after->io);
|
||||||
|
}
|
||||||
|
if (before->ofc0 != after->ofc0) {
|
||||||
|
LOG_WRN("%s OFC0: 0x%02X -> 0x%02X", tag, before->ofc0, after->ofc0);
|
||||||
|
}
|
||||||
|
if (before->ofc1 != after->ofc1) {
|
||||||
|
LOG_WRN("%s OFC1: 0x%02X -> 0x%02X", tag, before->ofc1, after->ofc1);
|
||||||
|
}
|
||||||
|
if (before->ofc2 != after->ofc2) {
|
||||||
|
LOG_WRN("%s OFC2: 0x%02X -> 0x%02X", tag, before->ofc2, after->ofc2);
|
||||||
|
}
|
||||||
|
if (before->fsc0 != after->fsc0) {
|
||||||
|
LOG_WRN("%s FSC0: 0x%02X -> 0x%02X", tag, before->fsc0, after->fsc0);
|
||||||
|
}
|
||||||
|
if (before->fsc1 != after->fsc1) {
|
||||||
|
LOG_WRN("%s FSC1: 0x%02X -> 0x%02X", tag, before->fsc1, after->fsc1);
|
||||||
|
}
|
||||||
|
if (before->fsc2 != after->fsc2) {
|
||||||
|
LOG_WRN("%s FSC2: 0x%02X -> 0x%02X", tag, before->fsc2, after->fsc2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -102,31 +187,23 @@ uint8_t ads1256_read_reg(uint8_t reg) {
|
|||||||
*/
|
*/
|
||||||
void ads1256_write_cmd(uint8_t cmd) {
|
void ads1256_write_cmd(uint8_t cmd) {
|
||||||
ads1256_wait_drdy(50);
|
ads1256_wait_drdy(50);
|
||||||
gpio_pin_set_dt(&cs_spec, 1);
|
|
||||||
struct spi_buf tx = { .buf = &cmd, .len = 1 };
|
struct spi_buf tx = { .buf = &cmd, .len = 1 };
|
||||||
struct spi_buf_set tx_set = { .buffers = &tx, .count = 1 };
|
struct spi_buf_set tx_set = { .buffers = &tx, .count = 1 };
|
||||||
spi_write(spi_dev, &spi_cfg, &tx_set);
|
spi_write(spi_dev, &spi_cfg, &tx_set);
|
||||||
gpio_pin_set_dt(&cs_spec, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 发送 SYNC + WAKEUP 命令,触发一次同步采样。
|
* @brief 发送 SYNC + WAKEUP 命令,触发一次同步采样。
|
||||||
*
|
*
|
||||||
* @return 无返回值。
|
* SYNC 和 WAKEUP 必须在同一次 CS 内完成,用单次 transceive 保持 CS。
|
||||||
|
* 中间插入 dummy 字节满足 t11 延时 (24 × tCLKIN ≈ 3.1µs)。
|
||||||
*/
|
*/
|
||||||
void ads1256_sync_wakeup(void) {
|
void ads1256_sync_wakeup(void) {
|
||||||
uint8_t cmd_sync = CMD_SYNC;
|
/* [SYNC, dummy(延时), WAKEUP] — 500kHz 下每字节 16µs,1 字节 dummy 远超 3.1µs */
|
||||||
uint8_t cmd_wakeup = CMD_WAKEUP;
|
uint8_t tx_buf[3] = { CMD_SYNC, 0xFF, CMD_WAKEUP };
|
||||||
struct spi_buf tx_s = { .buf = &cmd_sync, .len = 1 };
|
struct spi_buf tx = { .buf = tx_buf, .len = 3 };
|
||||||
struct spi_buf tx_w = { .buf = &cmd_wakeup, .len = 1 };
|
struct spi_buf_set tx_set = { .buffers = &tx, .count = 1 };
|
||||||
struct spi_buf_set set_s = { .buffers = &tx_s, .count = 1 };
|
spi_write(spi_dev, &spi_cfg, &tx_set);
|
||||||
struct spi_buf_set set_w = { .buffers = &tx_w, .count = 1 };
|
|
||||||
gpio_pin_set_dt(&cs_spec, 1);
|
|
||||||
spi_write(spi_dev, &spi_cfg, &set_s);
|
|
||||||
/* t11: SYNC 后至少 24 × tCLKIN ≈ 3.1µs */
|
|
||||||
k_busy_wait(4);
|
|
||||||
spi_write(spi_dev, &spi_cfg, &set_w);
|
|
||||||
gpio_pin_set_dt(&cs_spec, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -149,22 +226,21 @@ int ads1256_hwreset(void) {
|
|||||||
/**
|
/**
|
||||||
* @brief 读取当前 24 位转换结果,符号扩展为 int32_t。
|
* @brief 读取当前 24 位转换结果,符号扩展为 int32_t。
|
||||||
*
|
*
|
||||||
|
* RDATA 命令后需 t6 延时再读 3 字节数据,全部在同一次 CS 内完成。
|
||||||
|
*
|
||||||
* @return 当前 ADC 转换原始值。
|
* @return 当前 ADC 转换原始值。
|
||||||
*/
|
*/
|
||||||
int32_t ads1256_read_data(void) {
|
int32_t ads1256_read_data(void) {
|
||||||
uint8_t cmd = CMD_RDATA;
|
/* tx: [RDATA, dummy(t6延时), MSB, MID, LSB]
|
||||||
uint8_t rx_buf[3] = { 0 };
|
* rx: [x, x, MSB, MID, LSB] */
|
||||||
gpio_pin_set_dt(&cs_spec, 1);
|
uint8_t tx_buf[5] = { CMD_RDATA, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||||
struct spi_buf tx = { .buf = &cmd, .len = 1 };
|
uint8_t rx_buf[5] = { 0 };
|
||||||
|
struct spi_buf tx = { .buf = tx_buf, .len = 5 };
|
||||||
struct spi_buf_set tx_set = { .buffers = &tx, .count = 1 };
|
struct spi_buf_set tx_set = { .buffers = &tx, .count = 1 };
|
||||||
spi_write(spi_dev, &spi_cfg, &tx_set);
|
struct spi_buf rx = { .buf = rx_buf, .len = 5 };
|
||||||
/* t6: RDATA 后至少 50 × tCLKIN ≈ 6.5µs */
|
|
||||||
k_busy_wait(10);
|
|
||||||
struct spi_buf rx = { .buf = rx_buf, .len = 3 };
|
|
||||||
struct spi_buf_set rx_set = { .buffers = &rx, .count = 1 };
|
struct spi_buf_set rx_set = { .buffers = &rx, .count = 1 };
|
||||||
spi_read(spi_dev, &spi_cfg, &rx_set);
|
spi_transceive(spi_dev, &spi_cfg, &tx_set, &rx_set);
|
||||||
gpio_pin_set_dt(&cs_spec, 0);
|
int32_t val = ((int32_t)rx_buf[2] << 16) | ((int32_t)rx_buf[3] << 8) | rx_buf[4];
|
||||||
int32_t val = ((int32_t)rx_buf[0] << 16) | ((int32_t)rx_buf[1] << 8) | rx_buf[2];
|
|
||||||
if (val & 0x800000) val |= 0xFF000000;
|
if (val & 0x800000) val |= 0xFF000000;
|
||||||
return -val;
|
return -val;
|
||||||
}
|
}
|
||||||
@@ -179,16 +255,18 @@ int32_t ads1256_read_data(void) {
|
|||||||
*/
|
*/
|
||||||
int ads1256_init(void) {
|
int ads1256_init(void) {
|
||||||
/* GPIO */
|
/* GPIO */
|
||||||
/* CS 加内部上拉:EMI 干扰时维持高电平,阻止 ADS1256 误收命令 */
|
/* PDWN 低有效:配为 INACTIVE(物理高电平) 保持芯片正常运行 */
|
||||||
gpio_pin_configure_dt(&cs_spec, GPIO_OUTPUT_INACTIVE | GPIO_PULL_UP);
|
gpio_pin_configure_dt(&pdwn_spec, GPIO_OUTPUT_INACTIVE);
|
||||||
gpio_pin_configure_dt(&reset_spec, GPIO_OUTPUT_INACTIVE);
|
gpio_pin_configure_dt(&reset_spec, GPIO_OUTPUT_INACTIVE);
|
||||||
gpio_pin_configure_dt(&drdy_spec, GPIO_INPUT);
|
gpio_pin_configure_dt(&drdy_spec, GPIO_INPUT);
|
||||||
|
|
||||||
/* SPI */
|
/* SPI — CS 由 SPIM 驱动自动管理 */
|
||||||
spi_dev = DEVICE_DT_GET(DT_NODELABEL(spi1));
|
spi_dev = DEVICE_DT_GET(DT_NODELABEL(spi1));
|
||||||
spi_cfg.operation = SPI_OP;
|
spi_cfg.operation = SPI_OP;
|
||||||
spi_cfg.frequency = 500000;
|
spi_cfg.frequency = 500000;
|
||||||
spi_cfg.slave = 0;
|
spi_cfg.slave = 0;
|
||||||
|
spi_cfg.cs.gpio = cs_spec;
|
||||||
|
spi_cfg.cs.delay = 0;
|
||||||
|
|
||||||
if (!device_is_ready(spi_dev)) {
|
if (!device_is_ready(spi_dev)) {
|
||||||
LOG_ERR("SPI device not ready");
|
LOG_ERR("SPI device not ready");
|
||||||
@@ -259,6 +337,9 @@ int ads1256_init(void) {
|
|||||||
* @retval -EIO 达到最大重试次数仍未恢复。
|
* @retval -EIO 达到最大重试次数仍未恢复。
|
||||||
*/
|
*/
|
||||||
int ads1256_recover(int max_retries) {
|
int ads1256_recover(int max_retries) {
|
||||||
|
struct ads1256_reg_snapshot before_snapshot;
|
||||||
|
ads1256_read_snapshot(&before_snapshot);
|
||||||
|
|
||||||
for (int i = 0; i < max_retries; i++) {
|
for (int i = 0; i < max_retries; i++) {
|
||||||
ads1256_write_reg(REG_STATUS, 0x06);
|
ads1256_write_reg(REG_STATUS, 0x06);
|
||||||
ads1256_write_reg(REG_ADCON, 0x07);
|
ads1256_write_reg(REG_ADCON, 0x07);
|
||||||
@@ -269,10 +350,17 @@ int ads1256_recover(int max_retries) {
|
|||||||
uint8_t adcon = ads1256_read_reg(REG_ADCON);
|
uint8_t adcon = ads1256_read_reg(REG_ADCON);
|
||||||
uint8_t drate = ads1256_read_reg(REG_DRATE);
|
uint8_t drate = ads1256_read_reg(REG_DRATE);
|
||||||
if (adcon == 0x07 && drate == 0xC0) {
|
if (adcon == 0x07 && drate == 0xC0) {
|
||||||
|
struct ads1256_reg_snapshot after_snapshot;
|
||||||
|
ads1256_read_snapshot(&after_snapshot);
|
||||||
|
ads1256_log_snapshot_delta("ADS1256 recover reg change", &before_snapshot, &after_snapshot);
|
||||||
LOG_WRN("ADS1256 recovered after %d retries", i + 1);
|
LOG_WRN("ADS1256 recovered after %d retries", i + 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
struct ads1256_reg_snapshot failed_snapshot;
|
||||||
|
ads1256_read_snapshot(&failed_snapshot);
|
||||||
|
ads1256_log_snapshot_delta(
|
||||||
|
"ADS1256 recover reg change after retries exhausted", &before_snapshot, &failed_snapshot);
|
||||||
LOG_ERR("ADS1256 recovery failed after %d retries", max_retries);
|
LOG_ERR("ADS1256 recovery failed after %d retries", max_retries);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,9 +13,11 @@ static const struct gpio_dt_spec led1 = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios);
|
|||||||
|
|
||||||
static struct gpio_callback btn_cb_data;
|
static struct gpio_callback btn_cb_data;
|
||||||
static struct k_work_delayable led_off_work;
|
static struct k_work_delayable led_off_work;
|
||||||
|
static struct k_work_delayable emi_off_work;
|
||||||
|
|
||||||
#define LED_FLASH_MS 200
|
#define LED_FLASH_MS 200
|
||||||
#define LED_BLINK_COUNT 3
|
#define LED_BLINK_COUNT 3
|
||||||
|
#define EMI_LED_HOLD_MS 3000
|
||||||
|
|
||||||
static struct k_work tare_work;
|
static struct k_work tare_work;
|
||||||
static volatile int blink_remaining;
|
static volatile int blink_remaining;
|
||||||
@@ -38,6 +40,21 @@ static void led_off_handler(struct k_work *work) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief EMI 指示熄灯 work:3 秒延时到期后熄灭 LED1。
|
||||||
|
*
|
||||||
|
* 与 led_off_work 分开是因为按键闪烁序列依赖 blink_remaining 的奇偶节拍,
|
||||||
|
* EMI 指示是单次长亮,混用会让 blink_remaining 状态机错乱。
|
||||||
|
*
|
||||||
|
* @param work Zephyr delayable work 入口参数,当前实现未直接使用。
|
||||||
|
*
|
||||||
|
* @return 无返回值。
|
||||||
|
*/
|
||||||
|
static void emi_off_handler(struct k_work *work) {
|
||||||
|
ARG_UNUSED(work);
|
||||||
|
gpio_pin_set_dt(&led1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 在工作队列上下文执行去皮,并启动 LED 闪烁反馈。
|
* @brief 在工作队列上下文执行去皮,并启动 LED 闪烁反馈。
|
||||||
*
|
*
|
||||||
@@ -102,7 +119,14 @@ int button_init(void) {
|
|||||||
|
|
||||||
k_work_init(&tare_work, tare_work_handler);
|
k_work_init(&tare_work, tare_work_handler);
|
||||||
k_work_init_delayable(&led_off_work, led_off_handler);
|
k_work_init_delayable(&led_off_work, led_off_handler);
|
||||||
|
k_work_init_delayable(&emi_off_work, emi_off_handler);
|
||||||
|
|
||||||
LOG_INF("Button1 → tare + LED1 flash initialized");
|
LOG_INF("Button1 → tare + LED1 flash initialized");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void button_led_indicate_emi(void) {
|
||||||
|
/* 直接拉高 LED 并延后 3 秒熄灭;重复触发会刷新熄灭时刻,从而支持连续 EMI 事件累计指示 */
|
||||||
|
gpio_pin_set_dt(&led1, 1);
|
||||||
|
k_work_reschedule(&emi_off_work, K_MSEC(EMI_LED_HOLD_MS));
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "sensor.h"
|
#include "sensor.h"
|
||||||
#include "ads1256.h"
|
#include "ads1256.h"
|
||||||
#include "ble_transport.h"
|
#include "ble_transport.h"
|
||||||
|
#include "button.h"
|
||||||
#include "calibration.h"
|
#include "calibration.h"
|
||||||
#include "comm_protocol.h"
|
#include "comm_protocol.h"
|
||||||
|
|
||||||
@@ -237,6 +238,8 @@ static void sensor_thread_fn(void *p1, void *p2, void *p3) {
|
|||||||
if (acq < 10) {
|
if (acq < 10) {
|
||||||
LOG_ERR("EMI detected (acq=%lld ms)", (long long)acq);
|
LOG_ERR("EMI detected (acq=%lld ms)", (long long)acq);
|
||||||
ads1256_recover(10);
|
ads1256_recover(10);
|
||||||
|
/* 点亮 LED1 作为 EMI 恢复指示,3 秒后由 button 模块自动熄灭 */
|
||||||
|
button_led_indicate_emi();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user