跳转至内容
  • 版块
  • 最新
  • 标签
  • 热门
折叠
品牌标识

YunTu Forum

YTMicro.com
  1. 主页
  2. Discussion & Question
  3. YTM32B1M系列
  4. YTM32B1ME05 ADC不稳问题

YTM32B1ME05 ADC不稳问题

已定时 已固定 已锁定 已移动 已解决 YTM32B1M系列
16 帖子 4 发布者 3.4k 浏览
  • 从旧到新
  • 从新到旧
  • 最多赞同
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • OliverChenO 离线
    OliverChenO 离线
    OliverChen
    写于 最后由 编辑
    #1

    问题描述

    最近在使用YTM32B1ME05的ADC模块时时遇到了一个问题,使用了ADC0和ADC1两个模块,固定通过eTMR的一个通道触发采集,周期大概在1ms,测试发现采集到的AD值会一直跳动,排查发现和切换TMU和ADC_CHSELx的配置有关系,请问下这里有什么需要注意和的地方吗?如何解决?


    原理图 VREF:

    5d40928c-e247-4a91-b65f-c6f25f61dab7-image.png

    不切换配置

    void user_adc_start_conversion(void)
    {
    	tmu_target_module_t targetModule = TMU_TARGET_MODULE_ADC0_EXT_TRIG;
    	
    	/* Configure ADC channel selection based on PWM index */
    	if(adcInst[UserAdcParams.pwmIndex][0] == ADC1_INST) {
    //		ADC1->CHSEL[0] = adcInst[UserAdcParams.pwmIndex][1];
    //        ADC1->CHSEL[1] = adcInst[UserAdcParams.pwmIndex][1];
    //        ADC1->CHSEL[2] = adcInst[UserAdcParams.pwmIndex][1];
    //        ADC1->CHSEL[3] = adcInst[UserAdcParams.pwmIndex][1];
    //		targetModule = TMU_TARGET_MODULE_ADC1_EXT_TRIG;
    	} else {
    //		ADC0->CHSEL[0] = adcInst[UserAdcParams.pwmIndex][1];
    //        ADC0->CHSEL[1] = adcInst[UserAdcParams.pwmIndex][1];
    //        ADC0->CHSEL[2] = adcInst[UserAdcParams.pwmIndex][1];
    //        ADC0->CHSEL[3] = adcInst[UserAdcParams.pwmIndex][1];
    //		targetModule = TMU_TARGET_MODULE_ADC0_EXT_TRIG;
    	}
    	
    	/* Update TMU target module directly without reinitializing entire TMU
    	 * This is more efficient than TMU_DRV_Init which resets all target modules
    	 */
        TMU->MUX[3] = 0;
        TMU->MUX[4] = 0;
        TMU_SetTrigSourceForTargetModule(TMU, TMU_TRIG_SOURCE_eTMR0_EXT_TRIG, targetModule);
    }
    

    结果如图,基本在2938~2948之内,波动比较小
    12ce6b9a-cd59-44af-be94-d96c91fa69c4-image.png

    周期切换TMU

    void user_adc_start_conversion(void)
    {
    	tmu_target_module_t targetModule = TMU_TARGET_MODULE_ADC0_EXT_TRIG;
    	
    	/* Configure ADC channel selection based on PWM index */
    	if(adcInst[UserAdcParams.pwmIndex][0] == ADC1_INST) {
    //		ADC1->CHSEL[0] = adcInst[UserAdcParams.pwmIndex][1];
    //        ADC1->CHSEL[1] = adcInst[UserAdcParams.pwmIndex][1];
    //        ADC1->CHSEL[2] = adcInst[UserAdcParams.pwmIndex][1];
    //        ADC1->CHSEL[3] = adcInst[UserAdcParams.pwmIndex][1];
    		targetModule = TMU_TARGET_MODULE_ADC1_EXT_TRIG;
    	} else {
    //		ADC0->CHSEL[0] = adcInst[UserAdcParams.pwmIndex][1];
    //        ADC0->CHSEL[1] = adcInst[UserAdcParams.pwmIndex][1];
    //        ADC0->CHSEL[2] = adcInst[UserAdcParams.pwmIndex][1];
    //        ADC0->CHSEL[3] = adcInst[UserAdcParams.pwmIndex][1];
    		targetModule = TMU_TARGET_MODULE_ADC0_EXT_TRIG;
    	}
    	
    	/* Update TMU target module directly without reinitializing entire TMU
    	 * This is more efficient than TMU_DRV_Init which resets all target modules
    	 */
        TMU->MUX[3] = 0;
        TMU->MUX[4] = 0;
        TMU_SetTrigSourceForTargetModule(TMU, TMU_TRIG_SOURCE_eTMR0_EXT_TRIG, targetModule);
    }
    
    

    结果如图
    ca3aea5b-fc44-4907-95d7-69118442a9b3-image.png

    周期切换ADC通道

    注意通道0和1不切换,只切换2和3

    void user_adc_start_conversion(void)
    {
    	tmu_target_module_t targetModule = TMU_TARGET_MODULE_ADC1_EXT_TRIG;
    	
    	/* Configure ADC channel selection based on PWM index */
    	if(adcInst[UserAdcParams.pwmIndex][0] == ADC1_INST) {
    //		ADC1->CHSEL[0] = adcInst[UserAdcParams.pwmIndex][1];
    //        ADC1->CHSEL[1] = adcInst[UserAdcParams.pwmIndex][1];
            ADC1->CHSEL[2] = adcInst[UserAdcParams.pwmIndex][1];
            ADC1->CHSEL[3] = adcInst[UserAdcParams.pwmIndex][1];
    		targetModule = TMU_TARGET_MODULE_ADC1_EXT_TRIG;
    	} else {
    //		ADC0->CHSEL[0] = adcInst[UserAdcParams.pwmIndex][1];
    //        ADC0->CHSEL[1] = adcInst[UserAdcParams.pwmIndex][1];
            ADC0->CHSEL[2] = adcInst[UserAdcParams.pwmIndex][1];
            ADC0->CHSEL[3] = adcInst[UserAdcParams.pwmIndex][1];
    		targetModule = TMU_TARGET_MODULE_ADC0_EXT_TRIG;
    	}
    	
    	/* Update TMU target module directly without reinitializing entire TMU
    	 * This is more efficient than TMU_DRV_Init which resets all target modules
    	 */
        TMU->MUX[3] = 0;
        TMU->MUX[4] = 0;
        TMU_SetTrigSourceForTargetModule(TMU, TMU_TRIG_SOURCE_eTMR0_EXT_TRIG, targetModule);
    }
    
    

    结果如图,抖动的比较厉害
    e9dba9d3-df63-48a0-af25-c6f373d1a629-image.png

    用到的函数

    /**
     * @brief Print latest ADC samples in JustFloat-like format
     */
    void user_adc_print_samples(void)
    {
    	uint8_t frame[4U * sizeof(float) + 4U];
    	uint32_t offset = 0U;
        if(!sendFlag) {
            return;
        }
        sendFlag = false;
    	for(uint8_t idx = 0U; idx < 4U; idx++) {
    		float f = (float)adcSapleResult[idx];
    		(void)memcpy(&frame[offset], &f, sizeof(float));
    		offset += (uint32_t)sizeof(float);
    	}
    
    	(void)memcpy(&frame[offset], c_justfloat_tail, sizeof(c_justfloat_tail));
    	offset += (uint32_t)sizeof(c_justfloat_tail);
    
    	/* Send with LINFlexD UART polling, instance = 2 */
    	LINFlexD_UART_DRV_SendDataPolling(2U, frame, offset);
    }
    
    /**
     * @brief ADC0 interrupt handler
     * @return none
     */
    void ADC0_IRQHandler(void)
    {
        ADC_DRV_ClearEoseqFlagCmd(0);
        adcSapleResult[0] = ADC_DRV_ReadFIFO(0);
        adcSapleResult[1] = ADC_DRV_ReadFIFO(0);
        adcSapleResult[2] = ADC_DRV_ReadFIFO(0);
        adcSapleResult[3] = ADC_DRV_ReadFIFO(0);
        adcSapleSum = adcSapleResult[0] + adcSapleResult[1] + adcSapleResult[2] + adcSapleResult[3];
        updateAdcResult(adcSapleSum >> 2);
        UserAdcParams.boardSupplyVolt.rawAdcValue = ADC_DRV_ReadFIFO(0);
        UserAdcParams.ledSupplyVolt.rawAdcValue = ADC_DRV_ReadFIFO(0);
    }
    
    /**
     * @brief ADC1 interrupt handler
     * @return none
     */
    void ADC1_IRQHandler(void)
    {
        ADC_DRV_ClearEoseqFlagCmd(1);
        adcSapleResult[0] = ADC_DRV_ReadFIFO(1);
        adcSapleResult[1] = ADC_DRV_ReadFIFO(1);
        adcSapleResult[2] = ADC_DRV_ReadFIFO(1);
        adcSapleResult[3] = ADC_DRV_ReadFIFO(1);
        adcSapleSum = adcSapleResult[0] + adcSapleResult[1] + adcSapleResult[2] + adcSapleResult[3];
        updateAdcResult(adcSapleSum >> 2);
        sendFlag = true;
    }
    
    
    1 条回复 最后回复
    0
    • OliverChenO 离线
      OliverChenO 离线
      OliverChen
      在 回复了 Kirk 最后由 编辑
      #8

      @quanfeng 忘记说了,下午重新验证了下,发现并没有通道错位情况,数据还是一样波动比较大。

      代码如下:

      /**
       * @brief ADC0 interrupt handler
       * @return none
       */
      void ADC0_IRQHandler(void)
      {
          uint32_t adcSampleSum = 0U;
          uint8_t expectedChannel = adcInst[UserAdcParams.pwmIndex][1];
          uint8_t validCnt = 0U;
      
          ADC_DRV_ClearEoseqFlagCmd(0);
          adcSampleSum = 0U;
      
      	for(uint8_t readCnt = 0U; readCnt < 8U; readCnt++) {
              adcSampleResult[readCnt].u32DualWord = ADC0->FIFO;
              if(readCnt < 4U)
              {
                  if(adcSampleResult[readCnt].parts.u16ChnIndex == expectedChannel) {
                      adcSampleSum += adcSampleResult[readCnt].parts.u16ChnResult;
                      validCnt++;
                  } else {
                      misMatchFlag = true;
                  }
              }
      
          }
      
          if (validCnt > 0U) {
              updateAdcResult((uint16_t)(adcSampleSum / validCnt));
          } else {
              updateAdcResult(0x8000);
          }
      
          
          if(adcSampleResult[4].parts.u16ChnIndex == ADC_INPUTCHAN_EXT17) {
              UserAdcParams.boardSupplyVolt.rawAdcValue = adcSampleResult[4].parts.u16ChnResult;
          }else{
              misMatchFlag = true;
          }
          if(adcSampleResult[5].parts.u16ChnIndex == ADC_INPUTCHAN_EXT18) {
              UserAdcParams.ledSupplyVolt.rawAdcValue = adcSampleResult[5].parts.u16ChnResult;
          }else{
              misMatchFlag = true;
          }
      }
      
      /**
       * @brief ADC1 interrupt handler
       * @return none
       */
      void ADC1_IRQHandler(void)
      {
          uint32_t adcSampleSum = 0U;
          uint8_t expectedChannel = adcInst[UserAdcParams.pwmIndex][1];
          uint8_t validCnt = 0U;
      
          ADC_DRV_ClearEoseqFlagCmd(1);
          for(uint8_t readCnt = 0U; readCnt < 8U; readCnt++) {
              adcSampleResult[readCnt].u32DualWord = ADC1->FIFO;
              if(readCnt < 4U){
                  if(adcSampleResult[readCnt].parts.u16ChnIndex == expectedChannel) {
                      adcSampleSum += adcSampleResult[readCnt].parts.u16ChnResult;
                      validCnt++;
                  } else {
                      misMatchFlag = true;
                  } 
              }
          }
          if (validCnt > 0U) {
              updateAdcResult((uint16_t)(adcSampleSum / validCnt));
          } else {
              updateAdcResult(0x8000);
          }
      }
      
      

      进不到misMatchFlag 为true情况,采集到的数据波动比较大。
      b128dfb3-a1d3-4a43-bd30-8404cc65697f-image.png

      1 条回复 最后回复
      0
      • WRW 离线
        WRW 离线
        WR YunTu
        写于 最后由 编辑
        #2

        你每次读取adc的fifo值时,读取一下adc采集的通道号,看看是不是采集通道错乱了,程序可以这么写
        image.png

        OliverChenO 2 条回复 最后回复
        0
        • OliverChenO 离线
          OliverChenO 离线
          OliverChen
          在 回复了 WR 最后由 编辑
          #3

          WR 这样试了,还是没什么效果

          1 条回复 最后回复
          0
          • OliverChenO 离线
            OliverChenO 离线
            OliverChen
            在 回复了 WR 最后由 编辑
            #4

            WR 如果有错位的情况,直接丢弃吗?为啥会出现这种情况?

            1 条回复 最后回复
            0
            • KirkK 离线
              KirkK 离线
              Kirk YunTu
              写于 最后由 编辑
              #5

              您可以在官网上下载 ME05 的应用审查清单,有 ADC FIFO 错乱的说明和规避方案

              9935bfff-e812-4ad3-8747-6d0f27a05214-image.png

              image.png

              ADC FIFO 错乱帖子链接如下:
              https://forum.ytmicro.com/topic/1058/md1_adc测试到fifo错位问题

              OliverChenO 2 条回复 最后回复
              0
              • OliverChenO 离线
                OliverChenO 离线
                OliverChen
                在 回复了 Kirk 最后由 编辑
                #6

                @quanfeng 我使用的硬件触发,然后只打开了EOS中断,在中断中执行,也会出现这种情况吗?

                1 条回复 最后回复
                0
                • OliverChenO 离线
                  OliverChenO 离线
                  OliverChen
                  写于 最后由 编辑
                  #7

                  在ADC中断中每次读8次FIFO可以解决

                  1 条回复 最后回复
                  0
                  • OliverChenO 离线
                    OliverChenO 离线
                    OliverChen
                    在 回复了 Kirk 最后由 编辑
                    #8

                    @quanfeng 忘记说了,下午重新验证了下,发现并没有通道错位情况,数据还是一样波动比较大。

                    代码如下:

                    /**
                     * @brief ADC0 interrupt handler
                     * @return none
                     */
                    void ADC0_IRQHandler(void)
                    {
                        uint32_t adcSampleSum = 0U;
                        uint8_t expectedChannel = adcInst[UserAdcParams.pwmIndex][1];
                        uint8_t validCnt = 0U;
                    
                        ADC_DRV_ClearEoseqFlagCmd(0);
                        adcSampleSum = 0U;
                    
                    	for(uint8_t readCnt = 0U; readCnt < 8U; readCnt++) {
                            adcSampleResult[readCnt].u32DualWord = ADC0->FIFO;
                            if(readCnt < 4U)
                            {
                                if(adcSampleResult[readCnt].parts.u16ChnIndex == expectedChannel) {
                                    adcSampleSum += adcSampleResult[readCnt].parts.u16ChnResult;
                                    validCnt++;
                                } else {
                                    misMatchFlag = true;
                                }
                            }
                    
                        }
                    
                        if (validCnt > 0U) {
                            updateAdcResult((uint16_t)(adcSampleSum / validCnt));
                        } else {
                            updateAdcResult(0x8000);
                        }
                    
                        
                        if(adcSampleResult[4].parts.u16ChnIndex == ADC_INPUTCHAN_EXT17) {
                            UserAdcParams.boardSupplyVolt.rawAdcValue = adcSampleResult[4].parts.u16ChnResult;
                        }else{
                            misMatchFlag = true;
                        }
                        if(adcSampleResult[5].parts.u16ChnIndex == ADC_INPUTCHAN_EXT18) {
                            UserAdcParams.ledSupplyVolt.rawAdcValue = adcSampleResult[5].parts.u16ChnResult;
                        }else{
                            misMatchFlag = true;
                        }
                    }
                    
                    /**
                     * @brief ADC1 interrupt handler
                     * @return none
                     */
                    void ADC1_IRQHandler(void)
                    {
                        uint32_t adcSampleSum = 0U;
                        uint8_t expectedChannel = adcInst[UserAdcParams.pwmIndex][1];
                        uint8_t validCnt = 0U;
                    
                        ADC_DRV_ClearEoseqFlagCmd(1);
                        for(uint8_t readCnt = 0U; readCnt < 8U; readCnt++) {
                            adcSampleResult[readCnt].u32DualWord = ADC1->FIFO;
                            if(readCnt < 4U){
                                if(adcSampleResult[readCnt].parts.u16ChnIndex == expectedChannel) {
                                    adcSampleSum += adcSampleResult[readCnt].parts.u16ChnResult;
                                    validCnt++;
                                } else {
                                    misMatchFlag = true;
                                } 
                            }
                        }
                        if (validCnt > 0U) {
                            updateAdcResult((uint16_t)(adcSampleSum / validCnt));
                        } else {
                            updateAdcResult(0x8000);
                        }
                    }
                    
                    

                    进不到misMatchFlag 为true情况,采集到的数据波动比较大。
                    b128dfb3-a1d3-4a43-bd30-8404cc65697f-image.png

                    1 条回复 最后回复
                    0
                    • DigaD 离线
                      DigaD 离线
                      Diga
                      写于 最后由 编辑
                      #9

                      ADC 的配置是什么,贴一个

                      OliverChenO 1 条回复 最后回复
                      0
                      • OliverChenO 离线
                        OliverChenO 离线
                        OliverChen
                        在 回复了 Diga 最后由 编辑
                        #10

                        Diga

                        ADC0

                        4fc6015a-c393-44d1-ae03-ea88a09ca89a-image.png

                        ADC1

                        fd74665d-107a-4261-bf91-188362449f62-image.png

                        1 条回复 最后回复
                        0
                        • DigaD 离线
                          DigaD 离线
                          Diga
                          写于 最后由 编辑
                          #11

                          先这样试试,你把俩序列的所有通道配成同一个,然后切换配置的时候不要修改通道,只切换 Trigger,看一下结果

                          OliverChenO 1 条回复 最后回复
                          0
                          • OliverChenO 离线
                            OliverChenO 离线
                            OliverChen
                            在 回复了 Diga 最后由 编辑
                            #12

                            Diga

                            ADC0配置:

                            272a9caa-ba0c-4dec-83e0-d88d87a64219-image.png

                            ADC1配置

                            5e668428-4f6e-483d-9d8c-bdad26673548-image.png


                            代码

                            void user_adc_start_conversion(void)
                            {
                            	tmu_target_module_t targetModule = TMU_TARGET_MODULE_ADC1_EXT_TRIG;
                            	
                            	/* Configure ADC channel selection based on PWM index */
                            	if(adcInst[UserAdcParams.pwmIndex][0] == ADC1_INST) {
                            //		ADC1->CHSEL[0] = adcInst[UserAdcParams.pwmIndex][1];
                            //        ADC1->CHSEL[1] = adcInst[UserAdcParams.pwmIndex][1];
                            //        ADC1->CHSEL[2] = adcInst[UserAdcParams.pwmIndex][1];
                            //        ADC1->CHSEL[3] = adcInst[UserAdcParams.pwmIndex][1];
                            		targetModule = TMU_TARGET_MODULE_ADC1_EXT_TRIG;
                            	} else {
                            //		ADC0->CHSEL[0] = adcInst[UserAdcParams.pwmIndex][1];
                            //        ADC0->CHSEL[1] = adcInst[UserAdcParams.pwmIndex][1];
                            //        ADC0->CHSEL[2] = adcInst[UserAdcParams.pwmIndex][1];
                            //        ADC0->CHSEL[3] = adcInst[UserAdcParams.pwmIndex][1];
                            		targetModule = TMU_TARGET_MODULE_ADC0_EXT_TRIG;
                            	}
                            	
                            	/* Update TMU target module directly without reinitializing entire TMU
                            	 * This is more efficient than TMU_DRV_Init which resets all target modules
                            	 */
                                TMU->MUX[3] = 0;
                                TMU->MUX[4] = 0;
                                TMU_SetTrigSourceForTargetModule(TMU, TMU_TRIG_SOURCE_eTMR0_EXT_TRIG, targetModule);
                            }
                            
                            

                            结果如下
                            a69d9aba-5bfe-4fd4-9713-74c0a8eb7de2-image.png

                            1 条回复 最后回复
                            0
                            • DigaD 离线
                              DigaD 离线
                              Diga
                              写于 最后由 编辑
                              #13

                              你的这个结果是什么意思?ADC0 的 CH11?or ADC1 的 CH17?或者两者都有?
                              另外这两个通道的理想结果应该是多少

                              OliverChenO 1 条回复 最后回复
                              0
                              • OliverChenO 离线
                                OliverChenO 离线
                                OliverChen
                                在 回复了 Diga 最后由 编辑
                                #14

                                Diga 不好意思,两者都有,所以看起来波动很大,这里我重新测了下,不切换的情况下很稳定上边这个是ADC1下边是ADC0,基本误差不差10

                                40b7e59b-6adf-4cb5-9c15-e1de134f3104-image.png

                                1 条回复 最后回复
                                0
                                • DigaD 离线
                                  DigaD 离线
                                  Diga
                                  写于 最后由 编辑
                                  #15

                                  看起来你上一张图的下限 2900 应该是 ADC0 CH11 的结果,上限 3281 应该是 ADC1 CH17 的结果。那这两个通道的电压不一样,采样的结果不一样,不是一件正常的事嘛?

                                  要证明在跳,得把两个结果区分出来

                                  OliverChenO 1 条回复 最后回复
                                  0
                                  • OliverChenO 离线
                                    OliverChenO 离线
                                    OliverChen
                                    在 回复了 Diga 最后由 编辑
                                    #16

                                    Diga 理解你的意思了,我再试试

                                    1 条回复 最后回复
                                    0
                                    • FrankieF Frankie 将这个主题转为问答主题,在
                                    • FrankieF Frankie 将这个主题标记为已解决,在

                                  • 云途开发生态介绍

                                    快速上手云途开发生态

                                  • 云途论坛规则/Yuntu Forum Rules

                                    发帖前请查看

                                  • YT CONFIG TOOL调查问卷

                                    帮助改进和优化YT CONFIG TOOL,有机会抽取YTM32B1ME0 EVB哦...

                                  • can
                                    28
                                    demo
                                    23
                                    uds
                                    14
                                    lin stack
                                    13
                                    md14
                                    6
                                    yt-link
                                    6
                                    fbl
                                    5
                                    adc模块
                                    4
                                    Online Users
                                    • 登录

                                    • 登录或注册以进行搜索。
                                    • 第一个帖子
                                      最后一个帖子
                                    0
                                    • 版块
                                    • 最新
                                    • 标签
                                    • 热门