使用spi_transfer从SPI从设备读取字节时接收值无变化问题求助
问题原因及修复方案
代码存在的核心错误
- 错误1:
spi_transfer.tx_buf赋值错误:txbuf本身就是指向发送缓冲区的指针,代码中传入的&txbuf是指针变量自身的地址,而非实际发送数据的缓冲区地址 - 错误2:
spi_sync_transfer参数传递错误:该函数第三个参数是要传输的spi_transfer结构体的数量,而非单条传输的长度,你传入read.len(值为3)会导致内核访问非法地址,传输根本未正确执行,所以rx值没有变化 - 错误3:发送缓冲区长度不足:你设置单条传输长度
len=3(对应2字节发送+1字节接收的全双工时钟),但传入的txbuf只有2字节,传输第三字节时会读取缓冲区外的非法内容
修复后的代码
修改m_read函数即可:
int m_read(uint8_t txbuf[]) { int ret = -1; // 构造3字节发送缓冲区:前2字节是传入的指令,第三字节补0(用于提供接收响应的时钟) uint8_t tx[3] = {txbuf[0], txbuf[1], 0x00}; uint8_t rx = 0x01; struct spi_transfer xfer = { .tx_buf = tx, // 直接传发送缓冲区首地址 .rx_buf = &rx, // 此处rx_buf用法本身是正确的,之前未生效是其他调用错误导致 .len = 3, // 单条传输总长度3字节 .speed_hz = MAX_HZ, }; // 第三个参数传1:只有1个spi_transfer结构体 ret = spi_sync_transfer(slave_device, &xfer, 1); if (ret < 0) { printk("SPI transfer failed, ret=%d\n", ret); return ret; } printk("Bytes read: 0x%02x\n", rx); return ret; }
原有调用逻辑和mRead的定义不需要修改。
额外说明
- SPI是全双工通信,每发送1位数据的同时会接收1位数据,你需要接收1字节响应,就需要多提供1字节的发送时钟,所以总传输长度设为3字节是正确的
spi_transfer.rx_buf只要传入用来存放接收数据的缓冲区首地址即可,类型是void *无需强制转换
内容的提问来源于stack exchange,提问作者user16627306
相关产品推荐
相关产品推荐

