OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4648|回复: 6

STM32F7 ADC2+TIM2 CC2驱动+DMA传输,想要不停更新填充数组

[复制链接]

6

主题

23

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
236
金钱
236
注册时间
2021-6-19
在线时间
67 小时
发表于 2021-10-15 10:30:39 | 显示全部楼层 |阅读模式
6金钱
大家好!我在测试TIM2驱动ADC2采样,DMA传输时发现,当我设定的128大小的数组被填充完毕后,就不再更新。我设想的是当数组被填满后,继续开始从数组第0位填充更新数组。请问这种想法可以实现吗,具体要如何实现?谢谢各位大佬指教!
下面是我的具体配置
ADC2+DMA:
  1. ADC_HandleTypeDef hadc2;
  2. DMA_HandleTypeDef hdma_adc2;
  3. ADC_ChannelConfTypeDef hadc2_channel;

  4. void MY_ADC_Init(void)
  5. {
  6.     __HAL_RCC_DMA2_CLK_ENABLE();
  7.     HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0);
  8.     HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);

  9.     hdma_adc2.Instance = DMA2_Stream2;
  10.     hdma_adc2.Init.Channel = DMA_CHANNEL_1;
  11.     hdma_adc2.Init.Direction = DMA_PERIPH_TO_MEMORY;
  12.     hdma_adc2.Init.PeriphInc = DMA_PINC_DISABLE;               //???????
  13.     hdma_adc2.Init.MemInc = DMA_MINC_ENABLE;                   //???????
  14.     hdma_adc2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;  //??????:16?
  15.     hdma_adc2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;     //???????:16?
  16.     hdma_adc2.Init.Mode = DMA_CIRCULAR;                          //???????
  17.     hdma_adc2.Init.Priority = DMA_PRIORITY_LOW;             //?????
  18.     hdma_adc2.Init.FIFOMode = DMA_FIFOMODE_DISABLE;            /* ??FIFO*/

  19.     HAL_DMA_Init(&hdma_adc2);

  20.     __HAL_LINKDMA(&hadc2, DMA_Handle, hdma_adc2);                //?DMA?ADC????


  21.     hadc2.Instance = ADC2;
  22.     hadc2.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; //4??,ADCCLK=PCLK2/4=108/4=27MHZ
  23.     hadc2.Init.Resolution = ADC_RESOLUTION_12B;           //12???
  24.     hadc2.Init.ScanConvMode = DISABLE;                    //?????
  25.     hadc2.Init.ContinuousConvMode = DISABLE;              //??????
  26.     hadc2.Init.DiscontinuousConvMode = DISABLE;           //?????????
  27.     hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING; //??????
  28.     hadc2.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T2_CC2;     //????
  29.     hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;           //???
  30.     hadc2.Init.NbrOfConversion = 1;                       //1????????? ??????????1
  31.     hadc2.Init.DMAContinuousRequests = ENABLE;           //??DMA??
  32.     hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  33.     HAL_ADC_Init(&hadc2);

  34.     hadc2_channel.Channel = ADC_CHANNEL_3;                                 //??
  35.     hadc2_channel.Rank = 1;                                     //??1
  36.     hadc2_channel.SamplingTime = ADC_SAMPLETIME_480CYCLES;      //????
  37.     hadc2_channel.Offset = 0;
  38.     HAL_ADC_ConfigChannel(&hadc2, &hadc2_channel);       //????

  39.     MY_TIM2_Init();
  40.                 HAL_ADC_Start_DMA(&hadc2, (uint32_t *)buffer, sizeof(buffer));
  41. }


  42. //void DMA2_Stream2_IRQHandler(void)
  43. //{
  44. //    HAL_DMA_IRQHandler(&hdma_adc2);
  45. //}

  46. void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
  47. {
  48.     printf("DMA transfer complete\r\n");
  49. }
  50. void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc)
  51. {
  52.     printf("DMA Half transfer complete\r\n");
  53. }

  54. void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc)
  55. {
  56.     printf("DMA transfer error\r\n");
  57. }
复制代码
TIM2:
  1. TIM_HandleTypeDef htim2;
  2. TIM_OC_InitTypeDef TIM2_CH2Handler;
  3. void MY_TIM2_Init(void)
  4. {
  5.     __HAL_RCC_TIM2_CLK_ENABLE();
  6.        
  7.     HAL_NVIC_SetPriority(TIM2_IRQn, 1, 3);
  8.     HAL_NVIC_EnableIRQ(TIM2_IRQn);

  9.     htim2.Instance = TIM2;
  10.     htim2.Init.Prescaler = 10800-1;
  11.     htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  12.     htim2.Init.Period = 20000;
  13.     htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

  14.     HAL_TIM_PWM_Init(&htim2);


  15.     TIM2_CH2Handler.OCMode = TIM_OCMODE_PWM1;
  16.     TIM2_CH2Handler.Pulse = 10000;
  17.     TIM2_CH2Handler.OCPolarity = TIM_OCPOLARITY_LOW;
  18.     TIM2_CH2Handler.OCFastMode = TIM_OCFAST_DISABLE;
  19.     HAL_TIM_PWM_ConfigChannel(&htim2, &TIM2_CH2Handler, TIM_CHANNEL_2) ;


  20.     __HAL_TIM_ENABLE_IT(&htim2, TIM_IT_UPDATE);
  21.     TIM_CCxChannelCmd(htim2.Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);
  22.     __HAL_TIM_ENABLE(&htim2);
  23. }


  24. void TIM2_IRQHandler(void)
  25. {
  26.     HAL_TIM_IRQHandler(&htim2);
  27. }


  28. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  29. {
  30.     if (htim == (&htim2))
  31.     {
  32.         printf("timer irq\r\n");
  33.     }
  34. }


  35. void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
  36. {
  37.     GPIO_InitTypeDef GPIO_InitStruct = {0};

  38.     __HAL_RCC_TIM2_CLK_ENABLE();
  39.     __HAL_RCC_GPIOA_CLK_ENABLE();
  40.     GPIO_InitStruct.Pin = GPIO_PIN_1;
  41.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  42.     GPIO_InitStruct.Pull = GPIO_NOPULL;
  43.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  44.     GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
  45.     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  46. }
复制代码
main.c
  1. extern uint16_t buffer[128];
  2.         void show()
  3.         {
  4.     int i;
  5.     printf("\r\ndata:");
  6.     for (i = 0; i < 128; i++)
  7.     {
  8.         if (i % 16 == 0) printf("\r\n");
  9.         printf("%6d", buffer[i]);
  10.                         //buffer[i]=0;

  11.     }
  12.     printf("\r\n");
  13.         }
  14. int main
  15. {
  16.    MY_ADC_Init();
  17. }
复制代码


最佳答案

查看完整内容[请看2#楼]

可以是可以,不过堆栈得设置很大,建议在主程序(main函数)里面做fft会好点。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165371
金钱
165371
注册时间
2010-12-1
在线时间
2110 小时
发表于 2021-10-15 10:30:40 | 显示全部楼层
啾啾啾 发表于 2021-10-18 16:02
好的谢谢原子哥,我想请问一下,我想对采集来的adc数据进行FFT处理,请问在DMA传输完毕中断中可以进行FFT ...

可以是可以,不过堆栈得设置很大,建议在主程序(main函数)里面做fft会好点。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165371
金钱
165371
注册时间
2010-12-1
在线时间
2110 小时
发表于 2021-10-16 01:08:23 | 显示全部楼层
开启循环模式即可
回复

使用道具 举报

6

主题

23

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
236
金钱
236
注册时间
2021-6-19
在线时间
67 小时
 楼主| 发表于 2021-10-16 09:53:08 | 显示全部楼层

谢谢原子哥!我已经开启了DMA的循环模式,但是还是数组第一次填充完毕后就不再填充,串口打印了一段时间也不再打印。是不是需要设置DMA的传输完成中断?还想请问原子哥一个问题:我使用TIM2的CC2通道产生PWM波驱动ADC采样,是不是不需要开启TIM的中断?这个程序是我看别人的例程,他开启了TIM UPDATE中断。
回复

使用道具 举报

6

主题

23

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
236
金钱
236
注册时间
2021-6-19
在线时间
67 小时
 楼主| 发表于 2021-10-16 10:47:22 | 显示全部楼层

原子哥我将数组大小改成8位小一点后,发现等到数组填充完毕,过一段时间才会继续填充数组,我设置了DMA传输完毕中断,在中断里面打印传输完毕字符。通过串口观察,等到数组填完,过一会这个字符才会打印出来,然后就是继续填充
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165371
金钱
165371
注册时间
2010-12-1
在线时间
2110 小时
发表于 2021-10-17 22:17:23 | 显示全部楼层
啾啾啾 发表于 2021-10-16 09:53
谢谢原子哥!我已经开启了DMA的循环模式,但是还是数组第一次填充完毕后就不再填充,串口打印了一段时间 ...

开不开中断都不影响,DMA + ADC循环模式,论坛有参考代码,你可以搜索下参考一下
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

6

主题

23

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
236
金钱
236
注册时间
2021-6-19
在线时间
67 小时
 楼主| 发表于 2021-10-18 16:02:23 | 显示全部楼层
正点原子 发表于 2021-10-17 22:17
开不开中断都不影响,DMA + ADC循环模式,论坛有参考代码,你可以搜索下参考一下

好的谢谢原子哥,我想请问一下,我想对采集来的adc数据进行FFT处理,请问在DMA传输完毕中断中可以进行FFT处理吗
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-26 20:04

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表