实例:将1/3的的电压值通过ADC转化为数字信号,再将其通过串口信号发送到PC
·(芯片内部ADC,寄存器相对少一些)
·设置ADC的源电压为1/3电源电压(电源电压为3.3v),因此大概为1.1v。
·然后通过CC2530的ADC功能将获得模拟的电压值,通过相应公式转换为数字信号
·再由串口将数字信号打印到PC终端上
一、寄存器配置
①ADCCON1——ADC控制1
`EOC[7]: 转换完成,该位赋值为1,读取ADCH时,他就被清除。(开启转换后每次判断该位是否为1。想要清除该为,需要读取ADCH)
`ST[6]:开启转换,设置该位为1,前提是STSEL[5:4]的位为11。
`STSEL[5:4]:开启转换事件
因此想开启一个A/D转换就设置:ADCCON1 |=0x40;//启动A/D
(0x40, -> 0100 0000, |= 就是让6位设为1,其他位不变)
关闭A/D转换就设置:ADCCON1 &=~0x40;
(~0x40, -> 0100 0000->取反1011 1111,&=就是6位设为0,其他位不变)
②ADCCON3——ADC控制3
· ECH[3:0] :选择ADC触发的单个转换所在的通道号,本例选择VDD5 /3,设该位为1111。
(单个通道选择。选择ADCCON3触发的单个转换所在的通道号码。当单个转换完成,该位自动清除)
· EDIV[5:4]:设置抽取率,即设精度位12位,设该位为11。
·EREF[7:6] :选择用于额外转换的参考电压。本例选择AVDD5引脚,该位设为10
因此设置ADCCON3 = 0xbf; (1011 1111,即十六进制的0xbf)
③ADCL、ADCH 数据低、高位寄存器
·ADCL:0、1位无效的,没有使用读出来一直是0。2到7位对应的是ADC转换结果真正的值的0到5位
·ADCH:0到7位对应ADC转换结果的高位部分6到13位
二、ADC驱动编写步骤
1、清除EOC标志 ->读取ADCH
2、设置参考电源电压、抽取率、ADC通道 ->设置ADCCON3
3、是能A/D转换 ->设置ADCCON1
4、等待转换完毕
->等待转换完毕,由于转换完成,则ADCCON1的最高位第七位会被赋值为1,因此通过判断ADCCON1的最高位是否设置为1了,即while(!(ADCCON1&0x80);
5、读取数据 ->读取ADCL/ADCH 这两个寄存器的值
6、转换成模拟值 ->根据前面设置的抽取率来进行转换
三、编写代码
void InitalAD(void)
{
//初始化LED
P1DIR = 0x03; //P1控制LED
led1 = 1;
led2 = 1; //关LED
//ADC驱动编写
ADCH &= 0x00; //通过读取ADCH,清除EOC标志
ADCCON3 = 0xbf; //通过设置ADCCON3寄存器,其中6、7位设置为:10,参考电源电压AVDD5。其中4、5位设置为:11,抽取率为512。其中0到3位设置为:1111,ADC通道选择VDD/3。
即1011 1111-> 0xbf
//使能转换A/D
ADCCON1 = 0X30; //0011 0000 (DEC:48),A/D状态仍是停止,只是启动了选择,设置了STSEL的位
ADCCON1 |= 0x40; //0100 0000 (DEC:64),启动A/D
}
//循环读取ADC数据
while(1)
{
//判断转换是否完成,即ADCCON1高位(第七位)是否设置为1,如果ADCCON1 >=0x80那么第七位肯定设为1,转换完成
if(ADCCON1>=0x80)
{
led1 = 1; //转换完毕指示
//读取数据(拼接数据)
reading = ADCL;
reading = ADCH << 8;
reading >>= 2;
ADCCON1 = 0x40; //开启下一次转换
//转换为模拟值
num = (float)(reading)*3.3/8192; //定参考电压为3.3v,切分份数8192,读取的值除以8192得到所占比例,再乘以3.3得到模拟值
//通过串口发送给PC
sprintf(strTemp,"vol:%.02fv",num); //将模拟值存到了字符串中。%.02f :小数点后精确带2位,不足位补0
UartSendString(strTemp,12); //串口送数
DelayMS(1000);
led1 = 1; //完成数据处理
DelayMS(1000);
}
}
完整代码:
/****************************************************************************
* 文 件 名: main.c
* 描 述: 将 1/3 电压值通过 ADC 转换为数字信号,再将其通过串口发送到 PC
****************************************************************************/
#include <stdio.h>
#include <string.h>
#include "UartTimer.h"
//定义控制灯的端口
#define led1 P1_0
#define led2 P1_1
#define BEEP P0_0 //定义P0.0定义为蜂鸣器控制口
/****************************************************************************
* 名 称: InitBeep()
* 功 能: 初始化蜂鸣器,默认关闭
* 入口参数: 无
* 出口参数: 无
****************************************************************************/
void InitBeep(void)
{
P0DIR |= 0x01; //P0.0定义为输出口
BEEP = 0; //蜂鸣器灭
}
/****************************************************************************
* 名 称: InitSensor()
* 功 能: AD初始化函数
* 入口参数: 无
* 出口参数: 无
****************************************************************************/
void InitialAD(void)
{
P1DIR = 0x03; //P1 控制 LED
led1 = 1;
led2 = 1; //关 LED
ADCH &= 0X00; //清 EOC 标志 ADCCON1.EOC位是一个状态位,当一个转换结束时,设置为高电平;当读取ADCH时,它就被清除。
ADCCON3=0xbf; //单次转换,参考电压为电源电压,对 1/3 VDD 进行 A/D 转换
//14 位分辨率bf
ADCCON1 = 0X30; //停止 A/D
ADCCON1 |= 0X40; //启动 A/D
}
/****************************************************************************
* 程序入口函数
****************************************************************************/
void main(void)
{
char temp[2];
float num;
char strTemp[12]={0};
unsigned short reading;
InitBeep();
DISABLE_ALL_INTERRUPTS(); //关闭所有中断
InitClock(); //设置系统主时钟为 32M
InitUART(); //初始化串口
InitialAD();
led1 = 1;
//10bite
ADCCON3=0xaf;
while(1)
{
if(ADCCON1>=0x80)
{
led1 = 0; //转换完毕指示
reading = ADCL;
reading |= ADCH << 8;
reading >>= 5;
ADCCON1 |= 0x40; //开始下一转换
num = (float)(reading)*3.3/1024; //有一位符号位,取 2^10;
//定参考电压为 3.3V。 14 位精确度
sprintf(strTemp,"vol:%.02fV", num);//将浮点数转成字符串
UartSendString(strTemp,12); //串口送数
//包括空格
DelayMS(1000);
led1 = 1; //完成数据处理
DelayMS(1000);
}
}