我已将 AS5048A 磁编码器连接到 ESP32 开发板(VSPI/SPI3 总线:CS=5,CLK=18,MISO=19,MOSI=23)。使用 ESP IDF 4.0.1 版。Arduino 库: https ://github.com/espressif/arduino-esp32/tree/idf-release/v4.0
我测试了两个版本的 SPI 传输:a)有和b)没有Arduino ESP-IDF 库
Arduino 版本通常在不同的速度下都能很好地工作。纯 IDF 很难正确接收数据。奇怪的是,纯 IDF 版本设法在 SPI 模式 3(Arduino 与模式 1 下工作)下发送 0x0000 和 0xFFFF(具有奇偶校验和 r/w 的读取角度命令),但其他命令失败。0x0000(空命令)也会返回一些垃圾(0x6000 或类似的东西,而不是 0x00000)。所以纯 IDF 版本可以使用 SPI 模式 3 正确读取角度(?!),但其他任何操作都失败(我想这是一些意外,因为读取角度命令是 0xFFFF)。
我尝试了每种模式和很多计时配置。试图查看 Arduino 库 SPI 内部,它使用与 IDF 本身不同的 SPI 方法。
任何帮助/想法?下面是代码。
Arduino 实现非常简单:
this->settings = SPISettings(3000000, MSBFIRST, SPI_MODE1);
pinMode(this->_cs, OUTPUT);
SPI.begin();
SPI.beginTransaction(this->settings);
digitalWrite(this->_cs, LOW);
uint16_t response = SPI.transfer16(command);
digitalWrite(this->_cs, HIGH);
纯 IDF 如下:
spi_host_device_t spi_host = SPI3_HOST;
spi_device_handle_t spi;
esp_err_t ret;
spi_bus_config_t buscfg;
memset(&buscfg, 0, sizeof(buscfg));
buscfg.mosi_io_num = pinMOSI;
buscfg.miso_io_num = pinMISO;
buscfg.sclk_io_num = pinCLK;
buscfg.quadwp_io_num = -1;
buscfg.quadhd_io_num = -1;
buscfg.max_transfer_sz = 1;
buscfg.flags = SPICOMMON_BUSFLAG_MASTER ; /*| SPICOMMON_BUSFLAG_IOMUX_PINS ;*/
buscfg.intr_flags = 0;
spi_device_interface_config_t devcfg;
memset(&devcfg, 0, sizeof(devcfg));
devcfg.command_bits = 0;
devcfg.address_bits = 0;
devcfg.dummy_bits = 0;
devcfg.mode = (uint8_t) 1; //SPI_MODE;
devcfg.duty_cycle_pos = 0;
devcfg.cs_ena_pretrans = 0;
devcfg.cs_ena_posttrans = (uint8_t) 0; //CS_ENA_POSTTRANS;
devcfg.clock_speed_hz = 300 * 1000; //SPI_HZ;
devcfg.input_delay_ns = 50; // INPUT_DELAY_NS;
devcfg.spics_io_num = pinCS;
devcfg.flags = SPI_DEVICE_NO_DUMMY ;
devcfg.queue_size = 1;
devcfg.pre_cb = 0;
devcfg.post_cb = 0;
ret = spi_bus_initialize(spi_host, &buscfg, 0); // No DMA
ESP_ERROR_CHECK(ret);
ret = spi_bus_add_device(spi_host, &devcfg, &spi);
ESP_ERROR_CHECK(ret);
ESP_LOGI(TAG, "AS5048 device initialized on SPI with MISO=%d, MOSI=%d, CLK=%d, CS=%d, HZ=%d", pinMISO, pinMOSI, pinCLK, pinCS, SPI_HZ);
并传输(cmd 是 uint16_t,带有奇偶校验和 r/w 位):
esp_err_t ret;
spi_transaction_t t;
spi_device_acquire_bus(spi, portMAX_DELAY);
memset(&t, 0, sizeof(t));
t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA ;
*((uint16_t*)t.tx_data) = SPI_SWAP_DATA_TX(cmd, 16);
t.length = 16;
//ret = spi_device_transmit(spi, &t);
ret = spi_device_polling_transmit(spi, &t);
if(ret != ESP_OK)
ESP_LOGE(TAG, "spi_device_transmit() failed");
spi_device_release_bus(spi);
uint16_t response = SPI_SWAP_DATA_RX(*((uint16_t*)t.rx_data), 16);