问答

汇集网友智慧,解决技术难题

21ic问答首页 - 芯片是dsPIC33CK32MP105, 我的ADC轉換結果永遠是0? 請問哪裡錯了?

单片机 MUC ADC dspic33

芯片是dsPIC33CK32MP105, 我的ADC轉換結果永遠是0? 請問哪裡錯了?

edison吴2023-10-07
Dear Supporter,
如提, 芯片是dsPIC33CK32MP105, 這個芯片我第一次使用ADC, 好複雜, 我看了Datashet一周了, 還是搞不定.請求協助.
我的基本設定: 使用ADC中斷, 使用腳位AN0腳(如附圖), 代碼是MCC產生的.已經執行了ADC相關的代碼了。
我在方案中加入了一個AD 0_ENABLE()的測試代碼(如下方的while(1)中, 我在DEBUG模式中等待中斷發生,然後在中斷中發現ADC的結果都是0,
請問哪裡錯了? 因為無法附上我的方案, 所以我只能提問.
    SYSTEM_Initialize();
    ADC1_Initialize();
    ADC1_Core0PowerEnable ( );
    ADC1_SharedCorePowerEnable ( );
    IO_Iintialize();                            /* Initial set I/O    */
    //======================================================================
    INTERRUPT_Initialize ();
    INTCON1bits.NSTDIS = 0;             /* Interrupt nesting enabled here */
    INTCON2bits.GIE = 1;                    /*INTERRUPT_GlobalEnable();=INTCON2bits.GIE = 1;*/

  while(1)
    {
      DISC=1;//放電
      d_ms(10);
      DISC=0;//充電到3.3v, 已經電阻1k焊接到3.3v
      ADC1_ChannelSelect(channel_AN0);//選擇ADC的輸入腳位
      ADC0_ENABLE();//開啟ADC
      d_ms(1000); //在這裡等待ADC中斷產生, 並且已經在中斷設置了暫停點, 也有成功產生了中斷, 但是讀值永遠是0。
    }     


adc1.c代碼
void __attribute__ ( ( __interrupt__ , auto_psv, weak ) ) _ADCAN0Interrupt ( void )
{
    uint16_t valchannel_AN0;
    //Read the ADC value from the ADCBUF
    valchannel_AN0 = ADCBUF0;
    if(ADC1_channel_AN0DefaultInterruptHandler)
    {
        ADC1_channel_AN0DefaultInterruptHandler(valchannel_AN0);
    }
   V_AN0=valchannel_AN0;  //中斷服務程序, 在這裡暫停檢查轉換的結果
    //clear the channel_AN0 interrupt flag
    IFS5bits.ADCAN0IF = 0;
}




//ADC的中斷服務程式
//================================================
void __attribute__ ( ( __interrupt__ , auto_psv, weak ) ) _ADCAN0Interrupt ( void )
{
    uint16_t valchannel_AN0;
    //Read the ADC value from the ADCBUF
    valchannel_AN0 = ADCBUF0;
    valchannel_AN0 = ADCBUF2;
    valchannel_AN0 = ADCBUF3;
    valchannel_AN0 = ADCBUF19;
    valchannel_AN0 = ADCBUF20;
    if(ADC1_channel_AN0DefaultInterruptHandler)
    {
        ADC1_channel_AN0DefaultInterruptHandler(valchannel_AN0);
    }
   V_AN0=valchannel_AN0;
    //clear the channel_AN0 interrupt flag
    IFS5bits.ADCAN0IF = 0;
}


回答 +关注 5
2822人浏览 7人回答问题 分享 举报
7 个回答
  • 問題找到了, ADC有轉換, 原因是芯片壞了, 可能我輸入的電壓曾經>5V過, 沒有保護.
    我重新更換了新的芯片後, 已經可以轉換了.
    但是還有個問ˋ題: 我的ADC有3個輸入, AN0, AN3,AN4
    AN0是CORE1, AN3,4是SHARE ADC, AN0已經可以轉換了, 請問我要如何換AN3及AN4? 在MCC的代碼中, 只看到使用channel_AN3, channel_AN4來換, 我試了, 轉換的值不對, 我用電表量電壓是0V, 但是轉換出來的值有2000多, 代碼使用跟您的相同, 也是mcc產生的. 請問哪裡錯了?
  • edison吴 发表于 2023-10-8 16:43
    我修改了代碼, 使用您的建議重新測試, 不使用ADC中斷的作法, AN0輸入, 電壓是0V及3.3V, 但是結果都是2300~2 ...

    ADC只需初始化一次即可。
    按你的代码,我在自己的dsPIC33CK64MC105上试过了,没有你遇到的现象。
    int main(void)
    {
        // initialize the device
        SYSTEM_Initialize();

        while (1)
        {
            // Add your application code
            ADC1_Enable();
            ADC1_ChannelSelect(channel_AN9);
            ADC1_SoftwareTriggerEnable();
            //Provide Delay
            for(i=0;i <1000;i++)
            {
            }
            ADC1_SoftwareTriggerDisable();
            while(!ADC1_IsConversionComplete(channel_AN9));
            conversion = ADC1_ConversionResultGet(channel_AN9);
            ADC1_Disable();
        }
        return 1;
    }

    你直接查看ADCBUF0寄存器里是什么值。
  • 我修改了代碼, 使用您的建議重新測試, 不使用ADC中斷的作法, AN0輸入, 電壓是0V及3.3V, 但是結果都是2300~2330左右變化的值, 代碼如下:
      while(1)
        {
          DISC=1;//使用MOS管放電
          d_ms(1);
          DISC=0; //電容充電
          d_ms(1);
          uint32_t conversion,i=0;
            ADC1_Initialize();
            ADC1_Enable();
            channel=channel_AN0;// AN0使用CORE0做ADC輸入腳
            ADC1_ChannelSelect(channel);
            ADC1_SoftwareTriggerEnable();
            //Provide Delay
            for(i=0;i <1000;i++)
            {   }
            ADC1_SoftwareTriggerDisable();
            while(!ADC1_IsConversionComplete(channel));
            conversion = ADC1_ConversionResultGet(channel);//斷點設在這裡, conversion的值永遠都是2000~2300的值, 不管我的AN0接0或是3.3V, 結果都是這樣?我把channel換成其他的輸入腳, 也是這樣, 為什麼?
            ADC1_Disable();
            conversion=0;
        }      
  • edison吴 发表于 2023-10-8 11:50
    你的代碼我上周已經試過了, 是MCC產生的代碼, 結果也是0, 就是因為這個結果不對, 所以我改成了使用中斷的方 ...

    你确定使用while(!ADC1_IsConversionComplete(channel)); 判断到ADC转换完成了吗?如果触发ADC后ADC转换完成,那说明ADC是工作的。结果为0,你再检查一下被采信号输入的硬件连接,还有参考电压的设置。
  • 另外, ADC1_ENABLE是在 ADC1_Initialize ()中已經開啟了, 所以不需要再重新開啟吧? 是嗎?

    void ADC1_Initialize (void)
    {
        // ADSIDL disabled; CVDEN disabled; ADON enabled;
        ADCON1L = (0x8000 & 0x7FFF); //Disabling ADON bit
        // FORM Integer; SHRRES 12-bit resolution;
        ADCON1H = 0x60;
        // SHRADCS 2; REFCIE disabled; SHREISEL Early interrupt is generated 1 TADCORE clock prior to data being ready; REFERCIE disabled; EIEN disabled;
        ADCON2L = 0x00;
        // CVDCAP enabled; SHRSAMC 0;
        ADCON2H = 0x1C00;
        // SWCTRG disabled; SHRSAMP enabled; SUSPEND disabled; SWLCTRG disabled; SUSPCIE disabled; CNVCHSEL AN0; REFSEL enabled;
        ADCON3L = 0xE200;
        // SHREN enabled; C1EN disabled; C0EN enabled; CLKDIV 2; CLKSEL FOSC/2;
        ADCON3H = (0x181 & 0xFF00); //Disabling C0EN, C1EN, C2EN, C3EN and SHREN bits
        // SAMC0EN disabled; SAMC1EN disabled;
        ADCON4L = 0x00;
        // C0CHS AN0; C1CHS AN1;
        ADCON4H = 0x00;
        // SIGN0 disabled; SIGN4 disabled; SIGN3 disabled; SIGN2 disabled; SIGN1 disabled; SIGN7 disabled; SIGN6 disabled; DIFF0 disabled; SIGN5 disabled; DIFF1 disabled; DIFF2 disabled; DIFF3 disabled; DIFF4 disabled; DIFF5 disabled; DIFF6 disabled; DIFF7 disabled;
        ADMOD0L = 0x00;
        // DIFF15 disabled; DIFF14 disabled; SIGN8 disabled; DIFF13 disabled; SIGN14 disabled; DIFF12 disabled; SIGN15 disabled; DIFF11 disabled; DIFF10 disabled; SIGN9 disabled; DIFF8 disabled; DIFF9 disabled; SIGN10 disabled; SIGN11 disabled; SIGN12 disabled; SIGN13 disabled;
        ADMOD0H = 0x00;
        // DIFF19 disabled; DIFF18 disabled; SIGN20 disabled; DIFF17 disabled; DIFF16 disabled; SIGN16 disabled; SIGN17 disabled; SIGN18 disabled; DIFF20 disabled; SIGN19 disabled;
        ADMOD1L = 0x00;
        // IE15 disabled; IE1 disabled; IE0 enabled; IE3 disabled; IE2 disabled; IE5 disabled; IE4 disabled; IE10 disabled; IE7 disabled; IE6 disabled; IE9 disabled; IE13 disabled; IE8 disabled; IE14 disabled; IE11 disabled; IE12 disabled;
        ADIEL = 0x01;
        // IE17 disabled; IE18 disabled; IE16 disabled; IE19 enabled; IE20 enabled;
        ADIEH = 0x18;
        // CMPEN10 disabled; CMPEN11 disabled; CMPEN6 disabled; CMPEN5 disabled; CMPEN4 disabled; CMPEN3 disabled; CMPEN2 disabled; CMPEN1 disabled; CMPEN0 disabled; CMPEN14 disabled; CMPEN9 disabled; CMPEN15 disabled; CMPEN8 disabled; CMPEN12 disabled; CMPEN7 disabled; CMPEN13 disabled;
        ADCMP0ENL = 0x00;
        // CMPEN10 disabled; CMPEN11 disabled; CMPEN6 disabled; CMPEN5 disabled; CMPEN4 disabled; CMPEN3 disabled; CMPEN2 disabled; CMPEN1 disabled; CMPEN0 disabled; CMPEN14 disabled; CMPEN9 disabled; CMPEN15 disabled; CMPEN8 disabled; CMPEN12 disabled; CMPEN7 disabled; CMPEN13 disabled;
        ADCMP1ENL = 0x00;
        // CMPEN10 disabled; CMPEN11 disabled; CMPEN6 disabled; CMPEN5 disabled; CMPEN4 disabled; CMPEN3 disabled; CMPEN2 disabled; CMPEN1 disabled; CMPEN0 disabled; CMPEN14 disabled; CMPEN9 disabled; CMPEN15 disabled; CMPEN8 disabled; CMPEN12 disabled; CMPEN7 disabled; CMPEN13 disabled;
        ADCMP2ENL = 0x00;
        // CMPEN10 disabled; CMPEN11 disabled; CMPEN6 disabled; CMPEN5 disabled; CMPEN4 disabled; CMPEN3 disabled; CMPEN2 disabled; CMPEN1 disabled; CMPEN0 disabled; CMPEN14 disabled; CMPEN9 disabled; CMPEN15 disabled; CMPEN8 disabled; CMPEN12 disabled; CMPEN7 disabled; CMPEN13 disabled;
        ADCMP3ENL = 0x00;
        // CMPEN20 disabled; CMPEN18 disabled; CMPEN19 disabled; CMPEN16 disabled; CMPEN17 disabled;
        ADCMP0ENH = 0x00;
        // CMPEN20 disabled; CMPEN18 disabled; CMPEN19 disabled; CMPEN16 disabled; CMPEN17 disabled;
        ADCMP1ENH = 0x00;
        // CMPEN20 disabled; CMPEN18 disabled; CMPEN19 disabled; CMPEN16 disabled; CMPEN17 disabled;
        ADCMP2ENH = 0x00;
        // CMPEN20 disabled; CMPEN18 disabled; CMPEN19 disabled; CMPEN16 disabled; CMPEN17 disabled;
        ADCMP3ENH = 0x00;
        // CMPLO 0;
        ADCMP0LO = 0x00;
        // CMPLO 0;
        ADCMP1LO = 0x00;
        // CMPLO 0;
        ADCMP2LO = 0x00;
        // CMPLO 0;
        ADCMP3LO = 0x00;
        // CMPHI 0;
        ADCMP0HI = 0x00;
        // CMPHI 0;
        ADCMP1HI = 0x00;
        // CMPHI 0;
        ADCMP2HI = 0x00;
        // CMPHI 0;
        ADCMP3HI = 0x00;
        // OVRSAM 4x; MODE Oversampling Mode; FLCHSEL AN0; IE disabled; FLEN disabled;
        ADFL0CON = 0x400;
        // OVRSAM 4x; MODE Oversampling Mode; FLCHSEL AN0; IE disabled; FLEN disabled;
        ADFL1CON = 0x400;
        // OVRSAM 4x; MODE Oversampling Mode; FLCHSEL AN0; IE disabled; FLEN disabled;
        ADFL2CON = 0x400;
        // OVRSAM 4x; MODE Oversampling Mode; FLCHSEL AN0; IE disabled; FLEN disabled;
        ADFL3CON = 0x400;
        // HIHI disabled; LOLO disabled; HILO disabled; BTWN disabled; LOHI disabled; CMPEN disabled; IE disabled;
        ADCMP0CON = 0x00;
        // HIHI disabled; LOLO disabled; HILO disabled; BTWN disabled; LOHI disabled; CMPEN disabled; IE disabled;
        ADCMP1CON = 0x00;
        // HIHI disabled; LOLO disabled; HILO disabled; BTWN disabled; LOHI disabled; CMPEN disabled; IE disabled;
        ADCMP2CON = 0x00;
        // HIHI disabled; LOLO disabled; HILO disabled; BTWN disabled; LOHI disabled; CMPEN disabled; IE disabled;
        ADCMP3CON = 0x00;
        // LVLEN9 disabled; LVLEN8 disabled; LVLEN11 disabled; LVLEN7 disabled; LVLEN10 disabled; LVLEN6 disabled; LVLEN13 disabled; LVLEN5 disabled; LVLEN12 disabled; LVLEN4 disabled; LVLEN15 disabled; LVLEN3 disabled; LVLEN14 disabled; LVLEN2 disabled; LVLEN1 disabled; LVLEN0 disabled;
        ADLVLTRGL = 0x00;
        // LVLEN20 disabled; LVLEN17 disabled; LVLEN16 disabled; LVLEN19 disabled; LVLEN18 disabled;
        ADLVLTRGH = 0x00;
        // SAMC 0;
        ADCORE0L = 0x00;
        // SAMC 0;
        ADCORE1L = 0x00;
        // RES 12-bit resolution; EISEL Early interrupt is generated 1 TADCORE clock prior to data being ready; ADCS 2;
        ADCORE0H = 0x300;
        // RES 12-bit resolution; EISEL Early interrupt is generated 1 TADCORE clock prior to data being ready; ADCS 2;
        ADCORE1H = 0x300;
        // EIEN9 disabled; EIEN7 disabled; EIEN8 disabled; EIEN5 disabled; EIEN6 disabled; EIEN3 disabled; EIEN4 disabled; EIEN1 disabled; EIEN2 disabled; EIEN13 disabled; EIEN0 disabled; EIEN12 disabled; EIEN11 disabled; EIEN10 disabled; EIEN15 disabled; EIEN14 disabled;
        ADEIEL = 0x00;
        // EIEN17 disabled; EIEN16 disabled; EIEN19 disabled; EIEN18 disabled; EIEN20 disabled;
        ADEIEH = 0x00;
        // C0CIE enabled; C1CIE enabled; SHRCIE enabled; WARMTIME 32768 Source Clock Periods;
        ADCON5H = (0xF83 & 0xF0FF); //Disabling WARMTIME bit
           
        //Assign Default Callbacks
        ADC1_SetCommonInterruptHandler(&ADC1_CallBack);
        ADC1_Setchannel_AN3InterruptHandler(&ADC1_channel_AN3_CallBack);
        ADC1_Setchannel_AN4InterruptHandler(&ADC1_channel_AN4_CallBack);
        ADC1_Setchannel_AN19InterruptHandler(&ADC1_channel_AN19_CallBack);
        ADC1_Setchannel_AN20InterruptHandler(&ADC1_channel_AN20_CallBack);
        ADC1_Setchannel_AN0InterruptHandler(&ADC1_channel_AN0_CallBack);
       
        // Clearing channel_AN19 interrupt flag.
        IFS6bits.ADCAN19IF = 0;
        // Enabling channel_AN19 interrupt.
        IEC6bits.ADCAN19IE = 1;
        // Clearing channel_AN20 interrupt flag.
        IFS6bits.ADCAN20IF = 0;
        // Enabling channel_AN20 interrupt.
        IEC6bits.ADCAN20IE = 1;
        // Clearing channel_AN0 interrupt flag.
        IFS5bits.ADCAN0IF = 0;
        // Enabling channel_AN0 interrupt.
        IEC5bits.ADCAN0IE = 1;

        // Setting WARMTIME bit
        ADCON5Hbits.WARMTIME = 0xF;
        // Enabling ADC Module
        ADCON1Lbits.ADON = 0x1;
        // Enabling Power for the Shared Core
        ADC1_SharedCorePowerEnable();
        // Enabling Power for Core0
        ADC1_Core0PowerEnable();

        //TRGSRC0 Common Software Trigger; TRGSRC1 None;
        ADTRIG0L = 0x01;
        //TRGSRC3 Common Software Trigger; TRGSRC2 None;
        ADTRIG0H = 0x100;
        //TRGSRC4 Common Software Trigger; TRGSRC5 None;
        ADTRIG1L = 0x01;
        //TRGSRC6 None; TRGSRC7 None;
        ADTRIG1H = 0x00;
        //TRGSRC8 None; TRGSRC9 None;
        ADTRIG2L = 0x00;
        //TRGSRC11 None; TRGSRC10 None;
        ADTRIG2H = 0x00;
        //TRGSRC13 None; TRGSRC12 None;
        ADTRIG3L = 0x00;
        //TRGSRC15 None; TRGSRC14 None;
        ADTRIG3H = 0x00;
        //TRGSRC17 None; TRGSRC16 None;
        ADTRIG4L = 0x00;
        //TRGSRC19 Common Software Trigger; TRGSRC18 None;
        ADTRIG4H = 0x100;
        //TRGSRC20 Common Software Trigger;
        ADTRIG5L = 0x01;
    }
  • 你的代碼我上周已經試過了, 是MCC產生的代碼, 結果也是0, 就是因為這個結果不對, 所以我改成了使用中斷的方式.ADC0_ENABLE()是打開ADC中斷
    void    ADC0_ENABLE(void)
    {
        IEC5bits.ADCAN0IE = 1;              
        IFS5bits.ADCAN0IF = 1;     
    }
  • 你在While(1)里面调用的ADC0_ENABLE();是什么?不应该是ADC1_ENABLE();吗?

    你是选择用什么触发源来启动ADC采样转换的?如果是软件触发,没有看到你软件设置触发位的语句。如果是其他外设触发,请确认作为触发源的外设是否产生触发条件来触发ADC。

    按你说的情况,个人判断应该不会产生ADC中断。你说能进ADC中断,但读结果都是0,这点从逻辑上解释不通。

    一般用软件触发ACD的操作流程如下,你可以先用简单的查询法测试一下。
            ADC1_Initialize();
            ADC1_Enable();
            ADC1_ChannelSelect(channel);
            ADC1_SoftwareTriggerEnable();
            while(!ADC1_IsConversionComplete(channel));
            conversion = ADC1_ConversionResultGet(channel);

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