OpenEdv-开源电子网

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

STM32H743 ADC+DMA循环传输,数组超过16后读取不到数据

[复制链接]

4

主题

13

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
267
金钱
267
注册时间
2019-5-16
在线时间
94 小时
发表于 2019-8-26 09:04:34 | 显示全部楼层 |阅读模式
1金钱
现需要实现如下功能,采样一个ADC口,软件启动连续采样,数据通过DMA存放。
每连续采样30次后进入1次DMA中断。
在实现这个功能时发现只要连续采样的次数超过15次,15以后的数组都不再刷新,找了半天也没看出问题在哪。



ADC+DMA部分程序代码如下

定义ADC存放数组
__attribute__ ((at(0x30000000))) __IO uint16_t ADC_ConvertedValue[30];
//或使用ALIGN_32BYTES (static uint16_t   ADC_ConvertedValue[30]);

一、//ADC引脚配置
static void ADC_GPIO_Mode_Config(void)
{
  
    GPIO_InitTypeDef  GPIO_InitStruct;
   __HAL_RCC_GPIOC_CLK_ENABLE();

    GPIO_InitStruct.Pin = GPIO_PIN_1;  
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;

    /* 配置为模拟输入,不需要上拉电阻 */
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

}


二、//时钟+DMA配置
static void ADC_Mode_Config(void)
{
    ADC_ChannelConfTypeDef ADC_Config;

    RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit;  
    /*            配置ADC3时钟源             */
    /*    HSE Frequency(Hz)    = 25000000   */                                             

    RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
    RCC_PeriphClkInit.PLL2.PLL2FRACN = 0;
    RCC_PeriphClkInit.PLL2.PLL2M = 5;
    RCC_PeriphClkInit.PLL2.PLL2N = 160;
    RCC_PeriphClkInit.PLL2.PLL2P = 25;
    RCC_PeriphClkInit.PLL2.PLL2Q = 2;
    RCC_PeriphClkInit.PLL2.PLL2R = 2;
    RCC_PeriphClkInit.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_2;
    RCC_PeriphClkInit.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
    RCC_PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
   HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit);  

    /* 使能ADC1、2时钟 */
    __HAL_RCC_ADC12_CLK_ENABLE();
               
   //使能DMA时钟
   __HAL_RCC_DMA1_CLK_ENABLE();
         
         //指向DMA数据流基地址的指针,指定用数据流1
    hdma_adc.Instance = DMA1_Stream1;

     //DMA请求选择
    hdma_adc.Init.Request = DMA_REQUEST_ADC1;

   //传输方向,外设至存储器
    hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY;

   //如果配置为PeriphInc_Enable,使能外设地址自动递增。ADC1数据寄存器地址固定,无需递增使能
    hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE;

   //如果配置为MemInc_Enable,使能存储器地址自动递增功能
    hdma_adc.Init.MemInc = DMA_MINC_DISABLE;

     //外设数据宽度,可选字节(8位)、半字(16位)、字(32位)
    hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;

   //存储器字节宽度,可选字节(8位)、半字(16位)、字(32位)
    hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;

   //DMA传输模式选择,可选一次传输或者循环传输
    hdma_adc.Init.Mode = DMA_CIRCULAR;

        //软件设置数据流的优先级
    hdma_adc.Init.Priority = DMA_PRIORITY_LOW;

        //FIFO 模式使能
    hdma_adc.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
               
    HAL_DMA_Init(&hdma_adc);
                        
   //hdma_adc和ADC_Handle.DMA_Handle链接
    __HAL_LINKDMA(&ADC1_Handle,DMA_Handle,hdma_adc);
               
               
    ADC1_Handle.Instance = ADC1;
    HAL_ADC_DeInit(&ADC1_Handle);
        
    //使能Boost模式
    ADC1_Handle.Init.BoostMode = ENABLE;

    //ADC时钟1分频
    ADC1_Handle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
               
    //连续转换模式
    ADC1_Handle.Init.ContinuousConvMode = ENABLE;
               
    //数据存放在数据寄存器中
    ADC1_Handle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;

    //关闭不连续转换模式
    ADC1_Handle.Init.DiscontinuousConvMode = DISABLE;
    ADC1_Handle.Init.NbrOfDiscConversion = 0;

   //使能EOC标志位
    ADC1_Handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
        
    //软件触发   ADC1_Handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;
               
    //关闭低功耗自动等待
    ADC1_Handle.Init.LowPowerAutoWait = DISABLE;

    //数据溢出时,覆盖写入
    ADC1_Handle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;

    //不使能过采样模式
    ADC1_Handle.Init.OversamplingMode = DISABLE;

    //分辨率为:16bit
    ADC1_Handle.Init.Resolution = ADC_RESOLUTION_16B;

    //使能多通道扫描
    ADC1_Handle.Init.ScanConvMode = ENABLE;
               
   //扫描1个通道        
   ADC1_Handle.Init.NbrOfConversion = 1;

    //初始化 主ADC1
    HAL_ADC_Init(&ADC1_Handle) ;
               
               
    HAL_ADCEx_Calibration_Start(&ADC1_Handle,ADC_CALIB_OFFSET,ADC_SINGLE_ENDED);
               
    //使用通道11     ADC_Config.Channel = ADC_CHANNEL_11;
    //转换顺序为1
    ADC_Config.Rank = ADC_REGULAR_RANK_1 ;
    //采样周期为1.5个周期
    ADC_Config.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
    //不使用差分输入的功能
    ADC_Config.SingleDiff = ADC_SINGLE_ENDED ;
    ADC_Config.OffsetNumber = ADC_OFFSET_NONE;            
    ADC_Config.Offset = 0;                                
    //配置ADC1通道
    HAL_ADC_ConfigChannel(&ADC1_Handle, &ADC_Config);

    //使能DMA
    HAL_ADC_Start_DMA(&ADC1_Handle, (uint32_t*)&ADC_ConvertedValue, 30);
       


}



三、//DMA中断配置
static void DMA_NVIC_Config(void)
{
    HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
}

四、//DMA中断服务函数
void DMA1_Stream1_IRQHandler(void)
{
    HAL_DMA_IRQHandler(ADC1_Handle.DMA_Handle);
}





五、//最终初始化
void ADC_Init(void)
{

    ADC_GPIO_Mode_Config();

    ADC_Mode_Config();
    DMA_NVIC_Config();
    //软件触发ADC采样
    HAL_ADC_Start(&ADC1_Handle);
}


六、//ADC回调函数
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
       /* 获取结果 */

     SCB_InvalidateDCache_by_Addr((uint32_t *) &ADC_ConvertedValue[0],30);
    TEST=ADC_ConvertedValue[16];//TEST为随意设置的uint16_t型变量

   现在出现了这种情况,加上上面这句赋值语句,再观察ADC_ConvertedValue[16]以后的值,都无法再刷新,
   而ADC_ConvertedValue[0]到[15]都正常;
   把上面这句赋值语句去掉,ADC_ConvertedValue[16]以后的值刷新正常。
   有人能看出问题在哪吗?


}

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

4

主题

13

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
267
金钱
267
注册时间
2019-5-16
在线时间
94 小时
 楼主| 发表于 2019-8-26 17:04:55 | 显示全部楼层
回复

使用道具 举报

1

主题

18

帖子

0

精华

新手上路

积分
40
金钱
40
注册时间
2019-7-28
在线时间
8 小时
发表于 2019-9-3 10:11:51 | 显示全部楼层
那简单,就不要赋值了,接收完成后,在处理数组中的数据
回复

使用道具 举报

1

主题

18

帖子

0

精华

新手上路

积分
40
金钱
40
注册时间
2019-7-28
在线时间
8 小时
发表于 2019-9-8 16:32:34 | 显示全部楼层
能贴下完整代码不?
回复

使用道具 举报

4

主题

20

帖子

0

精华

初级会员

Rank: 2

积分
59
金钱
59
注册时间
2019-6-4
在线时间
13 小时
发表于 2019-10-21 09:48:11 | 显示全部楼层
可以看一下完整的工程吗?
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手入门

积分
16
金钱
16
注册时间
2019-11-23
在线时间
5 小时
发表于 2019-12-10 17:33:31 | 显示全部楼层
你好,我最近在做H743的双路AD同步采集,我想问问您,有没有什么经验分享,我已经弄了十天左右了,始终找不到问题所在,看到您发的帖子,想向您请教一下,打扰了
回复

使用道具 举报

0

主题

1

帖子

0

精华

初级会员

Rank: 2

积分
76
金钱
76
注册时间
2019-1-16
在线时间
28 小时
发表于 2020-8-21 11:59:57 | 显示全部楼层
楼主问题解决了吗?我现在也遇到了同样的问题,只要读取缓存区的内容DMA传输就会出问题。
回复

使用道具 举报

4

主题

13

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
267
金钱
267
注册时间
2019-5-16
在线时间
94 小时
 楼主| 发表于 2020-10-16 09:24:05 | 显示全部楼层
臭皮匠 发表于 2020-8-21 11:59
楼主问题解决了吗?我现在也遇到了同样的问题,只要读取缓存区的内容DMA传输就会出问题。

最终发现是32字节对齐的问题
回复

使用道具 举报

4

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
117
金钱
117
注册时间
2021-1-7
在线时间
31 小时
发表于 2021-5-20 16:40:05 | 显示全部楼层
请问你可以详细说说你的解决过程嘛
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-2-27 21:13

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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