你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32F7使用SPI发送完成和接收中断

[复制链接]
STMCU小助手 发布时间:2021-12-17 12:04
虽然在平常的使用中,spi使用轮询等待发送完成或者接收完成就行了。
但是在对时间有严格要求的设计中,假设我们需要发送完成后立马做xx事情,此时如果有低优先级的信号需要处理,我们的轮询方式就得不到及时的响应;
或者说比如需要定时从spi设备中采集数据,定时器中断来了我们就要马上调用接收函数,接收完成马上进行其他计算,同样此时应该保证数据的优先级。
此时就需要用到发送完成和接收中断了。

前面我们已经实现了SPI轮询的发送和接收,在前面的基础上进行修改。

接缓冲区满中断
新增发送和接收的回调函数,并在初始化的时候配置,使能SPI接收中断:

  1. SPI_HandleTypeDef SPI3_Handler;  //SPI2句柄

  2. void rx_isr(SPI_HandleTypeDef *hspi)
  3. {
  4.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)
  5.     {
  6.         u8 data = SPI3->DR;
  7.                 printf("0x%X  ",data);
  8.     }
  9. }
  10. void tx_isr(SPI_HandleTypeDef *hspi)
  11. {
  12.     if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE) == 1)
  13.     {

  14.     }
  15. }
  16. void SPI3_Init(void)
  17. {
  18.     HAL_NVIC_SetPriority(SPI3_IRQn, 0, 0);
  19.     HAL_NVIC_EnableIRQ(SPI3_IRQn);

  20.     SPI3_Handler.Instance = SPI3;
  21.     SPI3_Handler.Init.Mode = SPI_MODE_MASTER;
  22.     SPI3_Handler.Init.Direction = SPI_DIRECTION_2LINES;
  23.     SPI3_Handler.Init.DataSize = SPI_DATASIZE_8BIT;
  24.     SPI3_Handler.Init.CLKPolarity = SPI_POLARITY_LOW;
  25.     SPI3_Handler.Init.CLKPhase = SPI_PHASE_1EDGE;
  26.     SPI3_Handler.Init.NSS = SPI_NSS_SOFT;
  27.     SPI3_Handler.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
  28.     SPI3_Handler.Init.FirstBit = SPI_FIRSTBIT_MSB;
  29.     SPI3_Handler.Init.TIMode = SPI_TIMODE_DISABLE;
  30.     SPI3_Handler.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  31.     SPI3_Handler.Init.CRCPolynomial = 7;
  32.     SPI3_Handler.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  33.     SPI3_Handler.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;

  34.     SPI3_Handler.RxISR = rx_isr;
  35.     SPI3_Handler.TxISR = tx_isr;
  36.                
  37.     HAL_SPI_Init(&SPI3_Handler);

  38.     //__HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
  39.     __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_RXNE);

  40. }
  41. void SPI3_IRQHandler(void)
  42. {
  43.     HAL_SPI_IRQHandler(&SPI3_Handler);
  44. }
复制代码

对应的读写操作如下:

  1. u16 W25QXX_ReadID(void)
  2. {
  3.     u16 Temp = 0;

  4.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
  5.     SPI3_ReadWriteByte(0x90);//发送读取ID命令
  6.     SPI3_ReadWriteByte(0x00);
  7.     SPI3_ReadWriteByte(0x00);
  8.     SPI3_ReadWriteByte(0x00);
  9.     Temp |= SPI3_ReadWriteByte(0xFF) << 8;
  10.     Temp |= SPI3_ReadWriteByte(0xFF);
  11.     HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
  12.     return Temp;
  13. }
复制代码

显示结果如下:
20200423172457741.png


其中前面4个0xFF是因为在写,写完4个byte同样会进入4次中断,但由于我们在接收中断就把数据接受了,所以SPI3_ReadWriteByte因为超时才退出的,可以明显看到几个数不是同时打印的,至于后面的ID没有显示也是同样的道理。

发送缓冲区空中断
同样在前面使能发送完成中断就可以了:

  1. __HAL_SPI_ENABLE_IT(&SPI3_Handler, SPI_IT_TXE);
复制代码

但是由于发送完成了之后,发送缓冲区一直为空,所以会一直进入中断,所以我们使用发送完成中断的话,发送完成后除非再次填值或者关闭中断,否则会一直不停进入中断。

而实际上HAL库是提供了一个HAL_SPI_TransmitReceive_IT用于中断使用的发送接收函数,其中很重要的一部分内容:

  1.   hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
  2.   hspi->pTxBuffPtr  = pTxData;
  3.   hspi->TxXferSize  = Size;
  4.   hspi->TxXferCount = Size;
  5.   hspi->pRxBuffPtr  = pRxData;
  6.   hspi->RxXferSize  = Size;
  7.   hspi->RxXferCount = Size;

  8.   /* Set the function for IT treatment */
  9.   if(hspi->Init.DataSize > SPI_DATASIZE_8BIT )
  10.   {
  11.     hspi->RxISR = SPI_2linesRxISR_16BIT;
  12.     hspi->TxISR = SPI_2linesTxISR_16BIT;
  13.   }
  14.   else
  15.   {
  16.     hspi->RxISR = SPI_2linesRxISR_8BIT;
  17.     hspi->TxISR = SPI_2linesTxISR_8BIT;
  18.   }
  19.   __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
复制代码

重新配置了中断函数,配置了发送和接收缓冲区为传入的数组,所以这里的数组要设置为全局变量,而前面设置的中断函数也失效了,而且使能了中断,所以我们前面所作的工作都是白费了。



收藏 评论0 发布时间:2021-12-17 12:04

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版