野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 12106|回复: 3

请教stm32h7 adc(dma软件启动模式)程序不能工作

[复制链接]
发表于 2019-8-8 11:23:26 | 显示全部楼层 |阅读模式
DMA_HandleTypeDef  ADC1DMA_Handler;
ADC_HandleTypeDef  ADCHandle;
ADC_ChannelConfTypeDef        sConfig;
uint32_t   aADCxConvertedData[30];


//初始化ADC
//ch: ADC_channels
//通道值 0~16取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
void MY_ADC_Init(void)
{
    GPIO_InitTypeDef GPIO_Initure;
    __HAL_RCC_ADC12_CLK_ENABLE();                   //使能ADC1/2时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();                    //开启GPIOA时钟
    __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP);     //ADC外设时钟选择
   
    GPIO_Initure.Pin=GPIO_PIN_5;         //PA5 PA6
    GPIO_Initure.Mode=GPIO_MODE_ANALOG;             //模拟
    GPIO_Initure.Pull=GPIO_NOPULL;                  //不带上下拉
    HAL_GPIO_Init(GPIOA,&GPIO_Initure);
   
     GPIO_Initure.Pin=GPIO_PIN_6;         //PA5 PA6
    GPIO_Initure.Mode=GPIO_MODE_ANALOG;             //模拟
    GPIO_Initure.Pull=GPIO_NOPULL;                  //不带上下拉
    HAL_GPIO_Init(GPIOA,&GPIO_Initure);
   
    ADCHandle.Instance                      = ADC1;
    ADCHandle.DMA_Handle                    =&ADC1DMA_Handler;
    ADCHandle.Init.ClockPrescaler           = ADC_CLOCK_SYNC_PCLK_DIV4;     
    ADCHandle.Init.Resolution               = ADC_RESOLUTION_16B;
    ADCHandle.Init.ScanConvMode             = ADC_SCAN_ENABLE;
    //ADCHandle.Init.EOCSelection             = ADC_EOC_SINGLE_CONV;
    ADCHandle.Init.EOCSelection               = ADC_EOC_SEQ_CONV;
    ADCHandle.Init.LowPowerAutoWait         = DISABLE;
    ADCHandle.Init.ContinuousConvMode       = ENABLE;
    ADCHandle.Init.NbrOfConversion          = 2;                              
    ADCHandle.Init.DiscontinuousConvMode    = DISABLE;                        
    ADCHandle.Init.NbrOfDiscConversion      = 0;                           
    ADCHandle.Init.ExternalTrigConv         = ADC_SOFTWARE_START;//软件启动
    ADCHandle.Init.ExternalTrigConvEdge     = ADC_EXTERNALTRIGCONVEDGE_NONE;/**/
    ADCHandle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
    //ADCHandle.Init.Overrun                  = ADC_OVR_DATA_OVERWRITTEN;
    ADCHandle.Init.Overrun                  = ADC_OVR_DATA_PRESERVED;
    ADCHandle.Init.LeftBitShift              = ADC_LEFTBITSHIFT_NONE;
    ADCHandle.Init.BoostMode                = ENABLE;                          /* Enable Boost mode as ADC clock frequency is bigger than 20 MHz */
    ADCHandle.Init.OversamplingMode         = DISABLE;                         /* No oversampling */
    /* Initialize ADC peripheral according to the passed parameters */
    HAL_ADC_Init(&ADCHandle);
   
    HAL_ADCEx_Calibration_Start(&ADCHandle,ADC_CALIB_OFFSET,ADC_SINGLE_ENDED); //ADC校准
   
   
    sConfig.Channel              = ADC_CHANNEL_19;              /* Sampled channel number */
    sConfig.Rank                 = ADC_REGULAR_RANK_1;          /* Rank of sampled channel number ADCx_CHANNEL */
    sConfig.SamplingTime         = ADC_SAMPLETIME_387CYCLES_5;   /* Sampling time (number of clock cycles unit) */
    sConfig.SingleDiff           = ADC_SINGLE_ENDED;            /* Single-ended input channel */
    sConfig.OffsetNumber         = ADC_OFFSET_NONE;             /* No offset subtraction */
    sConfig.Offset                 = 0;                                 /* Parameter discarded because offset correction is disabled */
    sConfig.OffsetRightShift    = DISABLE;
    HAL_ADC_ConfigChannel(&ADCHandle, &sConfig);
   
    sConfig.Channel              = ADC_CHANNEL_3;              /* Sampled channel number */
    sConfig.Rank                 = ADC_REGULAR_RANK_2;          /* Rank of sampled channel number ADCx_CHANNEL */
    sConfig.SamplingTime         = ADC_SAMPLETIME_387CYCLES_5;   /* Sampling time (number of clock cycles unit) */
    sConfig.SingleDiff           = ADC_SINGLE_ENDED;            /* Single-ended input channel */
    sConfig.OffsetNumber         = ADC_OFFSET_NONE;             /* No offset subtraction */
    sConfig.Offset                 = 0;                                 /* Parameter discarded because offset correction is disabled */
    sConfig.OffsetRightShift    = DISABLE;
    HAL_ADC_ConfigChannel(&ADCHandle, &sConfig);
   
    HAL_ADC_Start(&ADCHandle);
   
   
    //HAL_ADC_Start_DMA()
    //HAL_ADC_GetValue()
    //HAL_ADC_Start_DMA(&AdcHandle,(uint32_t *)aADCxConvertedData,ADC_CONVERTED_DATA_BUFFER_SIZE);
    //HAL_ADC_Stop_DMA(&AdcHandle);
    //ADC1_Handler.DMA_Handle=&ADC1TxDMA_Handler; //开启DMA请求
    //HAL_ADC_Init(&ADC1_Handler);                //初始化
   
}






//DMAx的各通道配置
//这里的传输形式是固定的,这点要根据不同的情况来修改
//从存储器->外设模式/8位数据宽度/存储器增量模式
//DMA_StreamxMA数据流,DMA1_Stream0~7/DMA2_Stream0~7
void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx)
{
    if((u32)DMA_Streamx>(u32)DMA2)//得到当前stream是属于DMA2还是DMA1
    {
        __HAL_RCC_DMA2_CLK_ENABLE();//DMA2时钟使能   
    }else
    {
        __HAL_RCC_DMA1_CLK_ENABLE();//DMA1时钟使能
    }
   
    __HAL_LINKDMA(&ADCHandle,DMA_Handle,ADC1DMA_Handler);    //将DMA与USART1联系起来(发送DMA)
   
    //Tx DMA配置
    ADC1DMA_Handler.Instance=DMA_Streamx;                            //数据流选择
    ADC1DMA_Handler.Init.Request=DMA_REQUEST_ADC1;                     //ADC1发送DMA
    ADC1DMA_Handler.Init.Direction=DMA_PERIPH_TO_MEMORY;             //外设到存储器
    ADC1DMA_Handler.Init.PeriphInc=DMA_PINC_DISABLE;                 //外设非增量模式
    ADC1DMA_Handler.Init.MemInc=DMA_MINC_ENABLE;                     //存储器增量模式
    ADC1DMA_Handler.Init.PeriphDataAlignment=DMA_PDATAALIGN_HALFWORD;//外设数据长度:16位
    ADC1DMA_Handler.Init.MemDataAlignment=DMA_MDATAALIGN_HALFWORD;   //存储器数据长度:16位
    ADC1DMA_Handler.Init.Mode=DMA_NORMAL;                          //外设流控模式
    ADC1DMA_Handler.Init.Priority=DMA_PRIORITY_MEDIUM;               //中等优先级
    ADC1DMA_Handler.Init.FIFOMode=DMA_FIFOMODE_DISABLE;              
    ADC1DMA_Handler.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL;      
    ADC1DMA_Handler.Init.MemBurst=DMA_MBURST_SINGLE;                 //存储器突发单次传输
    ADC1DMA_Handler.Init.PeriphBurst=DMA_PBURST_SINGLE;              //外设突发单次传输
   
    //ADC1DMA_Handler.XferCpltCallback = HAL_DMA_IRQHandler;
    //HAL_DMA_DeInit(&ADC1DMA_Handler);   
    HAL_DMA_Init(&ADC1DMA_Handler);
}



main()
{
    MY_ADC_Init();                          //初始化ADC1
    MYDMA_Config(DMA2_Stream2);                //初始化DMA
   
    HAL_ADC_Start_DMA(&ADC1DMA_Handler,(uint32_t *)aADCxConvertedData,10);
    while(1)
   {
       adcx=aADCxConvertedData[0];
        LCD_ShowxNum(142,130,adcx,5,16,0);

   }


}


回复

使用道具 举报

发表于 2019-8-8 14:02:18 | 显示全部楼层
DMA1和DMA2访问不了DTCM区域,可以检查一下这个变量aADCxConvertedData的地址
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-8-8 16:43:56 | 显示全部楼层
Grit 发表于 2019-8-8 14:02
DMA1和DMA2访问不了DTCM区域,可以检查一下这个变量aADCxConvertedData的地址

ADC_HandleTypeDef ADC1_Handler;//ADC句柄
ADC_ChannelConfTypeDef ADC1_ChanConf;
DMA_HandleTypeDef  ADC1DMA_Handler;      //DMA句柄
uint32_t   aAD_Data[30];
//初始化ADC
//ch: ADC_channels
//通道值 0~16取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_16
void MY_ADC_Init(void)
{
        GPIO_InitTypeDef GPIO_Initure;
    __HAL_RCC_ADC12_CLK_ENABLE();           //使能ADC1/2时钟
    __HAL_RCC_GPIOA_CLK_ENABLE();                        //开启GPIOA时钟
        __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP); //ADC外设时钟选择
       
    GPIO_Initure.Pin=GPIO_PIN_5 | GPIO_PIN_6;            //PA5
    GPIO_Initure.Mode=GPIO_MODE_ANALOG;     //模拟
    GPIO_Initure.Pull=GPIO_NOPULL;          //不带上下拉
    HAL_GPIO_Init(GPIOA,&GPIO_Initure);
       
        ADC1_Handler.Instance          = ADC1;
        HAL_ADC_DeInit(&ADC1_Handler);
       
    ADC1_Handler.Instance=ADC1;
    ADC1_Handler.Init.ClockPrescaler=ADC_CLOCK_SYNC_PCLK_DIV4;         //4分频,ADCCLK=PER_CK/4=64/4=16MHZ
    ADC1_Handler.Init.Resolution=ADC_RESOLUTION_16B;                   //16位模式
    ADC1_Handler.Init.ScanConvMode=ENABLE;                            //扫描模式
    ADC1_Handler.Init.EOCSelection=ADC_EOC_SEQ_CONV;                       //关闭EOC中断
        //ADC_EOC_SEQ_CONV
        //ADC_EOC_SINGLE_CONV
        ADC1_Handler.DMA_Handle=&ADC1DMA_Handler;
        ADC1_Handler.Init.LowPowerAutoWait=DISABLE;                                        //自动低功耗关闭                               
    ADC1_Handler.Init.ContinuousConvMode=ENABLE;               //关闭连续转换
    ADC1_Handler.Init.NbrOfConversion=2;                        //1个转换在规则序列中 也就是只转换规则序列1
    ADC1_Handler.Init.DiscontinuousConvMode=DISABLE;            //禁止不连续采样模式
    ADC1_Handler.Init.NbrOfDiscConversion=0;                    //不连续采样通道数为0
    ADC1_Handler.Init.ExternalTrigConv=ADC_SOFTWARE_START;      //软件触发
    ADC1_Handler.Init.ExternalTrigConvEdge=ADC_EXTERNALTRIGCONVEDGE_NONE;//使用软件触发
        ADC1_Handler.Init.BoostMode=ENABLE;                                                        //BOOT模式关闭
        ADC1_Handler.Init.Overrun=ADC_OVR_DATA_OVERWRITTEN;                        //有新的数据的死后直接覆盖掉旧数据
        //ADC1_Handler.Init.Overrun=ADC_OVR_DATA_PRESERVED;
        ADC1_Handler.Init.OversamplingMode=DISABLE;                                        //过采样关闭
        ADC1_Handler.Init.ConversionDataManagement=ADC_CONVERSIONDATA_DMA_CIRCULAR;  //规则通道的数据仅仅保存在DR寄存器里面
    HAL_ADC_Init(&ADC1_Handler);                                 //初始化
        HAL_ADCEx_Calibration_Start(&ADC1_Handler,ADC_CALIB_OFFSET,ADC_SINGLE_ENDED); //ADC校准


        ADC1_ChanConf.Channel=ADC_CHANNEL_19;                             //通道
        ADC1_ChanConf.Rank=ADC_REGULAR_RANK_1;                          //1个序列
        ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_64CYCLES_5;              //采样时间      
        ADC1_ChanConf.SingleDiff=ADC_SINGLE_ENDED;                                  //单边采集                         
        ADC1_ChanConf.OffsetNumber=ADC_OFFSET_NONE;                    
        ADC1_ChanConf.Offset=0;   
        HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf);        //通道配置
       
        ADC1_ChanConf.Channel=ADC_CHANNEL_3;                             //通道
        ADC1_ChanConf.Rank=ADC_REGULAR_RANK_2;                          //1个序列
        ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_64CYCLES_5;              //采样时间      
        ADC1_ChanConf.SingleDiff=ADC_SINGLE_ENDED;                                  //单边采集                         
        ADC1_ChanConf.OffsetNumber=ADC_OFFSET_NONE;                    
        ADC1_ChanConf.Offset=0;   
        HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf);        //通道配置
       
       
        //HAL_ADC_Start(&ADC1_Handler);
        //HAL_ADC_PollForConversion(&ADC1_Handler,10);
}



void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx)
{
        __HAL_RCC_DMA2_CLK_ENABLE();//DMA2时钟使能       
    __HAL_RCC_DMA1_CLK_ENABLE();//DMA1时钟使能
       
       
    //Tx DMA配置
    ADC1DMA_Handler.Instance=DMA_Streamx;                            //数据流选择
        ADC1DMA_Handler.Init.Request=DMA_REQUEST_ADC1;                                         //ADC1发送DMA
    ADC1DMA_Handler.Init.Direction=DMA_PERIPH_TO_MEMORY;             //外设到存储器
    ADC1DMA_Handler.Init.PeriphInc=DMA_PINC_DISABLE;                 //外设非增量模式
    ADC1DMA_Handler.Init.MemInc=DMA_MINC_ENABLE;                     //存储器增量模式
    ADC1DMA_Handler.Init.PeriphDataAlignment=DMA_PDATAALIGN_WORD;//外设数据长度:16位
    ADC1DMA_Handler.Init.MemDataAlignment=DMA_MDATAALIGN_WORD;   //存储器数据长度:16位
    ADC1DMA_Handler.Init.Mode=DMA_CIRCULAR;                          //外设流控模式
    ADC1DMA_Handler.Init.Priority=DMA_PRIORITY_MEDIUM;               //中等优先级
    ADC1DMA_Handler.Init.FIFOMode=DMA_FIFOMODE_DISABLE;              
    ADC1DMA_Handler.Init.FIFOThreshold=DMA_FIFO_THRESHOLD_FULL;      
    ADC1DMA_Handler.Init.MemBurst=DMA_PBURST_SINGLE;                                 //存储器突发单次传输
    ADC1DMA_Handler.Init.PeriphBurst=DMA_PBURST_SINGLE;                      //外设突发单次传输
        ADC1DMA_Handler.StreamBaseAddress=(uint32_t)aAD_Data;
       
        __HAL_LINKDMA(&ADC1_Handler,DMA_Handle,ADC1DMA_Handler);    //将DMA与USART1联系起来(发送DMA)
       
        //HAL_DMA_DeInit(&ADC1DMA_Handler);   
    HAL_DMA_Init(&ADC1DMA_Handler);
        HAL_DMA_Start (&ADC1DMA_Handler,(u32)&ADC1->DR,(unsigned int)&aAD_Data,20);//
       
}


main()
{
        MY_ADC_Init();                                  //初始化ADC1通道5
        MYDMA_Config(DMA1_Stream7);                                //初始化DMA
        while(1)
        {
                HAL_ADC_Start_DMA(&ADC1_Handler, (uint32_t *)aAD_Data,2);
                delay_ms(450);       
                adcx=aAD_Data[0];
                  delay_ms(450);       
                  HAL_ADC_Stop_DMA(&ADC1_Handler);
        }
}


修改成这样以后,能读取ad值,但值一直不变

回复 支持 反对

使用道具 举报

发表于 2019-8-19 20:39:23 | 显示全部楼层
SCB清除....
回复

使用道具 举报

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

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-3-29 18:42 , Processed in 0.028064 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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