diff --git a/app.overlay b/app.overlay index 8b7a876..5fbb63f 100644 --- a/app.overlay +++ b/app.overlay @@ -15,7 +15,7 @@ pinctrl-0 = <&spi1_default>; pinctrl-1 = <&spi1_sleep>; pinctrl-names = "default", "sleep"; - + /* CS 引脚配置 */ cs-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; @@ -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>; + }; }; }; diff --git a/src/ads1256.c b/src/ads1256.c index c20c639..36f86df 100644 --- a/src/ads1256.c +++ b/src/ads1256.c @@ -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");