SPI相关基础知识
SPI基本概念请自行百度,参考:百度百科SPI简介.我们讲重点和要注意的地方。
master模式下要关注的地方
接线一一对应
也就是说主控的MISO,MOSI,SCLK,[CSn]分别和设备的MISO,MOSI,SCLK,[CSn]一一对应相连,不交叉,不交叉,不交叉...(重要的事情说三遍)。
从设备的时序图
这是无线模块CC2500的SPI接口时序,这里可以看到,从设备要求,1、时钟空闲时为低电平;2、数据在时钟下降沿跳变,上升沿稳定,第1个沿为数据采样点;3、高位先发送;4、数据长度8位;
这是AD7192的SPI接口时序,这里可以看到从设备要求,1、时钟空闲时为高电平;2、数据在时钟下降沿跳变,上升沿稳定,第2个沿为数据采样点;3、高位先发送;4、数据长度8位;
我们的master模式要根据从设备的时序要求来设置参数,才能正常访问设备。
初始化参数
STM32CubeMX是一个比较好用的可视化工具,具体使用方法参考官方文档,这里看重点:
这是连接上面那个AD7192芯片的配置,生成代码后,我们看它的设置:
c
/* SPI2 init function */
void MX_SPI2_Init(void)
{
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER; //MASTER模式
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT; //一个数据8位
hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH; //时钟空闲为高电平
hspi2.Init.CLKPhase = SPI_PHASE_2EDGE; //第二个跳变采样数据
hspi2.Init.NSS = SPI_NSS_SOFT; //软件设置CS
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB; //高位在前
hspi2.Init.TIMode = SPI_TIMODE_DISABLE; //禁用TI模式
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; //禁用CRC校验
hspi2.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
}
//引脚配置,自动生成,一般不用修改
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(spiHandle->Instance==SPI2)
{
/* SPI2 clock enable */
__HAL_RCC_SPI2_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI2 GPIO Configuration
PB13 ------> SPI2_SCK
PB14 ------> SPI2_MISO
PB15 ------> SPI2_MOSI
*/
GPIO_InitStruct.Pin = ADC_SCLK_Pin|ADC_MOSI_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = ADC_MISO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(ADC_MISO_GPIO_Port, &GPIO_InitStruct);
}
}
查询、中断还是DMA?
总的来说一句话就是,根据需要来决定,因为我们是接的低速AD芯片,所以直接用查询方式就够了,函数定义:
c
//SPI2,master模式,读写一个字节操作
//TxData:要写入的字节
//返回值:读取到的字节
uint8_t SPI2_ReadWriteByte(uint8_t TxData)
{
uint8_t Rxdata;
HAL_SPI_TransmitReceive(&hspi2,&TxData,&Rxdata,1, 1000);
return Rxdata; //返回收到的数据
}