fix(ads1256): 修复 SPI 无波形问题,添加 PDWN 引脚控制
PDWN 浮空导致 ADS1256 进入 power-down 模式,DRDY 无响应且 SPI 总线 无输出。同时将 CS 管理从手动 GPIO 改为 SPIM 驱动自动控制,消除引脚 所有权冲突;读寄存器和读数据改用 spi_transceive 保证单次 CS 内完成。
This commit is contained in:
+4
-4
@@ -46,21 +46,21 @@
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
ads-cs = &ads_cs_pin;
|
||||
ads-drdy = &ads_drdy_pin;
|
||||
ads-reset = &ads_reset_pin;
|
||||
ads-pdwn = &ads_pdwn_pin;
|
||||
};
|
||||
|
||||
ads1256_control {
|
||||
compatible = "gpio-keys";
|
||||
ads_cs_pin: ads_cs {
|
||||
gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
ads_drdy_pin: ads_drdy {
|
||||
gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
ads_reset_pin: ads_reset {
|
||||
gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
ads_pdwn_pin: ads_pdwn {
|
||||
gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
+35
-43
@@ -35,9 +35,10 @@ LOG_MODULE_REGISTER(ads1256, LOG_LEVEL_INF);
|
||||
/* --- 硬件资源 --- */
|
||||
static struct spi_config spi_cfg;
|
||||
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 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;
|
||||
@@ -82,12 +83,10 @@ int ads1256_wait_drdy(uint16_t timeout_ms) {
|
||||
*/
|
||||
void ads1256_write_reg(uint8_t reg, uint8_t val) {
|
||||
ads1256_wait_drdy(50);
|
||||
gpio_pin_set_dt(&cs_spec, 1);
|
||||
uint8_t tx_buf[3] = { CMD_WREG | reg, 0x00, val };
|
||||
struct spi_buf tx = { .buf = tx_buf, .len = 3 };
|
||||
struct spi_buf_set tx_set = { .buffers = &tx, .count = 1 };
|
||||
spi_write(spi_dev, &spi_cfg, &tx_set);
|
||||
gpio_pin_set_dt(&cs_spec, 0);
|
||||
/* t11: WREG 后至少 4 × tCLKIN ≈ 0.5µs */
|
||||
k_busy_wait(2);
|
||||
}
|
||||
@@ -95,25 +94,25 @@ void ads1256_write_reg(uint8_t reg, uint8_t val) {
|
||||
/**
|
||||
* @brief 从 ADS1256 读单个寄存器。
|
||||
*
|
||||
* ADS1256 RREG 时序要求:命令+数据在同一次 CS 拉低内完成,
|
||||
* 中间需 t6 延时。这里用单次 transceive 保证 CS 不释放。
|
||||
*
|
||||
* @param reg 目标寄存器地址。
|
||||
*
|
||||
* @return 读取到的寄存器值。
|
||||
*/
|
||||
uint8_t ads1256_read_reg(uint8_t reg) {
|
||||
ads1256_wait_drdy(50);
|
||||
gpio_pin_set_dt(&cs_spec, 1);
|
||||
uint8_t tx_buf[2] = { CMD_RREG | reg, 0x00 };
|
||||
struct spi_buf tx = { .buf = tx_buf, .len = 2 };
|
||||
/* tx: [RREG|reg, 0x00, dummy_for_t6, dummy_read]
|
||||
* rx: [x, x, x, data] — 前 3 字节是命令+延时期间的垃圾 */
|
||||
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 };
|
||||
spi_write(spi_dev, &spi_cfg, &tx_set);
|
||||
/* 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 rx = { .buf = rx_buf, .len = 4 };
|
||||
struct spi_buf_set rx_set = { .buffers = &rx, .count = 1 };
|
||||
spi_read(spi_dev, &spi_cfg, &rx_set);
|
||||
gpio_pin_set_dt(&cs_spec, 0);
|
||||
return rx_val;
|
||||
spi_transceive(spi_dev, &spi_cfg, &tx_set, &rx_set);
|
||||
return rx_buf[3];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,31 +187,23 @@ static void ads1256_log_snapshot_delta(
|
||||
*/
|
||||
void ads1256_write_cmd(uint8_t cmd) {
|
||||
ads1256_wait_drdy(50);
|
||||
gpio_pin_set_dt(&cs_spec, 1);
|
||||
struct spi_buf tx = { .buf = &cmd, .len = 1 };
|
||||
struct spi_buf_set tx_set = { .buffers = &tx, .count = 1 };
|
||||
spi_write(spi_dev, &spi_cfg, &tx_set);
|
||||
gpio_pin_set_dt(&cs_spec, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 发送 SYNC + WAKEUP 命令,触发一次同步采样。
|
||||
*
|
||||
* @return 无返回值。
|
||||
* SYNC 和 WAKEUP 必须在同一次 CS 内完成,用单次 transceive 保持 CS。
|
||||
* 中间插入 dummy 字节满足 t11 延时 (24 × tCLKIN ≈ 3.1µs)。
|
||||
*/
|
||||
void ads1256_sync_wakeup(void) {
|
||||
uint8_t cmd_sync = CMD_SYNC;
|
||||
uint8_t cmd_wakeup = CMD_WAKEUP;
|
||||
struct spi_buf tx_s = { .buf = &cmd_sync, .len = 1 };
|
||||
struct spi_buf tx_w = { .buf = &cmd_wakeup, .len = 1 };
|
||||
struct spi_buf_set set_s = { .buffers = &tx_s, .count = 1 };
|
||||
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);
|
||||
/* [SYNC, dummy(延时), WAKEUP] — 500kHz 下每字节 16µs,1 字节 dummy 远超 3.1µs */
|
||||
uint8_t tx_buf[3] = { CMD_SYNC, 0xFF, CMD_WAKEUP };
|
||||
struct spi_buf tx = { .buf = tx_buf, .len = 3 };
|
||||
struct spi_buf_set tx_set = { .buffers = &tx, .count = 1 };
|
||||
spi_write(spi_dev, &spi_cfg, &tx_set);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -235,22 +226,21 @@ int ads1256_hwreset(void) {
|
||||
/**
|
||||
* @brief 读取当前 24 位转换结果,符号扩展为 int32_t。
|
||||
*
|
||||
* RDATA 命令后需 t6 延时再读 3 字节数据,全部在同一次 CS 内完成。
|
||||
*
|
||||
* @return 当前 ADC 转换原始值。
|
||||
*/
|
||||
int32_t ads1256_read_data(void) {
|
||||
uint8_t cmd = CMD_RDATA;
|
||||
uint8_t rx_buf[3] = { 0 };
|
||||
gpio_pin_set_dt(&cs_spec, 1);
|
||||
struct spi_buf tx = { .buf = &cmd, .len = 1 };
|
||||
/* tx: [RDATA, dummy(t6延时), MSB, MID, LSB]
|
||||
* rx: [x, x, MSB, MID, LSB] */
|
||||
uint8_t tx_buf[5] = { CMD_RDATA, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
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 };
|
||||
spi_write(spi_dev, &spi_cfg, &tx_set);
|
||||
/* t6: RDATA 后至少 50 × tCLKIN ≈ 6.5µs */
|
||||
k_busy_wait(10);
|
||||
struct spi_buf rx = { .buf = rx_buf, .len = 3 };
|
||||
struct spi_buf rx = { .buf = rx_buf, .len = 5 };
|
||||
struct spi_buf_set rx_set = { .buffers = &rx, .count = 1 };
|
||||
spi_read(spi_dev, &spi_cfg, &rx_set);
|
||||
gpio_pin_set_dt(&cs_spec, 0);
|
||||
int32_t val = ((int32_t)rx_buf[0] << 16) | ((int32_t)rx_buf[1] << 8) | rx_buf[2];
|
||||
spi_transceive(spi_dev, &spi_cfg, &tx_set, &rx_set);
|
||||
int32_t val = ((int32_t)rx_buf[2] << 16) | ((int32_t)rx_buf[3] << 8) | rx_buf[4];
|
||||
if (val & 0x800000) val |= 0xFF000000;
|
||||
return -val;
|
||||
}
|
||||
@@ -265,16 +255,18 @@ int32_t ads1256_read_data(void) {
|
||||
*/
|
||||
int ads1256_init(void) {
|
||||
/* GPIO */
|
||||
/* CS 加内部上拉:EMI 干扰时维持高电平,阻止 ADS1256 误收命令 */
|
||||
gpio_pin_configure_dt(&cs_spec, GPIO_OUTPUT_INACTIVE | GPIO_PULL_UP);
|
||||
/* PDWN 低有效:配为 INACTIVE(物理高电平) 保持芯片正常运行 */
|
||||
gpio_pin_configure_dt(&pdwn_spec, GPIO_OUTPUT_INACTIVE);
|
||||
gpio_pin_configure_dt(&reset_spec, GPIO_OUTPUT_INACTIVE);
|
||||
gpio_pin_configure_dt(&drdy_spec, GPIO_INPUT);
|
||||
|
||||
/* SPI */
|
||||
/* SPI — CS 由 SPIM 驱动自动管理 */
|
||||
spi_dev = DEVICE_DT_GET(DT_NODELABEL(spi1));
|
||||
spi_cfg.operation = SPI_OP;
|
||||
spi_cfg.frequency = 500000;
|
||||
spi_cfg.slave = 0;
|
||||
spi_cfg.cs.gpio = cs_spec;
|
||||
spi_cfg.cs.delay = 0;
|
||||
|
||||
if (!device_is_ready(spi_dev)) {
|
||||
LOG_ERR("SPI device not ready");
|
||||
|
||||
Reference in New Issue
Block a user