[DemoCode下载] 新唐M051 ADC模数转换程序

[复制链接]
 楼主| heisexingqisi 发表于 2016-6-30 21:38 | 显示全部楼层 |阅读模式
以下程序是基于新唐M051单片机运行:
  1. /******************************************************************
  2. *注   意:硬件上的AVDD一定要接上基准电压
  3. ******************************************************************/
  4. #include "SmartM_M0.h"
  5. #define DEBUGMSG              printf
  6. #define ADC_CLOCK_DIVIDER     0x00040000
  7. #define ADC_CLK_Source        0x00000000
  8. #define AREF_VOLTAGE          4480
  9.       
  10. STATIC VOID AdcInit(VOID)
  11. {
  12. if(ADC_CLK_Source==0x00000004)
  13.     {
  14.         PLLCON |= PLL_SEL;
  15.         PLL_Enable();
  16.         /* 等待PLL稳定 */
  17.   while((CLKSTATUS & PLL_STB) == 0);  
  18. }
  19.     /* 复位ADC */   
  20.     set_ADC_RST;
  21.     clr_ADC_RST;
  22. /* ADC时钟使能 */      
  23.     set_ADEN_CLK;
  24.     if (ADC_CLK_Source==0x00000000 )
  25.     {
  26.         ADCClkSource_ex12MHZ;
  27.     }
  28.     else if(ADC_CLK_Source==0x00000004 )
  29.     {
  30.         ADCClkSource_PLL;
  31.     }
  32.     else if(ADC_CLK_Source==0x00000008 )
  33.     {
  34.         ADCClkSource_int22MHZ;
  35.     }
  36.     /* 设置ADC分频器 */
  37.     CLKDIV=ADC_CLOCK_DIVIDER;  
  38.   
  39.     /* ADC使能 */
  40.     set_ADEN;
  41.     set_CALEN;   
  42. while(!(ADCALR&CALDONE));
  43.     /* 单次转换模式 */
  44.     setAD_SIG;              
  45.     clr_DIFFEN;
  46. /* 设置ADC通道 */
  47.     set_CHEN0;
  48.     /* 使能P1.0为模拟输入引脚 */
  49.     set_ADC0_channel;
  50. /* 禁止P1.0数字输入通道 */
  51. P1_OFFD |= OFFD0;
  52.     /* 设置P1.0引脚为输入模式Configure P1.0 as input mode */
  53.     P10_InputOnly;
  54.     /* 清除ADC中断标志位 */
  55.     set_ADF;      
  56. }
  57. /****************************************
  58. *函数名称:main
  59. *输    入:无
  60. *输    出:无
  61. *功    能:函数主体
  62. ******************************************/
  63. INT32 main(VOID)
  64. {
  65.      UINT32 unVoltageValue;
  66.                            
  67.   PROTECT_REG          //ISP下载时保护FLASH存储器
  68.   (
  69.    PWRCON |= XTL12M_EN;       //默认时钟源为外部晶振
  70.    while((CLKSTATUS & XTL12M_STB) == 0);    //等待12MHz时钟稳定
  71.   
  72.    CLKSEL0 = (CLKSEL0 & (~HCLK)) | HCLK_12M;//设置外部晶振为系统时钟  
  73.   )
  74.   UartInit(12000000,9600);       //波特率设置为9600bps
  75.   AdcInit();
  76.   while(1)
  77.   {
  78.      set_ADST;            //启动ADC
  79.   while(ADSR&ADF==0);        //等待ADC结束
  80.   set_ADF;          //清空ADC结束标志位
  81.   unVoltageValue = AREF_VOLTAGE*(ADDR0&0xFFF)/4096;//将ADC值转换为电压值
  82.   DEBUGMSG("Voltage %d mv \r\n",unVoltageValue);
  83.   Delayms(500);
  84.   }
  85. }


zhuomuniao110 发表于 2016-6-30 21:58 | 显示全部楼层
ADC在单片机上就是现实世界和数字世界的桥梁。
643757107 发表于 2016-6-30 22:17 | 显示全部楼层
新唐科技NuMicro M051™ 系列基于ARM® Cortex™-M0核心的高效能、低功耗的单片机,其核心执行速度高达50MHz相当于45DMIPS,每秒执行4千五百万条指令,且内建32位乘法器,嵌套向量中断控制器NVIC,双信道APB设计,使系统效能发挥到极致。而芯片周边配置有内建8K到64K Bytes 快闪内存,4K Bytes RAM存储器,独立4K Bytes DATA FLASH快闪数据区,独立4K Bytes 程序升级快闪内存,外部扩充地址/数据总线(EBI),整合与周边模块高效通讯的能力;通讯部份整合2组高速UART、2组SPI、1组I2C;模拟信号模块提供8通道高速12位模数转换器ADC、低压侦测和欠压检测等功能。另外还有脉宽调制模块(PWM)、加上捕获与比较功能。并具备4组32位定时器(Timer)、看门狗定时器(Watch Dog Timer),内部RC晶振,内部复位等,是一颗高集成度的产品。在关键特色部份,除了Cortex™-M0核心与周边IP特性外,新唐独特的宽操作电压 (2.5V~5.5V),高抗干扰、抗噪声、工业温度规格设计,更能满足客户对于要求高质量、高性能通用单片机的要求。NuMicro M051™ 系列特别适合应用于工业控制、安防、通讯系统与需要高速计算数据采集系统领域。
734774645 发表于 2016-6-30 23:33 | 显示全部楼层
特性
 模拟输入电压范围: 0~AVDD .
 12位分辨率和10位精度保证.
 最多 8 路单端模拟输入通道或4路差分模拟输入通道.
 最大 ADC 时钟频率 16MHz.
 高达760k SPS 采样速率.
 四种操作模式
 单次转换模式: A/D在指定通道完成一次转换.
 突发模式: A/D转换在指定单个通道连续进行,并将结果顺序地存入FIFO.
 单周期扫描模式: A/D 转换在所有指定通道完成一次转换(从低序号通道到高序号通道) .
 连续扫描模式: A/D 转换连续执行单周期扫描模式直到软件停止A/D转换.
 A/D转换开始条件
 软件向ADST 位写1
 外部引脚STADC触发
 PWM触发,启动延迟可以配置(只有M05xxDN/DE)
 每个通道的转换结果存储在相应数据寄存器内,并带有有效和溢出标志.
 转换结果可以和指定的值相比较, 当转换结果和比较寄存器的设定值相匹配时,用户可设定
是否产生中断请求.
 通道 7 支持 3种输入源:外部模拟电压, 内部带隙电压和内部温度传感器的输出

734774645 发表于 2016-6-30 23:40 | 显示全部楼层
734774645 发表于 2016-6-30 23:42 | 显示全部楼层
我们看到ADC虽然很复杂,但是通过上面的结构图,我们就可以很清楚内部关系,怎么操作。
 楼主| heisexingqisi 发表于 2016-6-30 23:48 | 显示全部楼层
每个通道的转换结果存储在相应数据寄存器内,并带有有效和溢出标志.上面补充的图很不错。
jxthk 发表于 2016-7-1 09:06 | 显示全部楼层
看看看看
liangwode 发表于 2016-7-1 16:06 | 显示全部楼层
学习了
lovecat2015 发表于 2016-7-1 20:40 | 显示全部楼层
新唐M051的这个片子有几个独立的adc呢?
zsp06312222 发表于 2016-7-5 09:46 | 显示全部楼层
就一个问题:ADC的处理时间周期怎么控制
capturesthe 发表于 2016-7-5 10:22 | 显示全部楼层
M051有没有双路adc实现同步采集呢?
 楼主| heisexingqisi 发表于 2016-7-7 23:44 | 显示全部楼层
lovecat2015 发表于 2016-7-1 20:40
新唐M051的这个片子有几个独立的adc呢?

一个8通道12位的SAR型模拟 – 数字转换器 (SAR A/D转换器)
 楼主| heisexingqisi 发表于 2016-7-7 23:46 | 显示全部楼层
zsp06312222 发表于 2016-7-5 09:46
就一个问题:ADC的处理时间周期怎么控制

根据选择的时钟来控制,当然外设具有自己的物理时间,因为测量ADC实际是个充放电过程。不过你可以通过定时采样来控制,也可以不停的读取。。。具体跟选择的时钟有关系
 楼主| heisexingqisi 发表于 2016-7-7 23:47 | 显示全部楼层
capturesthe 发表于 2016-7-5 10:22
M051有没有双路adc实现同步采集呢?

可以实现双路采集,那个就是以下两种情况, 单周期是只操作一次,调用该功能,就执行一次测量,第二个连续,就是测完会自动进入下次测量。
单周期扫描模式: A/D 转换在所有指定通道完成一次转换(从低序号通道到高序号通
道) .

连续扫描模式: A/D 转换连续执行单周期扫描模式直到软件停止A/D转换.
 楼主| heisexingqisi 发表于 2016-7-7 23:55 | 显示全部楼层
3.png
4.png

/*---------------------------------------------------------------------------------------------------------*/
    /* Init System Clock                                                                                       */
    /*---------------------------------------------------------------------------------------------------------*/

    /* Enable Internal RC 22.1184MHz clock */
    CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);

    /* Waiting for Internal RC clock ready */
    CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);

    /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */
    CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));

    /* Enable external XTAL 12MHz clock */
    CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);

    /* Waiting for external XTAL clock ready */
    CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);

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

    /* Enable UART module clock */
    CLK_EnableModuleClock(UART0_MODULE);

    /* Enable ADC module clock */
    CLK_EnableModuleClock(ADC_MODULE);

    /* Select UART module clock source */
    CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_PLL, CLK_CLKDIV_UART(1));

    /* ADC clock source is 22.1184MHz, set divider to 7, ADC clock is 22.1184/7 MHz */
    CLK_SetModuleClock(ADC_MODULE, CLK_CLKSEL1_ADC_S_HIRC, CLK_CLKDIV_ADC(7));


 楼主| heisexingqisi 发表于 2016-7-7 23:57 | 显示全部楼层
上面就是ADC的时钟配置,当然为了系统运行,肯定要配置系统核心的时钟系统。
之前的例子实际上是两种情况,我们知道,ADC输入有单极性输入和双极性输入
而单极性实际上就是把一个极固定到地
Roderman_z 发表于 2016-7-9 20:45 | 显示全部楼层
如何设置两个adc同步采集呢
 楼主| heisexingqisi 发表于 2016-7-14 07:11 | 显示全部楼层
Roderman_z 发表于 2016-7-9 20:45
如何设置两个adc同步采集呢

两个采集一次呢,还是不停的循环采集呢?
 楼主| heisexingqisi 发表于 2016-7-14 07:12 | 显示全部楼层
Roderman_z 发表于 2016-7-9 20:45
如何设置两个adc同步采集呢

如果是只扫描一次,就是单次循环扫描
  1. /****************************************************************************
  2. * [url=home.php?mod=space&uid=288409]@file[/url]    main.c
  3. * [url=home.php?mod=space&uid=895143]@version[/url]  V3.0
  4. * $Revision: 4 $
  5. * $Date: 14/01/28 11:44a $
  6. * [url=home.php?mod=space&uid=247401]@brief[/url]    M051 Series ADC Interface Controller Driver Sample Code
  7. *
  8. * @note
  9. * Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved.
  10. *
  11. ******************************************************************************/
  12. #include <stdio.h>
  13. #include "M051Series.h"

  14. #define PLL_CLOCK       50000000


  15. /*---------------------------------------------------------------------------------------------------------*/
  16. /* Define Function Prototypes                                                                              */
  17. /*---------------------------------------------------------------------------------------------------------*/
  18. void SYS_Init(void);
  19. void UART0_Init(void);
  20. void AdcSingleCycleScanModeTest(void);


  21. void SYS_Init(void)
  22. {
  23.     /*---------------------------------------------------------------------------------------------------------*/
  24.     /* Init System Clock                                                                                       */
  25.     /*---------------------------------------------------------------------------------------------------------*/

  26.     /* Enable Internal RC 22.1184MHz clock */
  27.     CLK_EnableXtalRC(CLK_PWRCON_OSC22M_EN_Msk);

  28.     /* Waiting for Internal RC clock ready */
  29.     CLK_WaitClockReady(CLK_CLKSTATUS_OSC22M_STB_Msk);

  30.     /* Switch HCLK clock source to Internal RC and HCLK source divide 1 */
  31.     CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_CLKDIV_HCLK(1));

  32.     /* Enable external XTAL 12MHz clock */
  33.     CLK_EnableXtalRC(CLK_PWRCON_XTL12M_EN_Msk);

  34.     /* Waiting for external XTAL clock ready */
  35.     CLK_WaitClockReady(CLK_CLKSTATUS_XTL12M_STB_Msk);

  36.     /* Set core clock as PLL_CLOCK from PLL */
  37.     CLK_SetCoreClock(PLL_CLOCK);

  38.     /* Enable UART module clock */
  39.     CLK_EnableModuleClock(UART0_MODULE);

  40.     /* Enable ADC module clock */
  41.     CLK_EnableModuleClock(ADC_MODULE);

  42.     /* Select UART module clock source */
  43.     CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_CLKDIV_UART(1));

  44.     /* ADC clock source is 22.1184MHz, set divider to 7, ADC clock is 22.1184/7 MHz */
  45.     CLK_SetModuleClock(ADC_MODULE, CLK_CLKSEL1_ADC_S_HIRC, CLK_CLKDIV_ADC(7));

  46.     /*---------------------------------------------------------------------------------------------------------*/
  47.     /* Init I/O Multi-function                                                                                 */
  48.     /*---------------------------------------------------------------------------------------------------------*/

  49.     /* Set P3 multi-function pins for UART0 RXD and TXD */
  50.     SYS->P3_MFP &= ~(SYS_MFP_P30_Msk | SYS_MFP_P31_Msk);
  51.     SYS->P3_MFP |= SYS_MFP_P30_RXD0 | SYS_MFP_P31_TXD0;

  52.     /* Disable the P1.0 - P1.3 digital input path to avoid the leakage current */
  53.     GPIO_DISABLE_DIGITAL_PATH(P1, 0xF);

  54.     /* Configure the P1.0 - P1.3 ADC analog input pins */
  55.     SYS->P1_MFP &= ~(SYS_MFP_P10_Msk | SYS_MFP_P11_Msk | SYS_MFP_P12_Msk | SYS_MFP_P13_Msk);
  56.     SYS->P1_MFP |= SYS_MFP_P10_AIN0 | SYS_MFP_P11_AIN1 | SYS_MFP_P12_AIN2 | SYS_MFP_P13_AIN3 ;

  57. }

  58. /*---------------------------------------------------------------------------------------------------------*/
  59. /* Init UART                                                                                               */
  60. /*---------------------------------------------------------------------------------------------------------*/
  61. void UART0_Init()
  62. {
  63.     /* Reset IP */
  64.     SYS_ResetModule(UART0_RST);

  65.     /* Configure UART0 and set UART0 Baudrate */
  66.     UART_Open(UART0, 115200);
  67. }

  68. /*---------------------------------------------------------------------------------------------------------*/
  69. /* Function: AdcSingleCycleScanModeTest                                                                    */
  70. /*                                                                                                         */
  71. /* Parameters:                                                                                             */
  72. /*   None.                                                                                                 */
  73. /*                                                                                                         */
  74. /* Returns:                                                                                                */
  75. /*   None.                                                                                                 */
  76. /*                                                                                                         */
  77. /* Description:                                                                                            */
  78. /*   ADC single cycle scan mode test.                                                                      */
  79. /*---------------------------------------------------------------------------------------------------------*/
  80. void AdcSingleCycleScanModeTest()
  81. {
  82.     uint8_t  u8Option;
  83.     uint32_t u32ChannelCount;
  84.     int32_t  i32ConversionData;

  85.     printf("\n");
  86.     printf("+----------------------------------------------------------------------+\n");
  87.     printf("|                 ADC single cycle scan mode sample code               |\n");
  88.     printf("+----------------------------------------------------------------------+\n");

  89.     while(1)
  90.     {
  91.         printf("\n\nSelect input mode:\n");
  92.         printf("  [1] Single end input (channel 0, 1, 2 and 3)\n");
  93.         printf("  [2] Differential input (input channel pair 0 and 1)\n");
  94.         printf("  Other keys: exit single cycle scan mode test\n");
  95.         u8Option = getchar();
  96.         if(u8Option == '1')
  97.         {

  98.             /* Set the ADC operation mode as single-cycle, input mode as single-end and
  99.                  enable the analog input channel 0, 1, 2 and 3 */
  100.             ADC_Open(ADC, ADC_ADCR_DIFFEN_SINGLE_END, ADC_ADCR_ADMD_SINGLE_CYCLE, 0xF);

  101.             /* Power on ADC module */
  102.             ADC_POWER_ON(ADC);

  103.             /* clear the A/D interrupt flag for safe */
  104.             ADC_CLR_INT_FLAG(ADC, ADC_ADF_INT);

  105.             /* start A/D conversion */
  106.             ADC_START_CONV(ADC);

  107.             /* Wait conversion done */
  108.             while(!ADC_GET_INT_FLAG(ADC, ADC_ADF_INT));

  109.             for(u32ChannelCount = 0; u32ChannelCount < 4; u32ChannelCount++)
  110.             {
  111.                 i32ConversionData = ADC_GET_CONVERSION_DATA(ADC, u32ChannelCount);
  112.                 printf("Conversion result of channel %d: 0x%X (%d)\n", u32ChannelCount, i32ConversionData, i32ConversionData);
  113.             }
  114.         }
  115.         else if(u8Option == '2')
  116.         {

  117.             /* Set the ADC operation mode as single-cycle, input mode as differential and
  118.                enable analog input channel 0 and 2 */
  119.             ADC_Open(ADC, ADC_ADCR_DIFFEN_DIFFERENTIAL, ADC_ADCR_ADMD_SINGLE_CYCLE, 0x5);

  120.             /* Power on ADC module */
  121.             ADC_POWER_ON(ADC);

  122.             /* clear the A/D interrupt flag for safe */
  123.             ADC_CLR_INT_FLAG(ADC, ADC_ADF_INT);

  124.             /* start A/D conversion */
  125.             ADC_START_CONV(ADC);

  126.             /* Wait conversion done */
  127.             while(!ADC_GET_INT_FLAG(ADC, ADC_ADF_INT));

  128.             for(u32ChannelCount = 0; u32ChannelCount < 2; u32ChannelCount++)
  129.             {
  130.                 i32ConversionData = ADC_GET_CONVERSION_DATA(ADC, u32ChannelCount * 2);
  131.                 printf("Conversion result of differential input pair %d: 0x%X (%d)\n", u32ChannelCount, i32ConversionData, i32ConversionData);
  132.             }
  133.         }
  134.         else
  135.             return ;

  136.     }
  137. }

  138. /*---------------------------------------------------------------------------------------------------------*/
  139. /* MAIN function                                                                                           */
  140. /*---------------------------------------------------------------------------------------------------------*/

  141. main(void)
  142. {

  143.     /* Unlock protected registers */
  144.     SYS_UnlockReg();

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

  147.     /* Lock protected registers */
  148.     SYS_LockReg();

  149.     /* Init UART0 for printf */
  150.     UART0_Init();

  151.     /*---------------------------------------------------------------------------------------------------------*/
  152.     /* SAMPLE CODE                                                                                             */
  153.     /*---------------------------------------------------------------------------------------------------------*/

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

  155.     /* Single cycle scan mode test */
  156.     AdcSingleCycleScanModeTest();

  157.     /* Disable ADC module */
  158.     ADC_Close(ADC);

  159.     /* Disable ADC IP clock */
  160.     CLK_DisableModuleClock(ADC_MODULE);

  161.     /* Disable External Interrupt */
  162.     NVIC_DisableIRQ(ADC_IRQn);

  163.     printf("\nExit ADC sample code\n");

  164.     while(1);

  165. }


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

本版积分规则

157

主题

2770

帖子

2

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