N76E003的学习之路(ADC简单小例程篇)
N76E003内嵌12位逐次逼近寄存器型(SAR)的模拟数字转换器(ADC)。模数转换模块负责将管脚上的模拟
信号转换为12位二进制数据。N76E003支持8通道单端输入模式。内部带隙电压(band-gap voltage)为
1.22V,同时也可用作内部ADC输入端。所有模拟电路复用同一组采样电路和同一组采样保持电容。该组
采样保持电容为转换电路的输入端。然后转换器通过逐次逼近的方式得到有效结果并存放在ADC结果寄
存器中。

在开始ADC转换前,通过设置ADCEN (ADCCON1.0)位使能ADC电路,从而激活ADC电路,由于ADC
模块需要额外功耗,一旦ADC转换模块不再使用,建议清零ADCEN位关闭ADC模块电路以节省功耗。
ADC转换输入管脚需要特别配置,通过ADCHS[2:0] 来选择采样所需要的ADC通道连接到采样电路上。
同时,用户需要通过PxMn寄存器把采样所用的管脚配置为“输入高阻模式” (input-only high
impedance) 。配置后用于ADC管脚与数字输出电路将断开,但数字输入电路仍然可以工作,因此数字
输入将可能产生漏电流。所以还需要通过配置AINDIDS寄存器相应位来关闭数字输入缓冲区。如上配置
后,ADC输入脚将变成纯模拟输入电路。同样ADC采样时钟也需要认真考虑。
ADC最高时钟频率参考表

表 31-9. 当采样时钟设置超过最大值时,采样结果数据为不可预测。
通过置ADCS位(ADCCON0.6)开启AD转换。当转换完成后,硬件会自动清除该位,同时置ADCF
(ADCCON0.7)位,如果之前ADC中断已使能,则会产生ADC中断。转换结果存放在ADCRH (高8位) 及
ADCRL (低4位)中。12位转换结果值为REF
内部及外部数字电路,可能影响采样结果的准确度。所以如果需要高精准的转换结果,请参考如下应
用,以降低噪声电平干扰。
1. 模拟输入脚尽量离芯片越近越好,避免管脚附近有高速数字电路经过,并离高速数字电路越远越好。
2. 在转换过程中,将芯片进入空闲模式。
3. 如果模拟输入脚AIN在系统中同时需要切换做数字管脚,请确保在转换过程中不要做数字/模拟切换动
作。
现在我们可以根据功能描述来编写程序
在开始ADC转换前,通过设置ADCEN (ADCCON1.0)位使能ADC电路,从而激活ADC电路,由于ADC
模块需要额外功耗,一旦ADC转换模块不再使用,建议清零ADCEN位关闭ADC模块电路以节省功耗。
ADC转换输入管脚需要特别配置,通过ADCHS[2:0] 来选择采样所需要的ADC通道连接到采样电路上。
同时,用户需要通过PxMn寄存器把采样所用的管脚配置为“输入高阻模式” (input-only high
impedance) 。配置后用于ADC管脚与数字输出电路将断开,但数字输入电路仍然可以工作,因此数字
输入将可能产生漏电流。所以还需要通过配置AINDIDS寄存器相应位来关闭数字输入缓冲区。如上配置
后,ADC输入脚将变成纯模拟输入电路。同样ADC采样时钟也需要认真考虑。
首先设置ADCEN(ADCCON1.0)位使能ADC电路,从而激活ADC电路


由于ADC模块需要额外功耗,一旦ADC转换模块不再使用,建议清零ADCEN位关闭ADC模块电路以节省功耗。
ADC转换输入管脚需要特别配置,通过ADCHS[2:0] 来选择采样所需要的ADC通道连接到采样电路上。
同时,用户需要通过PxMn寄存器把采样所用的管脚配置为“输入高阻模式” (input-only high
impedance) 。


用户需要通过PxMn寄存器把采样所用的管脚配置为“输入高阻模式” (input-only high
impedance) 。



配置后用于ADC管脚与数字输出电路将断开,但数字输入电路仍然可以工作,因此数字
输入将可能产生漏电流。所以还需要通过配置AINDIDS寄存器相应位来关闭数字输入缓冲区。如上配置
后,ADC输入脚将变成纯模拟输入电路。同样ADC采样时钟也需要认真考虑。

首先设置ADCEN(ADCCON1.0)位使能ADC电路,从而激活ADC电路
ADC转换输入管脚需要特别配置,通过ADCHS[2:0] 来选择采样所需要的ADC通道连接到采样电路上。
同时,用户需要通过PxMn寄存器把采样所用的管脚配置为“输入高阻模式” (input-only high
impedance) 。
配置后用于ADC管脚与数字输出电路将断开,但数字输入电路仍然可以工作,因此数字
输入将可能产生漏电流。所以还需要通过配置AINDIDS寄存器相应位来关闭数字输入缓冲区。如上配置
后,ADC输入脚将变成纯模拟输入电路。同样ADC采样时钟也需要认真考虑。
根据上述内容,程序具体如下:
Enable_ADC_AIN3; // Enable AIN0 P1.7 as ADC input, Find in "Function_define.h" - "ADC INIT" #define Enable_ADC_AIN3 ADCCON0&=0xF0;ADCCON0|=0x03;P06_Input_Mode;AINDIDS=0x00;AINDIDS|=SET_BIT3;ADCCON1|=SET_BIT0 //P06
ADCCON0&=0xF0;ADCCON0|=0x03;这部分的意思是选中引脚3 具体看上面的ADCCON0部分 //注意
ADCCON0&=0xF0;这部分是一定要加的,因为在项目中必须要先清零在选择通道,如果涉及多个通道切换,每个通道一定要加上这句,否则系统只会承认上一个通道。

P06_Input_Mode;是将通道三即P06引脚设为输入高阻模式,
#define P00_Input_Mode P0M1|=SET_BIT0;P0M2&=~SET_BIT0
P0M1|=SET_BIT0;P0M2&=~SET_BIT0 这部分看上文配置即可
AINDIDS=0x00;AINDIDS|=SET_BIT3;这部分意思是将第三通道数字输入功能关闭,由此三通道即P06引脚将变成纯模拟输入
ADCCON1|=SET_BIT0 是将ADCEN使能位使能 也就是说
Enable_ADC_AIN3;这个宏定义就是将ADC通道进行初始化
初始化完成,接下来来看应用:
通过置ADCS位(ADCCON0.6)开启AD转换。


当转换完成后,硬件会自动清除该位,同时置ADCF
(ADCCON0.7)位,如果之前ADC中断已使能,则会产生ADC中断。

转换结果存放在ADCRH (高8位) 及ADCRL (低4位)中。12位转换结果值为REF

程序如下:
while()
{
clr_ADCF;
set_ADCS; // ADC start trig signal
while(ADCF == );
printf ("\n Value = 0x%bx",ADCRH);
printf ("\n Value = 0x%bx",ADCRL);
Timer0_Delay1ms();
}
clr_ADCF;以防万一,软件清零
#define clr_ADCF ADCF = 0
set_ADCS;启动AD转换
#define set_ADCS ADCS = 1
while(ADCF == 0);由于其AD转换完成后置位为一,可以进行读取当前转换结果,那么这行代码的作用是等待该位置一,然后进行读数
printf ("\n Value = 0x%bx",ADCRH);
printf ("\n Value = 0x%bx",ADCRL);
Timer0_Delay1ms(100);
之后进行串口打印
完整程序如下:
void main (void)
{
InitialUART0_Timer1(); Enable_ADC_AIN3; // Enable AIN0 P1.7 as ADC input, Find in "Function_define.h" - "ADC INIT"
while()
{
clr_ADCF;
set_ADCS; // ADC start trig signal
while(ADCF == );
printf ("\n Value = 0x%bx",ADCRH);
printf ("\n Value = 0x%bx",ADCRL);
Timer0_Delay1ms();
}
}
当然这只是一个很简单的小程序,如果涉及复杂程序,欢迎交流。
接下来 就是ADC中断部分 首先来讲讲中断使能
每一个中断源都可以通过各自的中断使能位开启或关闭,这些位在IE和EIE特殊功能寄存器SFRs中。有一个全局使能中断EA(IE.7)位,清0将关闭所有中断,置位启用已单独使能了的中断,清0不管单独的中断源,是否使能了都关闭所有中断。注意:当EA为0时有中断请求,所有中断会被挂起直到EA恢复为1,才去执行该中断。所有中断标志位可以用软件置位,也可以用软件启动中断。
注意:每一个中断产生时对应中断标志位都会被置1,不管是通过硬件还是软件。用户在中断服务程序里应该小心处理中断标志位,大多数中断标志位都是写0清除,这样可以避免递归中断请求。

中断服务
中断标志位在每个系统时钟周期都会被采样。在同一个周期内,被采样到的中断和优先级都会被解决。如果满足特定的条件硬件将执行内部产生的LCALL指令,目标地址是中断向量地址。能产生LCALL条件如下:
1. 没有相同或更高优先级中断服务程序在执行。
2.当前查询中断标志周期正好是当前执行指令的最后一个周期。
3. 当前指令不是写任何中断使能位或优先级位且也不能是中断返回指令RETI。
如果以上任何一个条件不满足,就不能产生LCALL指令。在每一个指令周期都会重新检测中断标志。当某个中断标志位被置起,但没有满足上述条件都不会被响应,即使后面满足上述条件,没有立即执行的中断仍然不会执行LCALL指令。这个中断标志生效,但没有进入中断服务程序,下一个指令周期需要重新检测中断标志。
处理器响应一个有效的中断,通过执行一个LCALL 指令将程序转移到中断入口地址。对应的中断标志根据不同的中断源在执行中断服务程序时,可能被硬件清除,也可能不被清除。硬件LCALL与软件LCALL指令相同,执行LCALL指令,保存程序计数器PC内容到堆栈,但不保存程序状态字PSW,PC指针重新装载产生中断的中断向量地址,从向量地址继续执行程序直到执行RETI指令。在执行RETI指令时,处理器弹出堆栈,将栈顶内容加载到程序计数器PC。用户必须注意堆栈的状态,如果堆栈的内容被修改,处理器不会被通知,将会从堆栈加载的地址继续执行。注,RET指令与RETI指令表现相同,但它不会通知中断控制器中断服务已经完成,致使控制器认为中断服务仍在进行。使中断不可能再产生。
中断的目的是让软件处理非常规或异步的事件。N76E003有 4个中断优先级、18个中断源。每个中断源都有独立的优先级、标志位、中断向量和使能位。另外,中断可被全局使能或关闭。当中断发生时,CPU将执行对应的中断服务子程序(ISR)。 ISR被分配到预先指定的地址如中断向量表表20-1.中断向量. 如果中断使能,当中断发生时,CPU 将根据中断源跳转到相应的中断向量地址,执行此地址处的程序,保持中断服务状态直到执行中断服务程序ISR。 一旦ISR 开始执行, 仅能被更高优先级的中断抢占。 ISR 通过指令RETI返回,该指令强迫CPU回到中断发生前所执行指令的下一条指令。
从上表可以看出,EADC是使能ADC中断的指令,所以有了下面的这行代码
#define set_EADC EADC = 1
可寻址指的是这个寄存器中各位值可以直接调用
如:可寻址的IE中有八位EA - ET2 ES ET1 EX1 ET0 EX0可以直接用ET2=1来操作;
不可寻址的TMOD只能用TMOD=0x00来控制其中的各位。N76E003这个寄存器是可寻址的。
void main (void)
{
Set_All_GPIO_Quasi_Mode;
InitialUART0_Timer1();
/*---------------------------------------------------------------
ADC port trig initial setting toggle P0.4 to start ADC
----------------------------------------------------------------*/
Enable_ADC_AIN0; // Enable AIN0 P1.7 as ADC pin
P04_FALLINGEDGE_TRIG_ADC; // P0.4 falling edge as adc start trig signal
// find ADC result in ADC interrupt
set_EADC; // Enable ADC interrupt (if use interrupt)
EA = ; // Enable global interrupt
// set_ADCS; // Trig P04 falling edge to start adc, no need set ADCS bit
while(); // Wait ADC interrupt }
Set_All_GPIO_Quasi_Mode;将引脚设为准双向模式
Enable_ADC_AIN0; 初始化0通道
set_EADC; 打开ADC中断
EA = 1; 打开中断
中断服务函数
void ADC_ISR (void) interrupt
{
clr_ADCF; //clear ADC interrupt flag
printf ("\n Value = 0x%bx",ADCRH);
}
清楚标志,并进行打印高位的数值。
先开始转换然后打开中断,然后进行配置。
N76E003的学习之路(ADC简单小例程篇)的更多相关文章
- N76E003的学习之路(一)
N76E003是8051内核的一款单片机MCU,它提供丰富的特殊功能模块,包括: 1KRAM其中包括256字节SRAM,768字节XRAM. 最多可达18个标准管脚. 两组标准16位定时器/计数器:定 ...
- redis——学习之路五(简单的C#使用redis)
redis官方推荐使用的客户端程序 打星星表示推荐使用的客户端程序,一个笑脸表示最近6个月内有过正式活动的.http://redis.io/clients/#c 从这里我们可以判断官方推荐我们使用Se ...
- Spring学习之路-SpringBoot简单入门
简单讲SpringBoot是对spring和springMVC的二次封装和整合,新添加了一些注解和功能,不算是一个新框架. 学习来源是官方文档,虽然很详细,但是太墨迹了… 地址:https://doc ...
- linux下的学习之路下的小困难
centos下源码安装python3wget --no-check-certificate https://www.python.org/ftp/python/3.6.2/Python-3.6.2.t ...
- #Java学习之路——基础阶段(第一篇)
我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ...
- #Java学习之路——基础阶段(第二篇)
我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ...
- #Java学习之路——基础阶段(第九篇)
我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ...
- Salesforce LWC学习(二十二) 简单知识总结篇二
本篇参看: https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.reactivity_fi ...
- Qt学习之路:自定义Model三篇,自定义委托等等
http://devbean.blog.51cto.com/448512/d-8/p-2
随机推荐
- 自然语言交流系统 phxnet团队 创新实训 个人博客 (十二)
在本项目中关于天空盒子的使用的配置方法: 给场景添加天空盒 第二种方式 在菜单栏中选择:Edit->Render Setting,在保证不在选择场景中其它文件的前提下,Inspector面 ...
- Python之使用PIL实现cv2
有时候使用cv2需要安装opencv,但是opencv安装比较麻烦,因为需要编译过程. 所以,我们可以使用PIL对cv2的一些常用接口进行复现. 这里我们实现了cv2的imread(), imwrit ...
- linux系统下的缺失 libstdc++.so.6: version’GLIBCXX_3.4.20’的问题:
在linux下遇到了一个这样的问题,使用anaconda时,它的安装库里的文件被提示:缺失 libstdc++.so.6: version’GLIBCXX_3.4.20’.后来经过查看资料知道了原来是 ...
- Java如何删除数组中的元素?
Java中,如何删除数组元素? 示例 以下示例显示如何从数组中删除元素. package com.yiibai; import java.util.ArrayList; public class Re ...
- Java如何合并两个数组?
Java中,如何合并两个数组? 示例 本例展示了如何使用List类的List.Addall(array1.asList(array2))方法和Array类的Arrays.toString()方法将两个 ...
- 解决ubuntu上网慢的方法
在ubuntu下用firefox等浏览器上网,往往比在windows下上网要慢好多,但细心的人会发现,慢的时间是花在DNS查找上面了.那么 我们可以在本机缓存DNS,也就是在本机架设一个DNS代理服务 ...
- Sublime Text 3技巧:支持GB2312和GBK编码
From: http://blog.csdn.net/ubuntulover/article/details/21101979 Sublime Text 3与Sublime Text 2的不同 其实有 ...
- crontab(定时任务操作)
定时任务顾名思义就是在某一时间点自动进行任务操作.在做Pgsql的备份利用crontab进行定时操作, 使用起来比较方便.故分享具体的定时编辑命令:crontab -e 首先从crontab的文件分析 ...
- dropwizard metrics - 基本使用介绍
之前在healthcheck中介绍了怎样通过metrics lib往系统中增加一些简单的健康侦測.如今讲讲dropwizard metrics更重要的部分.记录系统的度量信息. dropwizard提 ...
- 内存管理 初始化(三)before mm_init()
看到了mm_init(),期间将从bootmem迁移到伙伴系统,slab分配器也会建立. 在分析mm_init()之前,把setup_arch(&command_line)之后的函数分析了以下 ...
