前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CC2530基础实验五 ADC转换实验

CC2530基础实验五 ADC转换实验

作者头像
w候人兮猗
发布2020-07-01 17:34:14
2.9K0
发布2020-07-01 17:34:14
举报

####一、任务分析

编写程序实现实验板测定芯片外部光敏传感器的电压,通过串口发送电压值。实验板安装上光线传感器,光线的强弱转换成电压的高低,经ADC转换以后通过串口将电压值发送给PC,可以通过串口调试软件读取电压值。每发送一次电压值的字符串消息,LED1闪亮一次。具体工作方式如下:

①通电后LED1熄灭。 ②UART0初始化。 ③设置ADC。 ④LED1点亮。 ⑤开启单通道ADC。 ⑥ADC对通道0进行模数转换测量电压。 ⑦发送字符串“光照传感器电压值”与测量电压值。 ⑧LED1熄灭。 ⑨延时一段时间,延时时间可以设置为3秒。 ⑩返回步骤④循环执行。

1.电信号的形式与转换 信息是指客观事物属性和相互联系特性的表征,它反映了客观事物的存在形式和运动状态。表示信息的形式可以是数值、文字、图形、声音、图像以及动画等。信号是信息的载体,是运载信息的工具,信号可以是光信号、声音信号、电信号。电话网络中的电流就是一种电信号,人们可以将电信号经过发送、接收以及各种变换,传递着双方要表达的信息。数据是把事件的属性规范化以后的表现形式,它能被识别,可以被描述,是各种事物的定量或定性的记录。信号数据可以表示任何信息,如文字、符号、语音、图像、视频等等。 从电信号的表现形式上,可以分为模拟信号和数字信号。

(1)模拟信号 模拟信号是指用连续变化的物理量所表达的信息,如温度、湿度、压力、长度、电流、电压等等,我们通常又把模拟信号称为连续信号,它在一定的时间范围内可以有无限多个不同的取值。 (2)数字信号 数字信号指自变量是离散的、因变量也是离散的信号,这种信号的自变量用整数表示,因变量用有限数字中的一个数字来表示,在计算机中,数字信号的大小常用有限位的二进制数表示。由于数字信号是用两种物理状态来表示0和1的,故其抵抗材料本身干扰和 和环境干扰的能力都比模拟信号强很多;在现代技术的信号处理中,数字信号发挥的作用越来越大,几乎复杂的信号处理都离不开数字信号,只要能把解决问题的方法用数学公式表示,就能用计算机来处理代表物理量的数字信号。 (3)模拟/数字转换 模拟/数字转换通常简写为ADC,是将输入的模拟信号转换为数字信号。各种被测控的物理量(如:速度、压力、温度、光照强度、磁场等)是一些连续变化的物理量,传感器将这些物理量转换成与之相对应的电压和电流就是模拟信号。单片机系统只能接收数字信号,要处理这些信号就必须把他们转换成数字信号。模拟/数字转换是数字测控系统中必须的信号转换。

2.CC2530的ADC模块 CC2530的ADC模块支持最高14位二进制的模拟数字转换,具有12位的有效数据位。它包括一个模拟多路转换器,具有8个各自可配置的通道;以及一个参考电压发生器。转换结果通过DMA写入存储器,还具有多种运行模式。ADC模块结构如图6-1所示。 CC2530的ADC模块有如下主要特征:

可选的抽取率,设置分辨率(7到12位) 8个独立的输入通道,可接收单端或差分信号 参考电压可选为内部单端、外部单端、外部差分或AVDD5 转换结束产生中断请求 转换结束时可发出DMA触发  可以将片内温度传感器作为输入  电池电压测量功能

3.ADC的工作模式

(1)ADC模块的输入 对于CC2530的ADC模块,端口P0引脚可以配置为ADC输入端,依次为AIN0~AIN7。可以把输入配置为单端或差分输入。在选择差分输入的情况下,差分输入包括输入对AIN0-AIN1、AIN2-AIN3、AIN4-AIN5和AIN6-AIN7。除了输入引脚AIN0-AIN7,片上温度传感器的输出也可以选择作为ADC的输入用于温度测量;还可以输入一个对应AVDD5/3的电压作为一个ADC输入,在应用中这个输入可以实现一个电池电压监测器的功能。特别提醒,负电压和大于VDD(未调节电压) 的电压都不能用于这些引脚。它们之间的转换结果是在差分模式下每对输入端之间的电压差值。 8位模拟量输入来自I/O引脚,不必通过编程将这些引脚变为模拟输入,但是,当相应的模拟输入端在APCFG寄存器中被禁用时,此通道将被跳过。当使用差分输入时,相应的两个引脚都必须在APCFG寄存器中设置为模拟输入引脚。APCFG寄存器如表6-1所示。 (2)序列ADC转换与单通道ADC转换 CC2530的ADC模块可以按序列进行多通道的ADC转换,并把结果通过DMA传送到存储器,而不需要CPU任何参与。 转换序列可以由APCFG寄存器设置,八位模拟输入来自I/O引脚,不必经过编程变为模拟输入。如果一个通道是模拟I/O输入,它就是序列的一个通道,如果相应的模拟输入在APCFG中禁用,那么此I/O通道将被跳过。当使用差分输入,处于差分对的两个引脚都必须在APCFG寄存器中设置为模拟输入引脚。 寄存器位ADCCON2.SCH用于定义一个ADC转换序列。如果ADCCON2.SCH设置为一个小于8的值,ADC转换序列包括从0通道开始,直到并包括ADCCON2.SCH所设置的通道号码。当ADCCON2.SCH设置为一个在8和12之间的值,转换序列包括从通道8开始差分输入,到ADCCON2.SCH所设置的通道号码结束。 除可以设置为按序列进行ADC转换之外,CC2530的ADC模块可以编程实现任何单个通道执行一个转换,包括温度传感器(14)和AVDD5/3(15)两个通道。单通道ADC转换通过写ADCCON3寄存器触发,转换立即开始。除非一个转换序列已经正在进行,在这种情况下序列一完成,单个通道的ADC转换就会被执行。

####二、初始化 1、定义结果变量; unsigned long value; //无符号long类型 2、ADC初始化 APCFG |= 1; //模拟 I/O 使能 P0SEL |= 0X01; //片上外设 P0DIR &= ~0X01; //设置输入模式 ADCIF = 0; //ADC中断标志位 3、参考电压、分辨率、序列通道选择(ADCCON2/ADCCON3) ADCCON3 = 0X90; //AVDD5引脚;9位分辨率; 3、采用基准电压 acdd5: 3.3v,通道0, 启动 AD 转换 ADCCON3 = (0x80 | 0x10 | 0x00); 4、等待ADC转换结束 while(!ADCIF); 5、得到的数据放到变量value 中 value = ADCH; value = value << 8; value |= ADCL; value = value*330; //电压值 = (value * 3.3) / 32768 value = value >>15; // value * 330 是为了后面处理数据所以多乘 100 6、返回value值 unsigned short 类型 return value;

这里写图片描述
这里写图片描述

ADC数据处理(光电传感器)

buf[0] = val / 100 + ‘0’; buf[1] = ‘.’; buf[2] = val / 10 % 10 + ‘0’; buf[3] = val % 10 + ‘0’; buf[4] = ‘V’; buf[5] = ‘\n’;

寄存器

代码语言:javascript
复制
ADCCON1
    选择ADC的启动模式和开启AD转换
    例如:设置ADC的启动模式为手动,并开启AD转换
      ADCCON1 |= 0X30;   //选择ADC的启动模式为手动
      ADCCON1 |= 0X40;   //开启AD转换
这里写图片描述
这里写图片描述

ADCCON2 选择内部参考电压;分辨率;多通道选择 与ADCCON3的区别是单/多通道的选择,其他配置相同。

这里写图片描述
这里写图片描述
代码语言:javascript
复制
ADCCON3
选择内部参考电压;分辨率;单通道选择
与ADCCON3的区别是单/多通道的选择,其他配置相同。
例如:选择内部参考电压;12位分辨率;对片内温度传感器采样
  ADCCON3 = 0X3E;
这里写图片描述
这里写图片描述
代码语言:javascript
复制
ADCL、ADCH
注意:低8位的0、1位一直为0;
这里写图片描述
这里写图片描述

APCFG

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

ADCIF ADC中断标志

这里写图片描述
这里写图片描述

###代码实现 /* 包含头文件 */ #include “ioCC2530.h” #include <string.h>

代码语言:javascript
复制
#define LED1 P1_0     // P1_0定义为P1_0  led灯端口
#define uint16 unsigned short
#define uint32 unsigned long
#define uint unsigned int

unsigned int flag,counter=0; //统计溢出次数
unsigned char s[8];//定义一个数组大小为8

void InitLED()
{
    P1SEL&=~0X01;          //P1_0设置为普通的IO口 1111 1110
    P1DIR |= 0x01;              //配置P1_0的方向为输出
    LED1=0;
}

void adc_Init(void)
{
    APCFG  |=1;
    P0SEL  |= 0x01; 
    P0DIR  &= ~0x01;    
}
/************************************************************
* 名称       get_adc
* 功能       读取ADC通道0电压值
* 入口参数   无
* 出口参数   16位电压值,分辨率为10mV
***************获取ADC通道0电压值************************/
uint16 get_adc(void)
{
    uint32 value;
    ADCIF = 0;   //清ADC 中断标志
    //采用基准电压avdd5:3.3V,通道0,启动AD转化
    ADCCON3 = (0x80 | 0x10 | 0x00);
    while ( !ADCIF )
    {
        ;  //等待AD转化结束
    }
    value = ADCH;
    value = value<< 8;
    value |= ADCL;
    // AD值转化成电压值
    // 0 表示 0V ,32768 表示 3.3V
    // 电压值 = (value*3.3)/32768 (V)
    value = (value * 330);
    value = value >> 15;   // 除以32768
    // 返回分辨率为0.01V的电压值
    return (uint16)value;
}
/**********串口通信初始化************************/
void initUART0(void)
{
    PERCFG = 0x00;  
    P0SEL = 0x3c;   
    U0CSR |= 0x80;
    U0BAUD = 216;
    U0GCR = 10;
    U0UCR |= 0x80;
    UTX0IF = 0;  // 清零UART0 TX中断标志
    EA = 1;   //使能全局中断
}

/*************************************************
* 函数名称:inittTimer1
* 功    能:初始化定时器T1控制状态寄存器
******************定时器初始化*****************************/
void inittTimer1()
{
    CLKCONCMD &= 0x80;   //时钟速度设置为32MHz
    T1CTL = 0x0E;    // 配置128分频,模比较计数工作模式,并开始运行
    T1CCTL0 |= 0x04;  //设定timer1通道0比较模式
    T1CC0L =50000 & 0xFF;    // 把50000的低8位写入T1CC0L
    T1CC0H = ((50000 & 0xFF00) >> 8); //把50000的高8位写入T1CC0H

    T1IF=0;           //清除timer1中断标志(同IRCON &= ~0x02)
    T1STAT &= ~0x01;  //清除通道0中断标志

    TIMIF &= ~0x40;  //不产生定时器1的溢出中断
    //定时器1的通道0的中断使能T1CCTL0.IM默认使能
    IEN1 |= 0x02;    //使能定时器1的中断
    EA = 1;        //使能全局中断
}
/***********************************************************
* 函数名称:UART0SendByte
* 功    能:UART0发送一个字节
* 入口参数:c
* 出口参数:无
* 返 回 值:无
************************************************************/
void UART0SendByte(unsigned char c)
{
    U0DBUF = c;     // 将要发送的1字节数据写入U0DBUF
    while (!UTX0IF) ;  // 等待TX中断标志,即U0DBUF就绪
    UTX0IF = 0;       // 清零TX中断标志
}

/**************************************************************
* 函数名称:UART0SendString
* 功    能:UART0发送一个字符串
* 入口参数:*str
* 出口参数:无
* 返 回 值:无
**********************************************************/
void UART0SendString(unsigned char *str)
{
    while(*str != '\0')
    {
        UART0SendByte(*str++);   // 发送一字节
    }
}

/**************获取电压值并处理数据******************/
void Get_val()
{
    uint16 sensor_val;
    sensor_val=get_adc();
    s[0]=sensor_val/100+'0';
    s[1]='.';
    s[2]=sensor_val/10%10+'0';
    s[3]=sensor_val%10+'0';
    s[4]='V';
    s[5]='\n';
    s[6]='\0';
}
/******************************************
* 功    能:定时器T1中断服务子程序
************************************/
#pragma vector = T1_VECTOR //中断服务子程序
__interrupt void T1_ISR(void)
{
    EA = 0;   //禁止全局中断
    counter++;
    T1STAT &= ~0x01;  //清除通道0中断标志
    EA = 1;   //使能全局中断
}
/******************************************
* 函数名称:main
* 功    能:main函数入口
* 入口参数:无
* 出口参数:无
* 返 回 值:无
**************************************************/
void main(void)
{
    InitLED();
    inittTimer1();  //初始化Timer1
    initUART0();  // UART0初始化
        adc_Init(); // ADC初始化
    while(1)
    {
        if(counter>=15)     //定时器每0.2S溢出中断计次
           {
            counter=0;       //清标志位
            LED1 = 1;    //指示灯点亮
            Get_val();
            UART0SendString("光照传感器电压值  ");
            UART0SendString(s); 
            LED1 = 0;    //指示灯熄灭
            }
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年3月28日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档