RISC-V技术论坛
直播中

golabs

8年用户 903经验值
擅长:可编程逻辑 电源/新能源 MEMS/传感技术 测量仪表
私信 关注

使用stm32mp157进行软件模式spi通讯,为什么无法设置为四线模式?

目前使用STM32mp157芯片进行软件模式的spi通讯,设备树内对使用的gpio口定义如下:
        gpio_spi1: spi@1 {
                    compatible = "spi-gpio";
                    #address-cells = <1>;
                    #size-cells = <0>;
                    status = "okay";

                    sck-gpios   = <&gpiod 8 0>;
                    mosi-gpios  = <&gpioh 15 0>;
                    miso-gpios  = <&gpioi 4 0>;
                    cs-gpios    = <&gpioi 0 0>, <&gpioe 6 0>;// drv:i0 dac:e6

                    num-chipselects = <2>;
                    /* Clients */
                    spidev@0 {
                        reg = <0>;
                        compatible = "linux,spidev";
                        spi-max-frequency = <200000>;
                    };

                    spidev@1 {
                        reg = <1>;
                        compatible = "linux,spidev";
                        spi-max-frequency = <200000>;
                    };
        };

在使用read或 ioctl函数,通过miso线进行读取时,发现读取到的都是mosi线的数据,也就是运行在三线模式。尝试使用ioctl(fd, SPI_IOC_WR_MODE, &mode)关闭三线模式,但没有产生效果。程序中spi读取的相关代码如下:

int myspi2_write_then_read(int fd, const uint8_t* tx_buf, size_t len_tx, uint8_t* rx_buf, size_t len_rx) {
    struct spi_ioc_transfer transfer[2];  // 两个传输结构,一个用于写入,一个用于读取
    memset(transfer, 0, sizeof(transfer));  // 清空结构体
    // 第一个传输,用于写入
    transfer[0].tx_buf = (unsigned long)tx_buf;  // 发送缓冲区
    transfer[0].rx_buf = 0;                      // 不接收数据
    transfer[0].len = len_tx;                    // 写入数据长度
    transfer[0].speed_hz = 0;                    // 使用当前 SPI 设备的默认速度
    transfer[0].cs_change = 0;                   // 在结束时不改变片选状态
    // 第二个传输,用于读取
    transfer[1].tx_buf = 0;                      // 不发送数据
    transfer[1].rx_buf = (unsigned long)rx_buf;  // 接收缓冲区
    transfer[1].len = len_rx;                    // 读取数据长度
    transfer[1].speed_hz = 0;                    // 使用当前 SPI 设备的默认速度
    transfer[1].cs_change = 0;                   // 完成读写后释放片选
    // 使用 ioctl 进行双向传输(写入+读取)
    int ret = ioctl(fd, SPI_IOC_MESSAGE(2), transfer);
    printf("Wrote %zu bytes and read %zu bytes from SPI\n", len_tx, len_rx);
    return 0;
}


int spi_read(int fd, int read_length) {
    uint8_t buf[read_length];
    ssize_t ret = read(fd, buf, sizeof(buf));
    printf("Read from SPI: ");
    for (int i = 0; i < ret; i++) {
        printf("0x%02X ", buf[i]);
    }
    printf("\n");
    return 0;
}

希望各位大神帮忙看看问题出在哪里。

回帖(1)

茶壶茶茶

2024-9-29 16:42:26
在STM32MP157芯片上进行软件模式SPI通讯时,无法设置为四线模式的原因可能有以下几点:

1. GPIO配置问题:确保GPIO引脚已正确配置为SPI模式。在设备树中,需要为SPI的四个引脚(MISO、MOSI、SCK、CS)设置正确的属性。例如:

```
gpio_spi1: spi@1 {
    compatible = "spi-gpio";
    #address-cells = <1>;
    #size-cells = <0>;
    spi-max-frequency = <1000000>;

    spi1_mosi {
        gpios = <&gpioa 7 GPIO_ACTIVE_HIGH>;
        function = "spi";
    };

    spi1_miso {
        gpios = <&gpioa 6 GPIO_ACTIVE_HIGH>;
        function = "spi";
    };

    spi1_sck {
        gpios = <&gpioa 5 GPIO_ACTIVE_HIGH>;
        function = "spi";
    };

    spi1_cs {
        gpios = <&gpioa 4 GPIO_ACTIVE_HIGH>;
        function = "spi";
    };
};
```

2. 软件SPI实现问题:确保软件SPI实现正确处理四线模式。在编写软件SPI代码时,需要正确处理MISO、MOSI、SCK和CS引脚的读写操作。可以参考以下示例代码:

```c
#include "stm32mp1xx_hal.h"

#define SPI1_SCK_PIN GPIO_PIN_5
#define SPI1_SCK_GPIO_PORT GPIOA
#define SPI1_MISO_PIN GPIO_PIN_6
#define SPI1_MISO_GPIO_PORT GPIOA
#define SPI1_MOSI_PIN GPIO_PIN_7
#define SPI1_MOSI_GPIO_PORT GPIOA
#define SPI1_CS_PIN GPIO_PIN_4
#define SPI1_CS_GPIO_PORT GPIOA

void SPI1_Init(void) {
    // 初始化GPIO引脚
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitStruct.Pin = SPI1_SCK_PIN | SPI1_MISO_PIN | SPI1_MOSI_PIN | SPI1_CS_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    // 设置CS引脚为高电平
    HAL_GPIO_WritePin(SPI1_CS_GPIO_PORT, SPI1_CS_PIN, GPIO_PIN_SET);
}

void SPI1_Transmit(uint8_t data) {
    // 设置CS引脚为低电平
    HAL_GPIO_WritePin(SPI1_CS_GPIO_PORT, SPI1_CS_PIN, GPIO_PIN_RESET);

    // 发送数据
    for (int i = 0; i < 8; i++) {
        if (data & 0x80) {
            HAL_GPIO_WritePin(SPI1_MOSI_GPIO_PORT, SPI1_MOSI_PIN, GPIO_PIN_SET);
        } else {
            HAL_GPIO_WritePin(SPI1_MOSI_GPIO_PORT, SPI1_MOSI_PIN, GPIO_PIN_RESET);
        }
        data <<= 1;
        HAL_GPIO_WritePin(SPI1_SCK_GPIO_PORT, SPI1_SCK_PIN, GPIO_PIN_SET);
        HAL_Delay(1);
        HAL_GPIO_WritePin(SPI1_SCK_GPIO_PORT, SPI1_SCK_PIN, GPIO_PIN_RESET);
    }

    // 设置CS引脚为高电平
    HAL_GPIO_WritePin(SPI1_CS_GPIO_PORT, SPI1_CS_PIN, GPIO_PIN_SET);
}

uint8_t SPI1_Receive(void) {
    uint8_t data = 0;

    // 设置CS引脚为低电平
    HAL_GPIO_WritePin(SPI1_CS_GPIO_PORT, SPI1_CS_PIN, GPIO_PIN_RESET);

    // 接收数据
    for (int i = 0; i < 8; i++) {
        HAL_GPIO_WritePin(SPI1_SCK_GPIO_PORT, SPI1_SCK_PIN, GPIO_PIN_SET);
        HAL_Delay(1);
        if (HAL_GPIO_ReadPin(SPI1_MISO_GPIO_PORT, SPI1_MISO_PIN) == GPIO_PIN_SET) {
            data |= (1 << (7 - i));
        }
        HAL_GPIO_WritePin(SPI1_SCK_GPIO_PORT, SPI1_SCK_PIN, GPIO_PIN_RESET);
    }

    // 设置CS引脚为高电平
    HAL_GPIO_WritePin(SPI1_CS_GPIO_PORT, SPI1_CS_PIN, GPIO_PIN_SET);

    return data;
}
```

3. 硬件连接问题:确保硬件连接正确。检查SPI设备的MISO、MOSI、SCK和CS引脚是否已正确连接到STM32MP157芯片的对应引脚。

4. 时序问题:确保软件SPI的时序与SPI设备兼容。如果时序不正确,可能导致通信失败。可以通过调整代码中的延时来优化时序。

综上所述,如果以上几点
举报

更多回帖

发帖
×
20
完善资料,
赚取积分