问题
该项目中,使用外置的ADC芯片采集电压电流,主控MCU通过SPI与ADC芯片通信。调试时,SPI通信一直失败,与之前成功的项目对比,发现是SPI配置的问题。
void MX_SPI2_Init(void)
{/* USER CODE BEGIN SPI2_Init 0 *//* USER CODE END SPI2_Init 0 *//* USER CODE BEGIN SPI2_Init 1 *//* USER CODE END SPI2_Init 1 */hspi2.Instance = SPI2;hspi2.Init.Mode = SPI_MODE_MASTER;hspi2.Init.Direction = SPI_DIRECTION_2LINES;hspi2.Init.DataSize = SPI_DATASIZE_8BIT;hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;hspi2.Init.NSS = SPI_NSS_SOFT;hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;hspi2.Init.TIMode = SPI_TIMODE_DISABLE;hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;hspi2.Init.CRCPolynomial = 10;if (HAL_SPI_Init(&hspi2) != HAL_OK){Error_Handler();}/* USER CODE BEGIN SPI2_Init 2 *//* USER CODE END SPI2_Init 2 */}
SPI初始化时,如果配置CRCCalculation 为Enable,通信就会失败;如果配置CRCCalculation 为Disable,通信就成功。
解决
知其然还得知其所以然。
看看具体的配置选项的含义:
void MX_SPI2_Init(void)
{/* USER CODE BEGIN SPI2_Init 0 *//* USER CODE END SPI2_Init 0 *//* USER CODE BEGIN SPI2_Init 1 *//* USER CODE END SPI2_Init 1 */hspi2.Instance = SPI2;hspi2.Init.Mode = SPI_MODE_MASTER; //主机模式,即MCU主导SPI时钟和数据通信hspi2.Init.Direction = SPI_DIRECTION_2LINES; //全双工模式,可以同时发送、接收数据hspi2.Init.DataSize = SPI_DATASIZE_8BIT; //数据帧为8位,每次传输8位数据hspi2.Init.CLKPolarity = SPI_POLARITY_LOW; //时钟极性为低电平,即空闲时,时钟线保持低电平hspi2.Init.CLKPhase = SPI_PHASE_2EDGE; //时钟相位为第二边沿采样,即数据将在时钟信号的第二个边沿采样hspi2.Init.NSS = SPI_NSS_SOFT; //软件控制片选(即在读写数据时,要自己把CS拉低拉高)hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; //波特率分频器设置为156,即SPI的工作频率为时钟频率除以256hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB; //高位在前,即数据从最高位开始传输hspi2.Init.TIMode = SPI_TIMODE_DISABLE; //禁用TI模式,即SPI外设将工作在Motorola SPI模式下,这是绝大多数SPI设备所使用的模式hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; //禁用CRC计算hspi2.Init.CRCPolynomial = 10; //CRC校验的多项式,只有CRCCalculation 被启用时,这个值才有效if (HAL_SPI_Init(&hspi2) != HAL_OK){Error_Handler();}/* USER CODE BEGIN SPI2_Init 2 *//* USER CODE END SPI2_Init 2 */}
CRCCalculation 参数决定了 SPI 是否使用硬件 CRC 校验。
如果启用CRC校验,在通信过程中,SPI硬件会自动计算发送和接受数据的CRC校验值,并在传输的最后两个字节发送CRC值。
那么启用CRC校验时,通信失败的原因,可能是外置的ADC芯片的SPI配置中并没有CRC校验,两者不匹配。
补充
查看了一下ads1220的手册,从图中可以看到:
(1)CPOL = 0:SCLK 的空闲状态是低电平。
CPHA = 1:数据在时钟信号的第一个上升沿之前被捕获,在第二个上升沿时被发送。
(2)当 CS 低电平时,设备被选中并可以接收和发送数据。
(3)需要监控 DRDY 引脚的状态,以判断何时可以读取新的数据。
并没有提到CRC校验,可以看做是没有。