[技术问答] 新塘M451单片机ADC采集输出不能为0

[复制链接]
 楼主| delven 发表于 2017-2-17 15:52 | 显示全部楼层 |阅读模式
各位大侠,最近用新塘M451做ADC采集,在IO口接地时ADC输出最小只能为9,采集不能为0,不知是何原因,一下是我初始化ADC的代码,各位大侠帮忙看看。
//时钟配置
/* EADC clock source is 72MHz, set divider to 8, ADC clock is 72/6 MHz */
CLK->CLKDIV0  = ((CLK->CLKDIV0 & ~CLK_CLKDIV0_EADCDIV_Msk) | (((6) - 1) << CLK_CLKDIV0_EADCDIV_Pos));

//I/O口配置
SYS->GPB_MFPL &= ~(SYS_GPB_MFPL_PB1MFP_Msk | SYS_GPB_MFPL_PB2MFP_Msk | SYS_GPB_MFPL_PB3MFP_Msk | SYS_GPB_MFPL_PB4MFP_Msk);
SYS->GPB_MFPL |= SYS_GPB_MFPL_PB1MFP_EADC_CH1 | SYS_GPB_MFPL_PB2MFP_EADC_CH2 | SYS_GPB_MFPL_PB3MFP_EADC_CH3 | SYS_GPB_MFPL_PB4MFP_EADC_CH4;
GPIO_DISABLE_DIGITAL_PATH(PB,0x1F);

//ADC配置
void ADC_Init(void)
{       
        /* Reset EADC module */
    SYS->IPRST1 |= SYS_IPRST1_EADCRST_Msk ;
    SYS->IPRST1 &= ~SYS_IPRST1_EADCRST_Msk ;

    EADC->CTL &= ~(EADC_CTL_DIFFEN_Msk);

    EADC->CTL |= (EADC_CTL_DIFFEN_SINGLE_END | EADC_CTL_ADCEN_Msk);

    EADC->CTL &= ~EADC_CTL_SMPTSEL_Msk;

    EADC->CTL |= (6 - 1) << EADC_CTL_SMPTSEL_Pos;//(6 - 1) << EADC_CTL_SMPTSEL_Pos;

       
        EADC->SCTL[4] &= ~(EADC_SCTL_TRGSEL_Msk | EADC_SCTL_CHSEL_Msk);
    EADC->SCTL[4] |= (EADC_SOFTWARE_TRIGGER | EADC_SCTL_CHSEL(4));

        EADC->SCTL[3] &= ~(EADC_SCTL_TRGSEL_Msk | EADC_SCTL_CHSEL_Msk);
    EADC->SCTL[3] |= (EADC_SOFTWARE_TRIGGER | EADC_SCTL_CHSEL(3));

        EADC->SCTL[2] &= ~(EADC_SCTL_TRGSEL_Msk | EADC_SCTL_CHSEL_Msk);
    EADC->SCTL[2] |= (EADC_SOFTWARE_TRIGGER | EADC_SCTL_CHSEL(2));

        EADC->SCTL[0] &= ~(EADC_SCTL_TRGSEL_Msk | EADC_SCTL_CHSEL_Msk);
    EADC->SCTL[0] |= (EADC_SOFTWARE_TRIGGER | EADC_SCTL_CHSEL(1));

}
 楼主| delven 发表于 2017-2-17 15:56 | 显示全部楼层
更加奇怪的是通道1的ADC在外部加了1K电阻接地,这个IO口测量时有50mV电压,导致采样输出在70左右,这个50mV电压不知怎么消除。
wahahaheihei 发表于 2017-2-17 20:24 | 显示全部楼层
跑官方例程序试试看。
wahahaheihei 发表于 2017-2-17 20:35 | 显示全部楼层
  1. /**************************************************************************//**
  2. * [url=home.php?mod=space&uid=288409]@file[/url]     main.c
  3. * [url=home.php?mod=space&uid=895143]@version[/url]  V3.00
  4. * $Revision: 6 $
  5. * $Date: 15/09/02 10:04a $
  6. * @brief
  7. *           Monitor the conversion result of channel 2 by the digital compare function.
  8. *
  9. * @note
  10. * Copyright (C) 2013~2015 Nuvoton Technology Corp. All rights reserved.
  11. *
  12. ******************************************************************************/
  13. #include "stdio.h"
  14. #include "M451Series.h"

  15. #define PLLCTL_SETTING      CLK_PLLCTL_72MHz_HXT
  16. #define PLL_CLOCK           72000000

  17. /*---------------------------------------------------------------------------------------------------------*/
  18. /* Define global variables and constants                                                                   */
  19. /*---------------------------------------------------------------------------------------------------------*/
  20. volatile uint32_t g_u32AdcCmp0IntFlag;
  21. volatile uint32_t g_u32AdcCmp1IntFlag;

  22. /*---------------------------------------------------------------------------------------------------------*/
  23. /* Define functions prototype                                                                              */
  24. /*---------------------------------------------------------------------------------------------------------*/
  25. int32_t main(void);
  26. void EADC_FunctionTest(void);


  27. void SYS_Init(void)
  28. {

  29.     /*---------------------------------------------------------------------------------------------------------*/
  30.     /* Init System Clock                                                                                       */
  31.     /*---------------------------------------------------------------------------------------------------------*/

  32.     /* Enable HIRC clock (Internal RC 22.1184MHz) */
  33.     CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);

  34.     /* Wait for HIRC clock ready */
  35.     CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);

  36.     /* Select HCLK clock source as HIRC and and HCLK source divider as 1 */
  37.     CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HIRC, CLK_CLKDIV0_HCLK(1));

  38.     /* Set PLL to Power-down mode and PLLSTB bit in CLK_STATUS register will be cleared by hardware.*/
  39.     CLK_DisablePLL();

  40.     /* Enable HXT clock (external XTAL 12MHz) */
  41.     CLK_EnableXtalRC(CLK_PWRCTL_HXTEN_Msk);

  42.     /* Wait for HXT clock ready */
  43.     CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk);

  44.     /* Set core clock as PLL_CLOCK from PLL */
  45.     CLK_SetCoreClock(PLL_CLOCK);

  46.     /* Enable UART module clock */
  47.     CLK_EnableModuleClock(UART0_MODULE);

  48.     /* Select UART module clock source as HXT and UART module clock divider as 1 */
  49.     CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UARTSEL_HXT, CLK_CLKDIV0_UART(1));

  50.     /* Enable EADC module clock */
  51.     CLK_EnableModuleClock(EADC_MODULE);

  52.     /* EADC clock source is 72MHz, set divider to 8, ADC clock is 72/8 MHz */
  53.     CLK_SetModuleClock(EADC_MODULE, 0, CLK_CLKDIV0_EADC(8));

  54.     /*---------------------------------------------------------------------------------------------------------*/
  55.     /* Init I/O Multi-function                                                                                 */
  56.     /*---------------------------------------------------------------------------------------------------------*/

  57.     /* Set PD multi-function pins for UART0 RXD and TXD */
  58.     SYS->GPD_MFPL &= ~(SYS_GPD_MFPL_PD0MFP_Msk | SYS_GPD_MFPL_PD1MFP_Msk);
  59.     SYS->GPD_MFPL |= (SYS_GPD_MFPL_PD0MFP_UART0_RXD | SYS_GPD_MFPL_PD1MFP_UART0_TXD);

  60.     /* Configure the GPB0 - GPB3 ADC analog input pins.  */
  61.     SYS->GPB_MFPL &= ~(SYS_GPB_MFPL_PB0MFP_Msk | SYS_GPB_MFPL_PB1MFP_Msk |
  62.                        SYS_GPB_MFPL_PB2MFP_Msk | SYS_GPB_MFPL_PB3MFP_Msk);
  63.     SYS->GPB_MFPL |= (SYS_GPB_MFPL_PB0MFP_EADC_CH0 | SYS_GPB_MFPL_PB1MFP_EADC_CH1 |
  64.                       SYS_GPB_MFPL_PB2MFP_EADC_CH2 | SYS_GPB_MFPL_PB3MFP_EADC_CH3);

  65.     /* Disable the GPB0 - GPB3 digital input path to avoid the leakage current. */
  66.     GPIO_DISABLE_DIGITAL_PATH(PB, 0xF);

  67. }

  68. void UART0_Init()
  69. {
  70.     /*---------------------------------------------------------------------------------------------------------*/
  71.     /* Init UART                                                                                               */
  72.     /*---------------------------------------------------------------------------------------------------------*/
  73.     /* Reset UART IP */
  74.     SYS->IPRST1 |=  SYS_IPRST1_UART0RST_Msk;
  75.     SYS->IPRST1 &= ~SYS_IPRST1_UART0RST_Msk;

  76.     /* Configure UART0 and set UART0 baud rate */
  77.     UART0->BAUD = UART_BAUD_MODE2 | UART_BAUD_MODE2_DIVIDER(__HXT, 115200);
  78.     UART0->LINE = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1;
  79. }

  80. /*---------------------------------------------------------------------------------------------------------*/
  81. /* EADC function test                                                                                       */
  82. /*---------------------------------------------------------------------------------------------------------*/
  83. void EADC_FunctionTest()
  84. {
  85.     printf("\n");
  86.     printf("+----------------------------------------------------------------------+\n");
  87.     printf("|           EADC compare function (result monitor) sample code         |\n");
  88.     printf("+----------------------------------------------------------------------+\n");
  89.     printf("\nIn this test, software will compare the conversion result of channel 2.\n");

  90.     /* Set the ADC internal sampling time, input mode as single-end and enable the A/D converter */
  91.     EADC_Open(EADC, EADC_CTL_DIFFEN_SINGLE_END);
  92.     EADC_SetInternalSampleTime(EADC, 6);

  93.     /* Configure the sample module 0 for analog input channel 2 and ADINT0 trigger source */
  94.     EADC_ConfigSampleModule(EADC, 0, EADC_ADINT0_TRIGGER, 2);

  95.     /* Enable EADC comparator 0. Compare condition: conversion result < 0x800; match Count=5 */
  96.     printf("   Set the compare condition of comparator 0: channel 2 is less than 0x800; match count is 5.\n");
  97.     EADC_ENABLE_CMP0(EADC, 0, EADC_CMP_CMPCOND_LESS_THAN, 0x800, 0x5);

  98.     /* Enable EADC comparator 1. Compare condition: conversion result >= 0x800; match Count=5 */
  99.     printf("   Set the compare condition of comparator 1 : channel 2 is greater than or equal to 0x800; match count is 5.\n");
  100.     EADC_ENABLE_CMP1(EADC, 0, EADC_CMP_CMPCOND_GREATER_OR_EQUAL, 0x800, 0x5);

  101.     /* Enable sample module 0 interrupt */
  102.     EADC_ENABLE_SAMPLE_MODULE_INT(EADC, 0, 0x1);

  103.     /* Clear the A/D ADINT3 interrupt flag for safe */
  104.     EADC_CLR_INT_FLAG(EADC, (0x1 << 3));
  105.     /* Enable ADINT3 interrupt */
  106.     EADC_ENABLE_INT(EADC, (0x1 << 3));
  107.     NVIC_EnableIRQ(ADC03_IRQn);

  108.     /* Clear the EADC comparator 0 interrupt flag for safe */
  109.     EADC_CLR_INT_FLAG(EADC, (0x1 << 4));
  110.     /* Enable ADC comparator 0 interrupt */
  111.     EADC_ENABLE_CMP_INT(EADC, 0);

  112.     /* Clear the EADC comparator 1 interrupt flag for safe */
  113.     EADC_CLR_INT_FLAG(EADC, (0x1 << 5));
  114.     /* Enable ADC comparator 1 interrupt */
  115.     EADC_ENABLE_CMP_INT(EADC, 1);

  116.     /* Reset the EADC interrupt indicator and trigger sample module 0 to start A/D conversion */
  117.     g_u32AdcCmp0IntFlag = 0;
  118.     g_u32AdcCmp1IntFlag = 0;
  119.     EADC_START_CONV(EADC, 0x1);

  120.     /* Wait EADC compare interrupt */
  121.     while((g_u32AdcCmp0IntFlag == 0) && (g_u32AdcCmp1IntFlag == 0));

  122.     /* Disable the sample module 0 interrupt */
  123.     EADC_DISABLE_SAMPLE_MODULE_INT(EADC, 0, 0x1);

  124.     /* Disable ADC comparator interrupt */
  125.     EADC_DISABLE_CMP_INT(EADC, 0);
  126.     EADC_DISABLE_CMP_INT(EADC, 1);
  127.     /* Disable compare function */
  128.     EADC_DISABLE_CMP0(EADC);
  129.     EADC_DISABLE_CMP1(EADC);

  130.     if(g_u32AdcCmp0IntFlag == 1)
  131.     {
  132.         printf("Comparator 0 interrupt occurs.\nThe conversion result of channel 2 is less than 0x800\n");
  133.     }
  134.     else
  135.     {
  136.         printf("Comparator 1 interrupt occurs.\nThe conversion result of channel 2 is greater than or equal to 0x800\n");
  137.     }

  138. }

  139. /*---------------------------------------------------------------------------------------------------------*/
  140. /* EADC interrupt handler                                                                                  */
  141. /*---------------------------------------------------------------------------------------------------------*/
  142. void ADC03_IRQHandler(void)
  143. {
  144.     if(EADC_GET_INT_FLAG(EADC, (0x1 << 4)))
  145.     {
  146.         g_u32AdcCmp0IntFlag = 1;
  147.         EADC_CLR_INT_FLAG(EADC, (0x1 << 4));/* Clear the A/D compare flag 0 */
  148.     }

  149.     if(EADC_GET_INT_FLAG(EADC, (0x1 << 5)))
  150.     {
  151.         g_u32AdcCmp1IntFlag = 1;
  152.         EADC_CLR_INT_FLAG(EADC, (0x1 << 5));/* Clear the A/D compare flag 1 */
  153.     }
  154. }

  155. /*---------------------------------------------------------------------------------------------------------*/
  156. /*  Main Function                                                                                          */
  157. /*---------------------------------------------------------------------------------------------------------*/
  158. int32_t main(void)
  159. {

  160.     /* Unlock protected registers */
  161.     SYS_UnlockReg();

  162.     /* Init System, IP clock and multi-function I/O */
  163.     SYS_Init();

  164.     /* Lock protected registers */
  165.     SYS_LockReg();

  166.     /* Init UART0 for printf */
  167.     UART0_Init();

  168.     /*---------------------------------------------------------------------------------------------------------*/
  169.     /* SAMPLE CODE                                                                                             */
  170.     /*---------------------------------------------------------------------------------------------------------*/

  171.     printf("\nSystem clock rate: %d Hz", SystemCoreClock);

  172.     /* EADC function test */
  173.     EADC_FunctionTest();

  174.     /* Reset EADC module */
  175.     SYS_ResetModule(EADC_RST);

  176.     /* Disable EADC IP clock */
  177.     CLK_DisableModuleClock(EADC_MODULE);

  178.     /* Disable External Interrupt */
  179.     NVIC_DisableIRQ(ADC00_IRQn);

  180.     printf("Exit EADC sample code\n");

  181.     while(1);

  182. }
yiyigirl2014 发表于 2017-2-17 21:09 | 显示全部楼层
选择的什么参考?
玛尼玛尼哄 发表于 2017-2-17 21:22 | 显示全部楼层
用库函数试试。用寄存器容易漏。
robter 发表于 2017-2-18 07:21 | 显示全部楼层
这个没有注意到
戈卫东 发表于 2017-2-18 09:07 | 显示全部楼层
有这种问题?关注。。。
734774645 发表于 2017-2-19 18:46 | 显示全部楼层
第一次遇到ADC这种问题,以前都是可以输出到0的。
734774645 发表于 2017-2-19 18:47 | 显示全部楼层
我记得以前做,都是接地后就是0
 楼主| delven 发表于 2017-2-20 14:47 来自手机 | 显示全部楼层
yiyigirl2014 发表于 2017-2-17 21:09
选择的什么参考?

是用外部输入5V参考电压
 楼主| delven 发表于 2017-2-20 14:49 来自手机 | 显示全部楼层
wahahaheihei 发表于 2017-2-17 20:24
跑官方例程序试试看。

用官方例程下载到官方DEMO板,串口读取出来数据也不为0
稳稳の幸福 发表于 2017-2-20 16:04 | 显示全部楼层
好奇怪。
643757107 发表于 2017-2-20 19:12 | 显示全部楼层
谁有M451开发板跑一下官方例程试试看。
St小菜鸟 发表于 2017-2-21 09:37 | 显示全部楼层
wahahaheihei 发表于 2017-2-21 20:10 | 显示全部楼层
换个芯片试试看,是不是这个有问题。
 楼主| delven 发表于 2017-2-22 22:01 | 显示全部楼层
用官方的例程下载到官方的DEMO板,还会有这样的问题,很纠结啊!
 楼主| delven 发表于 2017-2-22 22:03 | 显示全部楼层
643757107 发表于 2017-2-20 19:12
谁有M451开发板跑一下官方例程试试看。

用官方的例程下载到官方的DEMO板,还会有这样的问题,很纠结啊!
 楼主| delven 发表于 2017-2-25 23:44 | 显示全部楼层
总结一下,问题的原因找到了,在ADC口有个输入超过5V的,大概在5.7V,结果这个ADC口影响到了其他的AD口数据读取。
Harvard 发表于 2017-2-26 10:46 | 显示全部楼层
放心吧 .新唐的adc还是非常给力的
您需要登录后才可以回帖 登录 | 注册

本版积分规则

3

主题

40

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部