打印
[菜农助学交流]

【第四批】笔记五——ADC初始化程序解析

[复制链接]
5330|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zxcscm|  楼主 | 2012-2-15 22:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 zxcscm 于 2012-2-15 22:56 编辑

我发现,学习某一个功能时,只是一味的看例程,将结果调试出来,总感觉并没有真正的掌握它
可能是因为还停留在51的学习习惯上,每学习一个功能总想弄清楚是具体怎么操作寄存器的,这样才觉得知根知底
所以又对着手册扒拉ADC的各个寄存器,这样做很笨也很费时间,也不知这种学习方法是否正确,但是心安

下面是对ADC初始化函数的一点分析

参考数据手册P449

三种操作模式: 单一(single, 单周期扫描(single-cycle scan) 和连续扫描模式(continuous scan). A/D 转换可由软件设定和外部STADCpin开启.
所有使能通道有三种操作模式

   · 单一触发模式: A/D转换在指定通道完成一次

   · 单周期扫描模式:A/D转换在指定通道完成一个周期,转换顺序从最小号通道到最大号通道

   · 连续扫描模式: A/D持续执行单周期扫描模式直到软件停止A/D转换
每个通道有两种输入方式
  ·单端输入方式
  ·差分输入方式
A/D转换开始条件

  · 软件向ADST 位写1
  · 外部 pin STADC

首先配置ADC时钟
ADC有三个时钟源,可由两位ADC_S(CLKSEL[3:2])选择;
ADC 时钟频率按如下公式进行8位预分频: ADC时钟频率= (ADC clock source frequency) /(ADC_N+1)

ADC_S在时钟源选择寄存器CLKSEL1[3:2]中设置【1】技术手册P162
ADC_N 在时钟分频寄存器CLKDIV[23:16]中设置. 2】技术手册P167
通常来说,软件设置ADC_S ADC_N 获得 16 MHz 或稍低于16 MHz的频率。
接下对ADC的一系列寄存器进行配置,启动ADC即可, 详细过程见下面驱动程序:
一、DrvADC_Open(E_ADC_INPUT_MODEInputMode, E_ADC_OPERATION_MODE OpMode, uint8_t u8ChannelSelBitwise,E_ADC_CLK_SRC ClockSrc, uint8_t u8AdcDivisor)

感觉这个函数把
ADC的所有寄存器都设置了一遍
原函数很长就不贴了

先来分析下几个形参,具体可见原函数的注释,这里只是稍微翻译了一下

1 InputMode:指定模拟输入信号的类型,可选择
.单端输入(single end input:
ADC_SINGLE_END
.差分输入(differential input:
ADC_DIFFERENTIAL
2
OpMode:指定操作模式,可选择
.
单一触发模式(single)ADC_SINGLE_OP
.单周期扫描模式(singlecycle scan)ADC_SINGLE_CYCLE_OP   
.连续扫描模式(continuousscan mode)ADC_CONTINUOUS_OP

3
u8ChannelSelBitwise:指定输入通道,举例说明
                  u8ChannelSelBitwise=0x1(00000001b)
使能通道0
                  u8ChannelSelBitwise=0x19(00011001b)
使能通道034

4
ClockSrc:指定ADC的时钟源,即设置ADC时钟源ADC_S,可选择
. EXTERNAL_12MHZ
.INTERNAL_PLL
.INTERNAL_RC22MHZ=2

有个小问题:可能是新版的手册有误ADC_S=11 = 内部 22.1184 MHz 高速振荡器
其实ADC_S=1x就能选择内部 22.1184MHz 高速振荡器所以例程中INTERNAL_RC22MHZ=2是没错的。

5
u8AdcDivisor:确定ADC时钟预分频,即设置时钟分频寄存器ADC_NADC时钟频率= (ADC 时钟源频率) / (ADC_N+1)

函数内部顺序执行的功能分别是:
1
、复位ADC:外设复位控制寄存器2(IPRSTC2). ADC_RST  P77
2
、设置ADC时钟源寄存器ADC_S      P162
3
、设置ADC时钟分频寄存器_ADC_N   P167
4
、使能ADC时钟:APB 设备时钟使能控制寄存器APBCLK.ADC_EN  P156
5
、使能ADCA/D 控制寄存器ADCR.ADEN  P422
6
、设置输入方式:单端输入或差分输入
7
、设置操作模式:单一触发模式单周期扫描模式
连续扫描模式
8
、选择ADC通道
9
、设置相应通道的GPIOADC功能

总结:该函数功能已经涵盖了下列函数的功能
DrvADC_SetADCChannel//
设置ADC通道
DrvADC_SetADCInputMode//
设置输入模式
DrvADC_SetADCOperationMode//
设置操作模式
DrvADC_SetADCClkSrc//
设置ADC时钟源

DrvADC_SetADCDivisor//
设置ADC时钟预分频
所以对该函数进行正确配置后几乎就完成了ADC的初始化
最后设置ADC->ADCR.DMOF =0;使AD转换的输出结果为无符号格式

二、DrvADC_StartConvert1、清除AD转换结束标志位ADF
outpw(ADC_ADSR, (inpw(ADC_ADSR)&(~0x7))|0x1);说明:不建议使用"ADC->ADSR.ADF= 1;"可能会清除了CMPF0 CMPF12、设置AD转换开始标志:ADC->ADCR.ADST= 1;
下面是P430ADF的描述,感觉很矛盾,在例程里也是这么操作的,所以想不通,
A/D 转换结束标志位

用以指示A/D转换已結束的状态标志位

以下两种条件下ADF1.
1.  单一模式下,A/D 转换结束.
2.  扫描模式下,在所有指定通道的A/D转换结束.
1可清除该标志

既然AD转换结束后能将ADF1,怎么写1又可以清除该标志?不知哪位大哥可以解惑

三、DrvADC_IsConversionDone

查询ADC->ADSR.ADF是否为1,若为0返回FALSE,否则返回TRUE

四、int32_t DrvADC_GetConversionData(uint8_tu8ChannelNum)

返回相应通道的AD转换值


参考文件:
1NUC100 NUC120 Technical ReferenceManual SC V2.01
下载:NUC100 NUC120 系列产品的技术参考文档V2.01 - 中文版
【2】NUC100SeriesBSP_v1.05.002
下载:
NUC100Series BSP_CMSIS V1.05.002.7z 其他参考资料可到官方论坛或新塘官方网站下载:NUC100系列开发资源汇总(最后更新:2011-12-06http://www.nuvoton-m0.com/forum.php?mod=viewthread&tid=1&extra=%26page%3D1&page=1

下面是调试用的源代码

#include "NUC1xx.h"
#include "DrvGPIO.h"
#include "DrvSYS.h"
#include "DrvADC.h"
#include "LCD4884.h"

void RCC_Configuration(void)
{
   UNLOCKREG();                                  // 对写保护位操作时 需要一次向0x50000 0100写入 0x59,0x16,0x88,
   DrvSYS_SetOscCtrl(E_SYS_XTL12M, 1);//与其 SYSCLK->PWRCON.XTL12M_EN = 1; 等同
                                      // PWRCON寄存器(这些寄存器在上电复位到用户解锁定之前是锁定的)除了 BIT[6]位其他位都受写保护
                                          // 解除这些需要向 0x50000 0100写入 0x59,0x16,0x88,
                                                                      // 令PWRCON寄存器的BITP[0]为1(即设定12M外部晶振)
   DrvSYS_Delay(5000);                //while (DrvSYS_GetChipClockSourceStatus(E_SYS_XTL12M) != 1);//等待外部12MHZ晶振就绪
   LOCKREG();                                  // 向“0x5000_0100”写入任何值,就可以重锁保护寄存器
}

void ADC_Configuration()
{

    DrvADC_Open(ADC_SINGLE_END, ADC_SINGLE_OP, 2, EXTERNAL_12MHZ, 5);         //  ADC_SINGLE_END  AD为单端输入模式
                                                                                                                                                  //  ADC_SINGLE_OP         单一触发模式
                                                                                                                                                 //  2         GA1作为输入         模式输入通道使能
                                                                                                                                                 //  EXTERNAL_12MHZ   ADC时钟为 外部12MHZ
                                                                                                                                                 //  5   AD时钟频率 = ADC时钟/(5+1)        = 2MHZ
                                                                                                     
    ADC->ADCR.DMOF = 0;                                                                                                         //转化结果无符号

}

void Set_System(void)
{
    RCC_Configuration();       //配置系统时钟
  
    ADC_Configuration();       //配置ADC
  
    LCD_init();
}

int main(void)
{
    int32_t i32AD_Data;
   
    Set_System();
   
    while(1)
    {
        DrvADC_StartConvert();                      //  开启ADC转换
            while(DrvADC_IsConversionDone()==FALSE);    //  判断ADC是否转换结束
        
        i32AD_Data = DrvADC_GetConversionData(1);   //获取AD寄存器的值

        LCD_clear();                                 //清屏幕               
        LCD_write_String(0,0,"Value:");     //LCD显示:Value
        LCD_set_XY(0,1);                    //设置LCD光标位置
        LCD_Disp_IntNum(i32AD_Data,'d',0);  //显示AD寄存器的值
        
        i32AD_Data = i32AD_Data*3380/0xfff; //修正AD转换的值为电压
                                            //3380:参考电压为3.38v
                                            //0xFFF:12位AD转换
        LCD_set_XY(0,2);
        LCD_Disp_IntNum(i32AD_Data,'d',0);  //显示修正后的电压值
        
        DrvSYS_Delay(5000000);
        DrvSYS_Delay(5000000);
    }
}




06-AD.rar (202.93 KB)

相关帖子

沙发
呆板书生| | 2012-2-16 08:32 | 只看该作者
既然AD转换结束后能将ADF置1,怎么写1又可以清除该标志?不知哪位大哥可以解惑

读和写其实是两个不同的寄存器,只是地址相同

使用特权

评论回复
板凳
zxcscm|  楼主 | 2012-2-22 12:48 | 只看该作者
明白了,哈哈哈  谢谢!

使用特权

评论回复
地板
john_lee| | 2012-2-22 19:39 | 只看该作者
顶楼主,有质量的好帖。

使用特权

评论回复
5
dong_abc| | 2012-2-22 20:34 | 只看该作者
既然AD转换结束后能将ADF置1,怎么写1又可以清除该标志?不知哪位大哥可以解惑

读和写其实是两个不同的寄存器,只是地址相同
呆板书生 发表于 2012-2-16 08:32


是啊,一直不知道为什么!

使用特权

评论回复
6
zxcscm|  楼主 | 2012-2-24 22:50 | 只看该作者
4# john_lee 多谢李老师的肯定

使用特权

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

本版积分规则

5

主题

628

帖子

1

粉丝