STM32F7使用SPI发送完成和接收中断

虽然在平常的使用中,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的具体过程,先埋个坑……(项目现在没这需求了)

STM32F7系列微控制器配置SPI(Serial Peripheral Interface)通常需要以下步骤: 1. **包含头文件**: 首先,在C文件头部包含相关的硬件库头文件,如`stm32f7xx_hal Spi.h`。 ```c #include "stm32f7xx_hal.h" ``` 2. **初始化HAL SPI模块**: 使用`Spi_HandleTypeDef`结构体`HAL_SPI_Init()`函数初始化SPI实例,设置必要的通信参数,如时钟频率、模式、数据位宽等。 ```c Spi_HandleTypeDef hi2c; HAL_StatusTypeDef status; // 初始化SPI handle hi2c.Instance = SPIx; // 替换为实际的SPI外设引脚 hi2c.Init.Mode = SPI_MODE MASTER; // 设定为主模式 hi2c.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; // 设置波特率预分频因子 hi2c.Init.Direction = SPI_DIRECTION_2LINES; // 双线模式 hi2c.Init.DataSize = SPI_DATASIZE_8BIT; // 数据位宽度 hi2c.Init.CLKPolarity = SPI_POLARITY_LOW; // 时钟极性低 hi2c.Init.CLKPhase = SPI_PHASE_1EDGE; // 时钟相位在数据的上升沿 // 开启GPIO功能并连接到SPI管脚 GPIO_InitTypeDef gpio_initTypeDef; // ... 配置GPIO为推挽输出 ... // 初始化SPI status = HAL_SPI_Init(&hi2c); if (status != HAL_OK) { // 处理错误... } ``` 3. **启用中断**: 如果需要,可以配置中断处理以监听接收完成发送完成或其他特定事件。 ```c // 如果需要,添加中断服务函数并开启中断 HAL_NVIC_EnableIRQ(SPIx_IRQn); // 替换SPIx为你使用中断标号 ``` 4. **发送接收数据**: 使用`HAL_SPI_Transmit()`或`HAL_SPI_Receive()`函数发送接收数据。 ```c uint8_t tx_data[] = {0x01, 0x02, 0x03}; // 发送的数据 uint16_t rx_buffer; // 接收缓冲区 // 发送数据 status = HAL_SPI_Transmit(&hi2c, tx_data, sizeof(tx_data), HAL_MAX_DELAY); if (status != HAL_OK) { // 处理错误... } // 接收数据 status = HAL_SPI_Receive(&hi2c, rx_buffer, sizeof(rx_buffer), HAL_MAX_DELAY); if (status != HAL_OK) { // 处理错误... } ``` 5. **关闭资源**: 当不再使用SPI时,记得释放资源: ```c HAL_GPIO_DeInit(hi2c.GpioxPin); // 关闭GPIO配置 HAL_SPI_DeInit(&hi2c); // 释放SPI资源 ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值