/**********************************************************************************************************************************************************
* 文 件 名:ADC.c
×
* 功 能:实验九 ADC实验
*
* CC2530内部包含一个ADC,它支持最高达12位的模拟到数字的转换。该ADC包含一个模拟多路复用器支持最高达8
* 路的独立可配置通道、参考电压产生器,转换结果通过DMA被写入存储器。支持多种运行模式。
*
* ADC的主要特性如下:
* 1. 可选择的抽取率,这也将决定分辨率(7到12位);
* 2. 8个独立的输入通道,单端或差分;
* 3. 参考电压可选择为内部、外部单端、外部差分或AVDD_SOC;
* 4. 可产生中断请求;
* 5. 转换结束时DMA触发;
* 6. 温度传感器输入;
* 7. 电池测量。
*
* ADC输入
* P0端口引脚上的信号可被用来作为ADC输入。在以下的描述中,我们将这些引脚记为AIN0-AIN7引脚。输入引脚
* AIN0-AIN7被连接到ADC。ADC可被设置为自动执行一个转换序列,当该序列被完成时可随意地从任一通道执行
* 一个附加的转换。
* 输入可被配置为单端或差分输入。当使用差分输入时,差分输入由输入组AIN0-1、AIN2-3、AIN3-4、AIN4-5和
* AIN6-7组成。注意:负电压不能被连接到这些引脚,大于VDD的电压也不能被连接到这些引脚。
* 除了输入引脚AIN0-AIN7外,一个片上温度传感器的输出可被选择作为ADC的一个输入用来进行温度测量。还可以
* 选择相当于AVDD_SOC/3的电压作为ADC的一个输入。该输入可被用来进行电池监测。
* 所有这些输入引脚的配置可通过寄存器ADCCON2.SCH进行配置。
*
* ADC转换序列
* ADC可执行一个转换序列并将结果传送到存储器(通过DMA)而不需要与CPU进行任何互操作。转换序列可被ADCCFG
* 寄存器影响,因为来自于IO引脚的ADC的8个模拟输入不必全部被编程作为模拟输入。如果一个通道作为一个序列
* 的一部分,但相应的模拟输入在ADCCFG中被禁止,那么该通道将被跳过。对于通道8到12,输入引脚必须被使能。
* ADCCON2.SCH寄存器位被用来定义一个来自ADC输入的ADC转换序列。当ADCCON2.SCH被设置为小于8的值时,一个
* 转换序列将包含从0到该值的所有通道。
* 单端输入AIN0到AIN7由ADCCON2.SCH中的通道号0到7来表示。通道号8到11分别表示差分输入AIN0-1、AIN2-3、
* AIN4-5和AIN6-7。通道号12到15分别表示GND、内部参考电压、温度传感器和AVDD_SOC/3。
* 当ADCCON2.SCH被设置为一个8到12之间的值时,转换序列将从通道8开始。对于更高的设置值,只进行单一的转换。
* 除了转换序列外,ADC可被编程为一旦转换序列完成,可以从任一通道执行一次单一转换。这被称为附加转换,由
* ADCCON3寄存器控制。
*
* ADC运行模式
* ADC有3个控制寄存器:ADCCON1、ADCCON2和ADCCON3。这些寄存器被用来配置ADC和报告状态。
* ADCCON1.EOC位是一个状态位,当一个转换结束时该位被设置为高,当ADCH被读取时该位被清零。
* ADCCON1.ST位被用来开始一个转换序列。当该位被设置为高、ADCCON1.STSEL为11并且当前没有转换在运行时,一
* 个转换序列将开始。当该转换序列被完成时该位被自动清零。
* ADCCON1.STSEL位被用来选择哪一个事件将开始一个新的转换序列。可被选择的事件有:外部引脚P2_0上的上升沿
* 信号、前一个转换序列结束、定时器1通道0比较事件和ADCCON1.ST位被设置为1。
* ADCCON2寄存器控制如何执行一个转换序列。
* ADCCON2.SREF被用来选择参考电压。参考电压只能在没有转换在进行的时候被改变。
* ADCCON2.SDIV被用来选择抽取率(分辨率、完成一次转换所需时间和采样率)。抽取率只能在没有转换在进行的时候
* 被改变。
* ADCCON2.SCH被用来选择一个转换序列中的最后一个通道。
* ADCCON3寄存器用来控制附加转换的通道号、参考电压和抽取率。在ADCCON3寄存器被更新后,附加转换将立刻发生。
* ADCCON3寄存器的位定义与ADCCON2寄存器的位定义非常相似。
*
* ADC转换结果
* 数字转换结果由二进制补码形式表示。对于单端输入,结果将总为正的。当输入振幅等于VREF(选定的参考电压)时
* 转换结果将达到最大值。对于差分输入,两引脚之间的差值被转换,该值可以是负的。对于12位分辨率,当模拟输
* 入等于VREF时数字转换结果为2047;当模拟输入等于-VREF时数字转换结果为-2048。
* 当ADCCON1.EOC被设置为1时,数字转换结果可从ADCH和ADCL中得到。
* 当ADCCON2.SCH位被读取时,读取值将指示通道号,在ADCH和ADCL中的转换结果是该通道之前的那个通道的转换结果。
* 例如,当从ADCCON2.SCH中读取的值为0x1,这意味着转换结果是来自于AIN0。
*
* ADC参考电压
* 模/数转换的正参考电压是可选择的。内部产生的1.25V电压、AVDD_SOC引脚上的电压、连接到AIN7引脚上的外部电压
* 或连接到AIN6-7输入的差分电压都可以作为正参考电压。
* 为了进行校准,可以选择参考电压作为ADC的输入进行参考电压的转换。类似的,可以选择GND作为ADC的输入。
*
* ADC转换时间
* 当在32MHz系统时钟下,该时钟被8分频后产生一个4MHz的时钟供ADC运行。三角积分调变器和抽取滤波器都是用4MHz
* 时钟进行计算。使用其他的频率将会影响结果和转换时间。以下描述我们假设使用32MHz系统时钟。
* 执行一次转换所需要的时间取决于所选择的抽取率。例如,当抽取率被设置为128时,抽取滤波器使用128个4MHz时钟
* 周期来计算结果。当一个转换开始后,输入多路复用器需要16个4MHz时钟周期来稳定。16个4MHz时钟周期的稳定时间
* 适用于所有抽取率。因此一般而言,转换时间由下式给定:Tconv = (抽取率 + 16) ×0.25us。
*
* ADC中断
* 当一个附加转换完成时ADC将产生一个中断。当来自转换序列的一个转换完成时将不会产生中断。
*
* ADC DMA触发
* 当来自一个转换序列的每一个转换完成时ADC将产生一个DMA触发。当一个附加转换完成时不产生DMA触发。首次在
* ADCCON2.SCH中定义的8个通道的每一个都有一个DMA触发。当一个新的采样就绪时DMA触发被激活。另外,还有一个
* DMA触发ADC_CHALL,当ADC转换序列中的任何通道有新数据就绪时该触发被激活。
*
* 本实验将使用CC2530内部的ADC,当调节OURS-CC2530开发板上的电位器时,输出电压(连接到CC2530的AIN0和AIN01)
* 被采样转换然后在LCD上显示电压值。
*
* 在\include\hal.h文件中包含了和ADC相关的一些宏,用户使用这些宏
* 可以简化对ADC的操作,提高代码的可读性,本实验中就使用了其中的一些宏。
*
* 注 意:本实验所需硬件资源:
* OURS-CC2530RF板
* 带LCD的智能主板
* 注意:进行该实验时,智能主板上不能插其他传感板。
*
*
* 版 本:V1.0
* 作 者:wuxianhai
* 日 期:2011.2.14
* 奥尔斯科技主页:www.ourselec.com
**********************************************************************************************************************************************************/
#include "hal.h"
#include "LCD.h"
#include "stdio.h"
/**************************************************************************************************
* 函数名称:halWait
*
* 功能描述:延时函数(不精确延时)
*
* 参 数:wait -- 延时时间
*
* 返 回 值:无
**************************************************************************************************/
void halWait(BYTE wait)
{
UINT32 largeWait;
if(wait == 0)
{return;}
largeWait = ((UINT16) (wait << 7));
largeWait += 114*wait;
largeWait = (largeWait >> CLKSPD);
while(largeWait--);
return;
}
/**************************************************************************************************
* 函数名称:scaleValue
*
* 功能描述:根据当前VDD值量化ADC值。
*
* 参 数:adc_value ADC值
*
* 返 回 值:量化值(输出电压)
**************************************************************************************************/
#define VDD 33 // 该值要根据AVDD_SOC引脚上的电压来调整
INT8 scaleValue(INT8 adc_value)
{
float v;
adc_value = (adc_value > 0 ? adc_value : 0); // 若输入参数adc_value小于0,则adc_value=0
// 因为单端输入的电压值应该在0到正参考电压值之间,不能为负
v = ((float)adc_value / (float)0x7F);
v *= VDD;
return (INT8)v;
}
/**************************************************************************************************
* 函数名称:main
*
* 功能描述:采样AIN0和AIN1上的电压,转换后在LCD上显示。
*
* 参 数:无