打印
[DemoCode下载]

新唐M051 ADC模数转换程序

[复制链接]
3301|24
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
以下程序是基于新唐M051单片机运行:
/****************************************************************** 
*注   意:硬件上的AVDD一定要接上基准电压
******************************************************************/
#include "SmartM_M0.h"
#define DEBUGMSG              printf
#define ADC_CLOCK_DIVIDER     0x00040000
#define ADC_CLK_Source        0x00000000
#define AREF_VOLTAGE          4480
      
STATIC VOID AdcInit(VOID)
{
if(ADC_CLK_Source==0x00000004)
    {
        PLLCON |= PLL_SEL;
        PLL_Enable();
        /* 等待PLL稳定 */
  while((CLKSTATUS & PLL_STB) == 0);  
}
    /* 复位ADC */   
    set_ADC_RST;
    clr_ADC_RST;
/* ADC时钟使能 */      
    set_ADEN_CLK;
    if (ADC_CLK_Source==0x00000000 )
    {
        ADCClkSource_ex12MHZ;
    }
    else if(ADC_CLK_Source==0x00000004 )
    {
        ADCClkSource_PLL;
    }
    else if(ADC_CLK_Source==0x00000008 )
    {
        ADCClkSource_int22MHZ;
    }
    /* 设置ADC分频器 */
    CLKDIV=ADC_CLOCK_DIVIDER;  
  
    /* ADC使能 */
    set_ADEN;
    set_CALEN;   
while(!(ADCALR&CALDONE));
    /* 单次转换模式 */
    setAD_SIG;              
    clr_DIFFEN;
/* 设置ADC通道 */
    set_CHEN0;
    /* 使能P1.0为模拟输入引脚 */
    set_ADC0_channel;
/* 禁止P1.0数字输入通道 */
P1_OFFD |= OFFD0;
    /* 设置P1.0引脚为输入模式Configure P1.0 as input mode */
    P10_InputOnly;
    /* 清除ADC中断标志位 */
    set_ADF;      
}
/****************************************
*函数名称:main
*输    入:无
*输    出:无
*功    能:函数主体
******************************************/
INT32 main(VOID)
{
     UINT32 unVoltageValue;
                           
  PROTECT_REG          //ISP下载时保护FLASH存储器
  (
   PWRCON |= XTL12M_EN;       //默认时钟源为外部晶振
   while((CLKSTATUS & XTL12M_STB) == 0);    //等待12MHz时钟稳定
  
   CLKSEL0 = (CLKSEL0 & (~HCLK)) | HCLK_12M;//设置外部晶振为系统时钟  
  )
  UartInit(12000000,9600);       //波特率设置为9600bps
  AdcInit();
  while(1)
  {
     set_ADST;            //启动ADC
  while(ADSR&ADF==0);        //等待ADC结束
  set_ADF;          //清空ADC结束标志位
  unVoltageValue = AREF_VOLTAGE*(ADDR0&0xFFF)/4096;//将ADC值转换为电压值
  DEBUGMSG("Voltage %d mv \r\n",unVoltageValue);
  Delayms(500);
  }
}


沙发
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种输入源:外部模拟电压, 内部带隙电压和内部温度传感器的输出

使用特权

评论回复
5
734774645| | 2016-6-30 23:40 | 只看该作者

使用特权

评论回复
6
734774645| | 2016-6-30 23:42 | 只看该作者
我们看到ADC虽然很复杂,但是通过上面的结构图,我们就可以很清楚内部关系,怎么操作。

使用特权

评论回复
7
heisexingqisi|  楼主 | 2016-6-30 23:48 | 只看该作者
每个通道的转换结果存储在相应数据寄存器内,并带有有效和溢出标志.上面补充的图很不错。

使用特权

评论回复
8
jxthk| | 2016-7-1 09:06 | 只看该作者
看看看看

使用特权

评论回复
9
liangwode| | 2016-7-1 16:06 | 只看该作者
学习了

使用特权

评论回复
10
lovecat2015| | 2016-7-1 20:40 | 只看该作者
新唐M051的这个片子有几个独立的adc呢?

使用特权

评论回复
11
zsp06312222| | 2016-7-5 09:46 | 只看该作者
就一个问题:ADC的处理时间周期怎么控制

使用特权

评论回复
12
capturesthe| | 2016-7-5 10:22 | 只看该作者
M051有没有双路adc实现同步采集呢?

使用特权

评论回复
13
heisexingqisi|  楼主 | 2016-7-7 23:44 | 只看该作者
lovecat2015 发表于 2016-7-1 20:40
新唐M051的这个片子有几个独立的adc呢?

一个8通道12位的SAR型模拟 – 数字转换器 (SAR A/D转换器)

使用特权

评论回复
14
heisexingqisi|  楼主 | 2016-7-7 23:46 | 只看该作者
zsp06312222 发表于 2016-7-5 09:46
就一个问题:ADC的处理时间周期怎么控制

根据选择的时钟来控制,当然外设具有自己的物理时间,因为测量ADC实际是个充放电过程。不过你可以通过定时采样来控制,也可以不停的读取。。。具体跟选择的时钟有关系

使用特权

评论回复
15
heisexingqisi|  楼主 | 2016-7-7 23:47 | 只看该作者
capturesthe 发表于 2016-7-5 10:22
M051有没有双路adc实现同步采集呢?

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

连续扫描模式: A/D 转换连续执行单周期扫描模式直到软件停止A/D转换.

使用特权

评论回复
16
heisexingqisi|  楼主 | 2016-7-7 23:55 | 只看该作者



/*---------------------------------------------------------------------------------------------------------*/
    /* 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));


使用特权

评论回复
17
heisexingqisi|  楼主 | 2016-7-7 23:57 | 只看该作者
上面就是ADC的时钟配置,当然为了系统运行,肯定要配置系统核心的时钟系统。
之前的例子实际上是两种情况,我们知道,ADC输入有单极性输入和双极性输入
而单极性实际上就是把一个极固定到地

使用特权

评论回复
18
Roderman_z| | 2016-7-9 20:45 | 只看该作者
如何设置两个adc同步采集呢

使用特权

评论回复
19
heisexingqisi|  楼主 | 2016-7-14 07:11 | 只看该作者
Roderman_z 发表于 2016-7-9 20:45
如何设置两个adc同步采集呢

两个采集一次呢,还是不停的循环采集呢?

使用特权

评论回复
20
heisexingqisi|  楼主 | 2016-7-14 07:12 | 只看该作者
Roderman_z 发表于 2016-7-9 20:45
如何设置两个adc同步采集呢

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

#define PLL_CLOCK       50000000


/*---------------------------------------------------------------------------------------------------------*/
/* Define Function Prototypes                                                                              */
/*---------------------------------------------------------------------------------------------------------*/
void SYS_Init(void);
void UART0_Init(void);
void AdcSingleCycleScanModeTest(void);


void SYS_Init(void)
{
    /*---------------------------------------------------------------------------------------------------------*/
    /* 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_HXT, 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));

    /*---------------------------------------------------------------------------------------------------------*/
    /* Init I/O Multi-function                                                                                 */
    /*---------------------------------------------------------------------------------------------------------*/

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

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

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

}

/*---------------------------------------------------------------------------------------------------------*/
/* Init UART                                                                                               */
/*---------------------------------------------------------------------------------------------------------*/
void UART0_Init()
{
    /* Reset IP */
    SYS_ResetModule(UART0_RST);

    /* Configure UART0 and set UART0 Baudrate */
    UART_Open(UART0, 115200);
}

/*---------------------------------------------------------------------------------------------------------*/
/* Function: AdcSingleCycleScanModeTest                                                                    */
/*                                                                                                         */
/* Parameters:                                                                                             */
/*   None.                                                                                                 */
/*                                                                                                         */
/* Returns:                                                                                                */
/*   None.                                                                                                 */
/*                                                                                                         */
/* Description:                                                                                            */
/*   ADC single cycle scan mode test.                                                                      */
/*---------------------------------------------------------------------------------------------------------*/
void AdcSingleCycleScanModeTest()
{
    uint8_t  u8Option;
    uint32_t u32ChannelCount;
    int32_t  i32ConversionData;

    printf("\n");
    printf("+----------------------------------------------------------------------+\n");
    printf("|                 ADC single cycle scan mode sample code               |\n");
    printf("+----------------------------------------------------------------------+\n");

    while(1)
    {
        printf("\n\nSelect input mode:\n");
        printf("  [1] Single end input (channel 0, 1, 2 and 3)\n");
        printf("  [2] Differential input (input channel pair 0 and 1)\n");
        printf("  Other keys: exit single cycle scan mode test\n");
        u8Option = getchar();
        if(u8Option == '1')
        {

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

            /* Power on ADC module */
            ADC_POWER_ON(ADC);

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

            /* start A/D conversion */
            ADC_START_CONV(ADC);

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

            for(u32ChannelCount = 0; u32ChannelCount < 4; u32ChannelCount++)
            {
                i32ConversionData = ADC_GET_CONVERSION_DATA(ADC, u32ChannelCount);
                printf("Conversion result of channel %d: 0x%X (%d)\n", u32ChannelCount, i32ConversionData, i32ConversionData);
            }
        }
        else if(u8Option == '2')
        {

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

            /* Power on ADC module */
            ADC_POWER_ON(ADC);

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

            /* start A/D conversion */
            ADC_START_CONV(ADC);

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

            for(u32ChannelCount = 0; u32ChannelCount < 2; u32ChannelCount++)
            {
                i32ConversionData = ADC_GET_CONVERSION_DATA(ADC, u32ChannelCount * 2);
                printf("Conversion result of differential input pair %d: 0x%X (%d)\n", u32ChannelCount, i32ConversionData, i32ConversionData);
            }
        }
        else
            return ;

    }
}

/*---------------------------------------------------------------------------------------------------------*/
/* MAIN function                                                                                           */
/*---------------------------------------------------------------------------------------------------------*/

main(void)
{

    /* Unlock protected registers */
    SYS_UnlockReg();

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

    /* Lock protected registers */
    SYS_LockReg();

    /* Init UART0 for printf */
    UART0_Init();

    /*---------------------------------------------------------------------------------------------------------*/
    /* SAMPLE CODE                                                                                             */
    /*---------------------------------------------------------------------------------------------------------*/

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

    /* Single cycle scan mode test */
    AdcSingleCycleScanModeTest();

    /* Disable ADC module */
    ADC_Close(ADC);

    /* Disable ADC IP clock */
    CLK_DisableModuleClock(ADC_MODULE);

    /* Disable External Interrupt */
    NVIC_DisableIRQ(ADC_IRQn);

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

    while(1);

}


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

116

主题

2538

帖子

2

粉丝