硬汉嵌入式论坛

 找回密码
 立即注册
查看: 3282|回复: 4
收起左侧

[ADC] STM32H7中的ADC3模拟看门狗不能触发

[复制链接]

4

主题

12

回帖

24

积分

新手上路

积分
24
发表于 2019-3-12 22:48:06 | 显示全部楼层 |阅读模式
本帖最后由 Paprika 于 2019-3-12 22:50 编辑

一直在调STM32H7的ADC,发现一个奇怪的现象,根据数据手册可以得知每个ADC有都有三个看门狗。但是在配置的过程中发现ADC12的看门狗可以实现中断但是ADC3的一直实现不了。不知道是我配置的问题还是硬件bug,希望得到各位的指导。先贴出ADC1可以正常触发的程序:
void ADC1_Config(void){//配置ADC、ADC通道、看门狗
    ADC_ChannelConfTypeDef                                            ADC1_ChanConf;
    //ADC1配置
    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_12B;  //16位模式
    ADC1_Handler.Init.ScanConvMode                                                 =ADC_SCAN_DISABLE;   //非扫描模式
    ADC1_Handler.Init.EOCSelection                                           =ADC_EOC_SINGLE_CONV; //关闭EOC中断
   ADC1_Handler.Init.LowPowerAutoWait                                 =DISABLE;                                        //自动低功耗关闭                                
    ADC1_Handler.Init.ContinuousConvMode                         =DISABLE;          //关闭连续转换
    ADC1_Handler.Init.NbrOfConversion                                         =1;              //1个转换在规则序列中 也就是只转换规则序列1
    ADC1_Handler.Init.DiscontinuousConvMode                 =DISABLE;            //禁止不连续采样模式
    ADC1_Handler.Init.NbrOfDiscConversion      =1;                    //不连续采样通道数为0
    ADC1_Handler.Init.ExternalTrigConv         =ADC_EXTERNALTRIG_T3_TRGO;      //T3触发
    ADC1_Handler.Init.ExternalTrigConvEdge     =ADC_EXTERNALTRIGCONVEDGE_RISING;//上升沿
        
   ADC1_Handler.Init.ConversionDataManagement =ADC_CONVERSIONDATA_DMA_CIRCULAR;  //规则通道的数据仅仅保存在DR寄存器里面
                ADC1_Handler.Init.BoostMode                                                     =ENABLE;                                                        //BOOT模式关闭
                ADC1_Handler.Init.Overrun                                                                         =ADC_OVR_DATA_OVERWRITTEN;                        //有新的数据的死后直接覆盖掉旧数据
                ADC1_Handler.Init.OversamplingMode                           =DISABLE;                                        //过采样关闭
        HAL_ADC_Init(&ADC1_Handler);                                 //初始化
        
        //配置通道
          ADC1_ChanConf.Channel                     =        ADC_CHANNEL_19;  //通道
    ADC1_ChanConf.Rank                                                       =        ADC_REGULAR_RANK_1;        //1个序列
    ADC1_ChanConf.SamplingTime                                                                =        ADC_SAMPLETIME_8CYCLES_5;  //采样时间      
                ADC1_ChanConf.SingleDiff                                                                        =        ADC_SINGLE_ENDED;                                  //单边采集                          
                ADC1_ChanConf.OffsetNumber                                                                =        ADC_OFFSET_NONE;                     
                ADC1_ChanConf.Offset                                                                                        =        0;   
    HAL_ADC_ConfigChannel(&ADC1_Handler,&ADC1_ChanConf);        //ADC的通道19
        //看门狗配置
                AnalogWDGConfig.WatchdogNumber            = ADC_ANALOGWATCHDOG_2;
                AnalogWDGConfig.WatchdogMode                                                         = ADC_ANALOGWATCHDOG_ALL_REG;
                AnalogWDGConfig.Channel                                                                         = ADC_CHANNEL_19;
                AnalogWDGConfig.ITMode                                                                                 = ENABLE;
                AnalogWDGConfig.HighThreshold                                                 = 2000;
                AnalogWDGConfig.LowThreshold                                                  = 0;
                HAL_ADC_AnalogWDGConfig(&ADC1_Handler, &AnalogWDGConfig);
}

ADC是用定时器触发的,在HAL_ADC_MspInit();函数中配置使用DMA传输,以及对应的时钟使能。
下面是ADC3是不能进入中断的,问题代码:
void ADC3_Config(void){//配置ADC3、ADC3通道
                ADC_ChannelConfTypeDef                                    ADC3_ChanConf;
                //ADC3配置        
                ADC3_Handler.Instance                                                                                  =         ADC3;
                ADC3_Handler.Init.ClockPrescaler                                         =         ADC_CLOCKPRESCALER_PCLK_DIV4;
                ADC3_Handler.Init.Resolution                                                         =        ADC_RESOLUTION_12B;
    ADC3_Handler.Init.ScanConvMode                                                 =        ADC_SCAN_DISABLE;   //非扫描模式
    ADC3_Handler.Init.EOCSelection                                           =        ADC_EOC_SINGLE_CONV; //关闭EOC中断
                ADC3_Handler.Init.LowPowerAutoWait                                 =        DISABLE;                                        //自动低功耗关闭                                
    ADC3_Handler.Init.ContinuousConvMode                         =        DISABLE;          //关闭连续转换
    ADC3_Handler.Init.NbrOfConversion                                         =        1;              //1个转换在规则序列中 也就是只转换规则序列1
    ADC3_Handler.Init.DiscontinuousConvMode                 =        DISABLE;            //禁止不连续采样模式
    ADC3_Handler.Init.NbrOfDiscConversion      =        1;                    //不连续采样通道数为0
    ADC3_Handler.Init.ExternalTrigConv         =        ADC_EXTERNALTRIG_T3_TRGO;      //T3触发
    ADC3_Handler.Init.ExternalTrigConvEdge     =        ADC_EXTERNALTRIGCONVEDGE_RISING;//上升沿

          ADC3_Handler.Init.ConversionDataManagement =        ADC_CONVERSIONDATA_DMA_CIRCULAR;  //规则通道的数据仅仅保存在DR寄存器里面
                ADC3_Handler.Init.BoostMode                                                     =        ENABLE;                                                        //BOOT模式关闭
                ADC3_Handler.Init.Overrun                                                                         =        ADC_OVR_DATA_OVERWRITTEN;                        //有新的数据的死后直接覆盖掉旧数据
                ADC3_Handler.Init.OversamplingMode                           =        DISABLE;                                        //过采样关闭
    HAL_ADC_Init(&ADC3_Handler);                                 //初始化         
                //配置通道PH4 ADC3_INP15
          ADC3_ChanConf.Channel                     =        ADC_CHANNEL_3;  //通道
    ADC3_ChanConf.Rank                                                       =        ADC_REGULAR_RANK_1;        //1个序列
    ADC3_ChanConf.SamplingTime                                                                =        ADC_SAMPLETIME_8CYCLES_5;  //采样时间      
                ADC3_ChanConf.SingleDiff                                                                        =        ADC_SINGLE_ENDED;                                  //单边采集                          
                ADC3_ChanConf.OffsetNumber                                                                =        ADC_OFFSET_NONE;                     
                ADC3_ChanConf.Offset                                                                                        =        0;   
    HAL_ADC_ConfigChannel(&ADC3_Handler,&ADC3_ChanConf);        //ADC的通道 15
        //看门狗配置
                AnalogWDGConfig.WatchdogNumber            = ADC_ANALOGWATCHDOG_1;
                AnalogWDGConfig.WatchdogMode                                                         = ADC_ANALOGWATCHDOG_ALL_REG;
                AnalogWDGConfig.Channel                                                                         = ADC_CHANNEL_3;
                AnalogWDGConfig.ITMode                                                                                 = ENABLE;
                AnalogWDGConfig.HighThreshold                                                 = 2000;
                AnalogWDGConfig.LowThreshold                                                  = 0;
                HAL_ADC_AnalogWDGConfig(&ADC1_Handler, &AnalogWDGConfig);
}

void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc){
                //*##- 1- Configure CLK###########/
                __HAL_RCC_GPIOF_CLK_ENABLE();                                                                        //开启GPIOH时钟
                __HAL_RCC_ADC3_CLK_ENABLE();                                                                         //使能ADC3时钟
                __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP);  //ADC外设时钟选择
                __HAL_RCC_DMA2_CLK_ENABLE();
                /*##- 2- Configure peripheral GPIO ############*/
                /* ADC3 Channel GPIO pin configuration */
                GPIO_Initure.Pin=GPIO_PIN_7;            //PH4
                GPIO_Initure.Mode=GPIO_MODE_ANALOG;     //模拟
                GPIO_Initure.Pull=GPIO_NOPULL;          //不带上下拉
                HAL_GPIO_Init(GPIOF,&GPIO_Initure);
                /*##- 3- Configure DMA ####################*/
                /*********************** Configure DMA parameters link ADC3 with DMA1_Stream2 ***/
                DmaHandle2.Instance                 = DMA2_Stream1;
                DmaHandle2.Init.Request             = DMA_REQUEST_ADC3;
                DmaHandle2.Init.Direction           = DMA_PERIPH_TO_MEMORY;
                DmaHandle2.Init.PeriphInc           = DMA_PINC_DISABLE;
                DmaHandle2.Init.MemInc              = DMA_MINC_ENABLE;
                DmaHandle2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
                DmaHandle2.Init.MemDataAlignment    = DMA_MDATAALIGN_HALFWORD;
                DmaHandle2.Init.Mode                = DMA_CIRCULAR;
                DmaHandle2.Init.Priority            = DMA_PRIORITY_MEDIUM;
                /* Deinitialize  & Initialize the DMA for new transfer */
                HAL_DMA_DeInit(&DmaHandle2);
                HAL_DMA_Init(&DmaHandle2);
                /* Associate the DMA handle 把结构体中的两个连到一起*/
                __HAL_LINKDMA(hadc, DMA_Handle, DmaHandle2);
                HAL_NVIC_SetPriority(ADC_IRQn, 0, 0);
                HAL_NVIC_EnableIRQ(ADC_IRQn);

}
将道理应该这个俩个ADC配置没什么区别,但是实际实验就是不好用。不知道是我哪里疏忽了。再就是有一个非常诡异的问题,假如先配置ADC3之后再配置ADC1的话ADC3还会不工作很诡异。。。。
希望能得到各位的指导十分感谢

adc.c

15.06 KB, 下载次数: 13

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106746
QQ
发表于 2019-3-13 00:10:50 | 显示全部楼层

回帖奖励 +10 个金币

程序里面两个问题,其它的问题你再找找。
1、这里是个bug,要改下
QQ截图20190313000521.jpg

原因看此贴:
STM32H7的DMA句柄关联到外设函数__HAL_LINKDMA注意事项
http://www.armbbs.cn/forum.php?m ... 1594&fromuid=58
(出处: 安富莱电子论坛)


2、你开了ADC中断NVIC,模拟看门狗中断使能,没找到你的ADC中断服务程序,是不是在其它文件里面。


ADC1,2,3做DMA时不支持DTCM,估计你的程序注意到了。
回复

使用道具 举报

4

主题

12

回帖

24

积分

新手上路

积分
24
 楼主| 发表于 2019-3-13 08:58:45 | 显示全部楼层
eric2013 发表于 2019-3-13 00:10
程序里面两个问题,其它的问题你再找找。
1、这里是个bug,要改下

先谢谢硬汉哥的指导,我研究一下。
回复

使用道具 举报

4

主题

12

回帖

24

积分

新手上路

积分
24
 楼主| 发表于 2019-3-13 11:53:09 | 显示全部楼层
经过硬汉哥的指导,果然不会出现配置先后导致adc不能工作的问题了,
但是还是依然会出现ADC3不能触发的问题。不过经过好长时间的研究发现问题是这样的:
adc3和adc12是完全独立的,所以在
HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)这个回调函数中应该把        
HAL_NVIC_SetPriority(ADC3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(ADC3_IRQn);
这样配置,而不是
HAL_NVIC_SetPriority(ADC_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(ADC_IRQn);
此外就是中断处理函数应该是
void ADC3_IRQHandler(void){
}
而不是
void ADC_IRQHandler(void){
}
知道了这个,之前的问题都可以解决了。总的来说还是自己学的不精,疏忽大意了还是要再谢谢硬汉哥
Snipaste_2019-03-13_11-48-59.png Snipaste_2019-03-13_11-47-26.png

回复

使用道具 举报

36

主题

2039

回帖

2147

积分

至尊会员

积分
2147
发表于 2019-3-13 11:54:14 | 显示全部楼层
Paprika 发表于 2019-3-13 11:53
经过硬汉哥的指导,果然不会出现配置先后导致adc不能工作的问题了,
但是还是依然会出现ADC3不能触发的问 ...

Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better.
回复

使用道具 举报

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

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-3 20:10 , Processed in 0.173805 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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