Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么带ESP-IDF的SPI与ESP-IDF Arduino端口(AS5048A)的工作原理不同?_Spi_Esp32_Esp Idf - Fatal编程技术网

为什么带ESP-IDF的SPI与ESP-IDF Arduino端口(AS5048A)的工作原理不同?

为什么带ESP-IDF的SPI与ESP-IDF Arduino端口(AS5048A)的工作原理不同?,spi,esp32,esp-idf,Spi,Esp32,Esp Idf,我已经将AS5048A磁编码器连接到ESP32开发板(VSPI/SPI3总线:CS=5,CLK=18,MISO=19,MOSI=23)。使用ESP IDF版本4.0.1。 Arduino图书馆: 我测试了两个版本的SPI传输:a)带和b)不带Arduino ESP-IDF库 Arduino版本通常在不同的速度下运行良好。纯IDF在正确接收数据方面做了很多努力。 奇怪的是,纯IDF版本设法在SPI模式3(Arduino使用模式1)下发送0x0000和0xFFFF(带奇偶校验和r/w的读取角度命令

我已经将AS5048A磁编码器连接到ESP32开发板(VSPI/SPI3总线:CS=5,CLK=18,MISO=19,MOSI=23)。使用ESP IDF版本4.0.1。 Arduino图书馆:

我测试了两个版本的SPI传输:a)带b)不带Arduino ESP-IDF库

Arduino版本通常在不同的速度下运行良好。纯IDF在正确接收数据方面做了很多努力。 奇怪的是,纯IDF版本设法在SPI模式3(Arduino使用模式1)下发送0x0000和0xFFFF(带奇偶校验和r/w的读取角度命令),但其他命令失败。另外,0x0000(null命令)返回一些垃圾(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);
纯以色列国防军如下:

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是带奇偶校验和r/w位的uint16_t):


我刚刚调出组件上的数据表,并注意到它声明SPI WireMode为1

还有一个表格提到了我在这里包括的一些其他项目。CSn下降沿和CLK上升沿之间的
时间指定为350ns,最小串行时钟周期为100ns,因此如果以10MHz运行,则最多需要等待4个时钟。我不认为这是一个问题,在你的速度运行,但想指出这一点

您对Arduino的配置显示为3MHz,传输前CS线路由软件驱动,这可能会处理您的设置时间,您的ESP-IDF代码会让您运行模式3,但为300KHz,这将使您远远超过所需的350ns设置时间(文档显示CS驱动后的1个spi时钟延迟,稍后将详细介绍). 模式3上的时钟与模式1相反,这意味着SPI将在数据线转换的同时尝试读取数据。我的猜测是,您正陷入一场逻辑竞赛,并且在某些情况下它正在“工作”,因为
input\u delay\n
参数可能会产生足够的延迟,使数据状态在采样之前发生变化

使用错误的SPI计时模式可能会让你发疯,因为事情几乎都能正常工作,有时你会得到正确的结果(此外,对于设备或总线布局来说,以过高的速度运行也会给你带来同样的痛苦)。为了快速地重新灰化,模式是时钟极性和相位的矩阵。模式1和模式3具有相反的极性,在上升沿或下降沿采样,当您使用错误的计时时,您可以在时钟改变状态的同时设置该值


我推荐您使用ESP-IDF,远离嵌入式世界的“Visual Basic”Arduino。如果要尝试接近设备的10MHz最大速度,还需要使用SPI ctrl2寄存器(0x14)。根据文档,位0-3(默认值为1)指定正在驱动的CS线与数据传输开始之间的延迟。

您可能希望在此处发布此问题:。
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);