You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP-IDF中SPI读函数正常但写函数失效问题求助

TCAN4550 SPI写寄存器函数异常排查

我需要实现两个SPI寄存器读写函数spiRegisterRead(uint16_t reg_addr)和spiRegisterWrite(uint16_t reg_addr, uint32_t reg_value),用于操作32位寄存器。目前读函数工作正常,但写函数无法完成写入操作。我已尝试多种修改方案,包括改用TXDATA替代TXBUFFERS等,但问题未解决。

正常工作的spiRegisterRead()代码

uint32_t spiRegisterRead(uint16_t reg_addr) {

    uint8_t rx_buffer[5];

    spi_transaction_t t;
    
    memset(&t, 0, sizeof(spi_transaction_t)); 

    t.cmd = SPI_READ_OPCODE;
    t.addr = reg_addr;
    t.length = 5 * 8; // length byte
    t.rxlength = 5 * 8;
    t.rx_buffer = rx_buffer;
    t.tx_buffer = NULL;

    // Transmit the dummy bytes to read the actual data
    spi_device_transmit(spi, &t);

    // Combine the received bytes into a 32-bit value
    uint32_t reg_value = ((uint64_t)rx_buffer[1] << 24) |
                ((uint64_t)rx_buffer[2] << 16) | ((uint64_t)rx_buffer[3] << 8) | (rx_buffer[4]);

    return reg_value;
}

无法正常工作的spiRegisterWrite()代码

uint8_t spiRegisterWrite(uint16_t reg_addr, uint32_t reg_value, uint32_t * pointer) {

    uint8_t tx_buffer[4];
    //uint8_t rx_buffer[4];
    
    tx_buffer[0] = (uint8_t)reg_value;
    tx_buffer[1] = (uint8_t)(reg_value >> 8);
    tx_buffer[2] = (uint8_t)(reg_value >> 16);
    tx_buffer[3] = (uint8_t)(reg_value >> 24);

    //memcpy(tx_buffer, &reg_value, sizeof(uint32_t));

    printf("Writing %lX into %X\n", reg_value, reg_addr);

    spi_transaction_t t;
    
    memset(&t, 0, sizeof(t)); 

    t.cmd = SPI_WRITE_OPCODE; // Not sure
    t.addr = reg_addr;
    t.length = 4 * 8; // length byte + 4*bytes data 
    //t.flags = SPI_TRANS_USE_TXDATA;
    //t.rxlength = 4 * 8;
    //t.rx_buffer = NULL;
    t.tx_buffer = tx_buffer;
    //memcpy(t.tx_data, &reg_value, sizeof(uint32_t));

    spi_device_polling_transmit(spi, &t);

    /*if (pointer != NULL)
    {
        memcpy(pointer, rx_buffer, sizeof(uint32_t));
    }*/


    // uint8_t data_to_send = 0x45;
    // spi_transaction_t t;
    // memset(&t, 0, sizeof(t));       //Zero out the transaction
    // t.length=8;                     //Command is 8 bits
    // t.tx_buffer=&data_to_send;      //The data is the cmd itself
    // t.user=(void*)1;                //D/C needs to be set to 1
    // t.addr = 0x0808;
    // t.cmd = SPI_WRITE_OPCODE;
    // spi_device_transmit(spi, &t);

    return 0;
}

注释中包含我已尝试过的修改方案。

SPI初始化代码

void spi_init() {
    esp_err_t ret;
    
    // Configure the SPI bus
    spi_bus_config_t buscfg = {
        .miso_io_num = PIN_NUM_MISO,
        .mosi_io_num = PIN_NUM_MOSI,
        .sclk_io_num = PIN_NUM_CLK,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
        .max_transfer_sz = 4096,
    };

    // Initialize the SPI bus
    ret = spi_bus_initialize(HSPI_HOST, &buscfg, 1);
    assert(ret == ESP_OK);

    // Configure the SPI device
    spi_device_interface_config_t devcfg = {
        .clock_speed_hz = 10 * 1000 * 1000,    // Clock out at 10 MHz
        .mode = 0,                             // SPI mode 0
        
        .spics_io_num = PIN_NUM_CS,            // CS pin
        .queue_size = 7,                     
        .pre_cb = NULL,
        .post_cb = NULL,
        .command_bits = 8,                     // Important! 
        .address_bits = 16                     // Important!
    };

    // Attach the SPI device to the SPI bus
    ret = spi_bus_add_device(HSPI_HOST, &devcfg, &spi);
    assert(ret == ESP_OK);
}

测试代码

我正在开发用于与TCAN4550交互的驱动,测试代码如下:

uint32_t check;
    
    value = spiRegisterRead(0x0808);

    printf("Reg content: %lX\n", value);

    spiRegisterWrite(0x0808, 0x87650000, &check);

    usleep(1000);

    value = spiRegisterRead(0x0808);

    printf("Prev reg value: %lX\n", check);
    printf("New reg content: %lX\n", value);

我写入的寄存器是专门用于读写测试的寄存器。

内容的提问来源于stack exchange,提问作者dabrag

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 22:55:55