赞
踩
虽然在平常的使用中,spi使用轮询等待发送完成或者接收完成就行了。
但是在对时间有严格要求的设计中,假设我们需要发送完成后立马做xx事情,此时如果有低优先级的信号需要处理,我们的轮询方式就得不到及时的响应;
或者说比如需要定时从spi设备中采集数据,定时器中断来了我们就要马上调用接收函数,接收完成马上进行其他计算,同样此时应该保证数据的优先级。
此时就需要用到发送完成和接收中断了。
前面我们已经实现了SPI轮询的发送和接收,在前面的基础上进行修改。
新增发送和接收的回调函数,并在初始化的时候配置,使能SPI接收中断:
SPI_HandleTypeDef SPI3_Handler; //SPI2句柄 void rx_isr(SPI_HandleTypeDef *hspi) { if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1) { u8 data = SPI3->DR; printf("0x%X ",data); } } void tx_isr(SPI_HandleTypeDef *hspi) { if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1) { } } void SPI3_Init(void) { HAL_NVIC_SetPriority(SPI3_IRQn, 0, 0); HAL_NVIC_EnableIRQ(SPI3_IRQn); SPI3_Handler.Instance = SPI3; SPI3_Handler.Init.Mode = SPI_MODE_MASTER; SPI3_Handler.Init.Direction = SPI_DIRECTION_2LINES; SPI3_Handler.Init.DataSize = SPI_DATASIZE_8BIT; SPI3_Handler.Init.CLKPolarity = SPI_POLARITY_LOW; SPI3_Handler.Init.CLKPhase = SPI_PHASE_1EDGE; SPI3_Handler.Init.NSS = SPI_NSS_SOFT; SPI3_Handler.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128; SPI3_Handler.Init.FirstBit = SPI_FIRSTBIT_MSB; SPI3_Handler.Init.TIMode = SPI_TIMODE_DISABLE; SPI3_Handler.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; SPI3_Handler.Init.CRCPolynomial = 7; SPI3_Handler.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE; SPI3_Handler.Init.NSSPMode = SPI_NSS_PULSE_DISABLE; SPI3_Handler.RxISR = rx_isr; SPI3_Handler.TxISR = tx_isr; HAL_SPI_Init(&SPI3_Handler); //__HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE); __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_RXNE); } void SPI3_IRQHandler(void) { HAL_SPI_IRQHandler(&SPI3_Handler); }
对应的读写操作如下:
u16 W25QXX_ReadID(void)
{
u16 Temp = 0;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
SPI3_ReadWriteByte(0x90);//发送读取ID命令
SPI3_ReadWriteByte(0x00);
SPI3_ReadWriteByte(0x00);
SPI3_ReadWriteByte(0x00);
Temp |= SPI3_ReadWriteByte(0xFF) << 8;
Temp |= SPI3_ReadWriteByte(0xFF);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
return Temp;
}
显示结果如下:
其中前面4个0xFF是因为在写,写完4个byte同样会进入4次中断,但由于我们在接收中断就把数据接受了,所以SPI3_ReadWriteByte
因为超时才退出的,可以明显看到几个数不是同时打印的,至于后面的ID没有显示也是同样的道理。
同样在前面使能发送完成中断就可以了:
__HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
但是由于发送完成了之后,发送缓冲区一直为空,所以会一直进入中断,所以我们使用发送完成中断的话,发送完成后除非再次填值或者关闭中断,否则会一直不停进入中断。
而实际上HAL库是提供了一个HAL_SPI_TransmitReceive_IT
用于中断使用的发送接收函数,其中很重要的一部分内容:
hspi->ErrorCode = HAL_SPI_ERROR_NONE; hspi->pTxBuffPtr = pTxData; hspi->TxXferSize = Size; hspi->TxXferCount = Size; hspi->pRxBuffPtr = pRxData; hspi->RxXferSize = Size; hspi->RxXferCount = Size; /* Set the function for IT treatment */ if(hspi->Init.DataSize > SPI_DATASIZE_8BIT ) { hspi->RxISR = SPI_2linesRxISR_16BIT; hspi->TxISR = SPI_2linesTxISR_16BIT; } else { hspi->RxISR = SPI_2linesRxISR_8BIT; hspi->TxISR = SPI_2linesTxISR_8BIT; } __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
重新配置了中断函数,配置了发送和接收缓冲区为传入的数组,所以这里的数组要设置为全局变量,而前面设置的中断函数也失效了,而且使能了中断,所以我们前面所作的工作都是白费了。
至于HAL_SPI_TransmitReceive_IT
的具体过程,先埋个坑……(项目现在没这需求了)
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。