1、HAL库驱动设置
2、SPI函数HAL_SPI_TransmitReceive引发的大小端格式问题
在CUBE下对SPI进行设置后,系统自动生成SPI初始化以及驱动代码,应用级所需要做的就是进行通讯,轮询方式下使用的函数有:
//数据发送:
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
//数据接收:
HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
//数据发送+接收:
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout)
//Timeout为ms级别
一般,对于发送1Byte+接收1Byte的通讯方式,直接调用HAL_SPI_Transmit 、 HAL_SPI_Receive即可
uint8_t Data=0;
uint8_t Reg=(reg | 0x80);
ADXMAIN_CE_L;
HAL_SPI_Transmit(&hspi3,®,1,0xff);
HAL_SPI_Receive(&hspi3,&data,1,0xff);
ADXMAIN_CE_H;
return Data;
出于好奇,调用HAL_SPI_TransmitReceive(&hspis,&TxData,&RxData,1,1)函数,完整代码如下
uint8_t ADXLREF_Read_1Byte(uint8_t reg)
{
uint8_t Data=0;
uint8_t Reg=(reg | 0x80);
ADXMAIN_CE_L;
HAL_SPI_TransmitReceive(&hspi3,&Reg,&Data,1,0xff);
ADXMAIN_CE_H;
return Data;
}
接收数据非预期,对HAL_SPI_TransmitReceive进行分析,函数中先发送1Byte数据(*Reg+0)发送的同时接收1Byte数据放入(*Data+0),即该函数并不会发送1Byte数据后再给时钟进行接收。于是修改代码如下
uint16_t Data=0;
uint16_t Reg=(reg | 0x80)<<8;
ADXMAIN_CE_L;
HAL_SPI_TransmitReceive(&hspi3,&Reg,&Data,2,0xff);
ADXMAIN_CE_H;
return (uint8_t)Data;
接收数据非预期。同时SPI数据线路波形如下蓝色为时钟,红色为MOSI,
按理应该在第一个Byte发送0x80,但在第二个Byte发送。原因是第一个STM32是小端格式(高位数据在地址低位),Reg=(reg | 0x80)<<8,Reg在内存中存储为(0x00地址:00000000,0x08地址100000000)在代码中顺地址获取Reg数据时,先获取了0x00地址数据,后获取0x08地址数据。需要修改为Reg=reg | 0x80;
uint16_t Data=0;
uint16_t Reg=reg | 0x80;
ADXMAIN_CE_L;
HAL_SPI_TransmitReceive(&hspi3,&Reg,&Data,2,0xff);
ADXMAIN_CE_H;
return (uint8_t)Data;
3、扩展
假如现有一32位int型数0x12345678,那么其MSB(Most Significant Byte,最高有效字节)为0x12,其LSB (Least Significant Byte,最低有效字节)为0x78,在CPU内存中有两种存放方式:(假设从地址0x4000开始存放)
https://blog.csdn.net/wwwlyj123321/article/details/100066463
上面问题还有一种更常规的解决思路:使用uint_8数组格式存储数据
uint8_t Data[2]={0};
uint8_t Reg[2]={reg | 0x80,0};