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

STM32F407 用定时器控制SPI传输的相关问题

[复制链接]
动于九天之上 提问时间:2022-12-7 17:14 / 未解决
我想用单片机读取ADS8695芯片的ADC值,单片机作为主机,ADC作为从机。SPI的CS端用TIM1的PWM替代,同时利用TIM1的UP事件,触发一次SPI发送,我的数据是32位的,通过UP事件触发的SPI发送只发送8位,导致SPI接收到的只有8位,请问该怎么解决呢?如何让UP事件触发的SPI发送能发送32位的数据呢。谢谢
收藏 评论6 发布时间:2022-12-7 17:14

举报

6个回答
xmshao 回答时间:2022-12-7 17:28:53
你如果想发送32位,每次更新事件后,你可以连续发送4个字节数据。另外,F407SPI支持16位数据模式,每次更新事件发2个半字数据也可以的。其中SPI的发送,基于查询或者中断方式还是DMA方式都可以。
动于九天之上 回答时间:2022-12-7 18:07:02
xmshao 发表于 2022-12-7 17:28
你如果想发送32位,每次更新事件后,你可以连续发送4个字节数据。另外,F407SPI支持16位数据模式,每次更新 ...

if(tim_baseHandle->Instance==TIM1)
  {
  /* USER CODE BEGIN TIM1_MspInit 0 */

  /* USER CODE END TIM1_MspInit 0 */
    /* TIM1 clock enable */
    __HAL_RCC_TIM1_CLK_ENABLE();

    /* TIM1 DMA Init */
    /* TIM1_UP Init */
    hdma_tim1_up.Instance = DMA2_Stream5;
    hdma_tim1_up.Init.Channel = DMA_CHANNEL_6;
    hdma_tim1_up.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_tim1_up.Init.PeriphInc = DMA_PINC_ENABLE;
    hdma_tim1_up.Init.MemInc = DMA_MINC_DISABLE;
    hdma_tim1_up.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_tim1_up.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_tim1_up.Init.Mode = DMA_CIRCULAR;
    hdma_tim1_up.Init.Priority = DMA_PRIORITY_LOW;
    hdma_tim1_up.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_tim1_up) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(tim_baseHandle,hdma[TIM_DMA_ID_UPDATE],hdma_tim1_up);

  /* USER CODE BEGIN TIM1_MspInit 1 */
    __HAL_TIM_CLEAR_IT(&htim1,TIM_IT_UPDATE);
    //HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);//打开DMA中断
    HAL_DMA_Start(&hdma_tim1_up,(uint32_t)arry_spi_tx,
                  (uint32_t)&SPI1->DR,D_ADS8695_LENGTH);
    __HAL_TIM_ENABLE_DMA(&htim1,TIM_DMA_UPDATE);
    __HAL_TIM_ENABLE(&htim1);
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);

  /* USER CODE END TIM1_MspInit 1 */
  }

  if(spiHandle->Instance==SPI1)
  {
  /* USER CODE BEGIN SPI1_MspInit 0 */

  /* USER CODE END SPI1_MspInit 0 */
    /* SPI1 clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**SPI1 GPIO Configuration
    PA5     ------> SPI1_SCK
    PA6     ------> SPI1_MISO
    PA7     ------> SPI1_MOSI
    */
    GPIO_InitStruct.Pin = ADS8695_SCL_Pin|ADS8695_SDI_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = ADS8695_SDO_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(ADS8695_SDO_GPIO_Port, &GPIO_InitStruct);

    /* SPI1 DMA Init */
    /* SPI1_RX Init */
    hdma_spi1_rx.Instance = DMA2_Stream0;
    hdma_spi1_rx.Init.Channel = DMA_CHANNEL_3;
    hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spi1_rx.Init.Mode = DMA_CIRCULAR;
    hdma_spi1_rx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_spi1_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
    hdma_spi1_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    hdma_spi1_rx.Init.MemBurst = DMA_MBURST_INC4;
    hdma_spi1_rx.Init.PeriphBurst = DMA_PBURST_INC4;
    if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(spiHandle,hdmarx,hdma_spi1_rx);

    /* SPI1_TX Init */
    hdma_spi1_tx.Instance = DMA2_Stream3;
    hdma_spi1_tx.Init.Channel = DMA_CHANNEL_3;
    hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spi1_tx.Init.Mode = DMA_NORMAL;
    hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_spi1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(spiHandle,hdmatx,hdma_spi1_tx);

    /* SPI1 interrupt Init */
    HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(SPI1_IRQn);
  /* USER CODE BEGIN SPI1_MspInit 1 */

    //注册传输完成中断
    HAL_DMA_RegisterCallback(&hdma_spi1_rx, HAL_DMA_XFER_CPLT_CB_ID, ADS8695_DmaCplCb);
    HAL_DMA_Start_IT(&hdma_spi1_rx, (uint32_t)&SPI1->DR,
                       (uint32_t)S_GLOBAL_VARIBLE.ARRYI_ADS8695_DATA,D_ADS8695_LENGTH);
    SET_BIT(SPI1->CR2,SPI_CR2_RXDMAEN);
    __HAL_SPI_ENABLE(&hspi1);
  /* USER CODE END SPI1_MspInit 1 */
  }


这是我的程序,如何在UP事件来到时发送 呢  我是采用
    HAL_DMA_Start(&hdma_tim1_up,(uint32_t)arry_spi_tx,
                  (uint32_t)&SPI1->DR,D_ADS8695_LENGTH);
这个函数的 如何让他发送 32位数据呢  这个函数只发送8位数据

动于九天之上 回答时间:2022-12-7 18:14:48
xmshao 发表于 2022-12-7 17:28
你如果想发送32位,每次更新事件后,你可以连续发送4个字节数据。另外,F407SPI支持16位数据模式,每次更新 ...

是在定时器更新中断中完成SPI的发送吗?能不能通过某些设置让SPI自动发送32位数据呢。我是通过    HAL_DMA_Start(&hdma_tim1_up,(uint32_t)arry_spi_tx,                  (uint32_t)&SPI1->DR,D_ADS8695_LENGTH);
这个函数完成更新事件触发DMA的,但是这个方式,只能发送一次,也就是8位,不能发送32位 请问这个该怎么解决呢?

动于九天之上 回答时间:2022-12-8 08:22:21
请ST的技术支持帮忙回复下把 如何让定时器更新事件触发DMA传输的时候,在没有任何干预的情况下 可以让SPI一次性输出至少18位 3个字节的数据?? 网上找了很多资料 都说做不到 只能通过事件中断来发送SPI数据,这样人为的中断干预会让程序变得不可控,毕竟要采集2048个点,要中断2048次,这个太频繁了,不知道是不是还有其他隐藏的设置可以做到让SPI在定时器更新事件触发的DMA能够发送3个以上字节???
xmshao 回答时间:2022-12-16 13:40:39
动于九天之上 发表于 2022-12-8 08:22
请ST的技术支持帮忙回复下把 如何让定时器更新事件触发DMA传输的时候,在没有任何干预的情况下 可以让SPI一 ...


对于STM32F4系列,没法一个事件触发多个DMA传输。

我之前的想法是1个更新事件,基于更新中断发送多个SPI数据。

你现在数据较多,不希望过多中断干预可以理解,也是你当前的真实需求。

比方你希望通过SPI发送1024个数据,使用定时器触发DMA也是可以的。

这里定时器事件作为DMA触发源,传输指定个数后,可以4个,可以是1024个,然后DMA停止传输。

当然,这里每个数据的传输还是对应1个定时器事件。不知这样是否可以满足你的应用需求。

xmshao 回答时间:2022-12-16 13:45:51
动于九天之上 发表于 2022-12-8 08:22
请ST的技术支持帮忙回复下把 如何让定时器更新事件触发DMA传输的时候,在没有任何干预的情况下 可以让SPI一 ...

对于STM32F4系列,一般没法一个事件触发多个DMA传输。

我之前的想法是1个更新事件,基于更新中断发送多个SPI数据。

你现在数据较多,不希望过多中断干预可以理解,也是你当前的真实需求。

比方你希望通过SPI发送1024个数据,使用定时器触发DMA也是可以的。

这里定时器事件作为DMA触发源,传输指定个数后,可以4个,可以是1024个,然后DMA停止传输。

当然,这里每个数据的传输还是对应1个定时器事件。不知这样是否可以满足你的应用需求。
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版