zoukankan      html  css  js  c++  java
  • CC2530ADC转换

    一、ADC简介

                ADC支持 14 位的模拟数字转换,具有多达12 位的 ENOB(有效数字位)。它包括一个模拟多路转换器,具有多达8 个各自可配置的通道,以及一个参考电压发生器。转换结果通过DMA写入存储器。还具有若干运行模式。

    二、A/D转换的基本工作原理

    将时间上连续变化的模拟量转化为脉冲有无的数字量,这一过程就叫做数字化,实现数字化的关键设备是ADC

            ADC:数模转换器,将时间和幅值连续的模拟量转化为时间和幅值离散的数字量,A/D转换一般要经过采样保持量化编码4个过程。

    三、CC2530的A/D转换模块

    ADC的主要特性如下:

    ● 可选的抽取率,这也设置了分辨率(7 到 12 位)

    ● 8 个独立的输入通道,可接受单端或差分信号

    ● 参考电压可选为内部单端、外部单端、外部差分或 AVDD5

    ● 产生中断请求

    ● 转换结束时的 DMA 触发

    ● 温度传感器输入

    ● 电池测量功能

    四、一些关于ADC的概念

    <1> 序列ADC转换:可以按序列进行多通道的ADC转换,并把结果通过DMA传送到存储器,而不需要CPU任何参与。

            <2> 单通道ADC转换:在程序设计中,通过写ADCCON3寄存器触发单通道ADC转换,一旦寄存器被写入,转换立即开始。

            <3> 参考电压:内部生成的电压、AVDD5引脚、适用于AIN7输入引脚的外部电压,或者 适用于AIN6~AIN7输入引脚的差分电压。

            <4> 转换结果:数字转换结果以2的补码形式表示。对于单端,结果总是正的。对于差分配置,两个引脚之间的差分被转换,可以是负数。 当ADCCON1.EOC设置为1时,数字转换结果可以获得,且结果总是驻留在ADCH和ADCL寄存器组合的MSB段中。

            <5> 中断请求:通过写ADCCON3触发一个单通道转换完成时,将产生一个中断,而完成 一个序列转换时,是不产生中断的。当每完成一个序列转换,ADC将产生 一个DMA触发。

            <6> 寄存器:ADC有两个数据寄存器:ADCLADCH;三个控制寄存器:ADCCON1ADCCON2ADCCON3;分别用来配置ADC并返回转换结果。

    五、ADC模块的信号输入

     端口0引脚可以配置为ADC输入端,依次为AIN0~AIN7

    <1> 可以把输入配置为单端输入或差分输入。

    <2> 在选择差分输入的情况下,差分输入对:AIN0~AIN1、AIN2~AIN3、AIN4~AIN5、AIN6~AIN7。

    <3>除了输入引脚 AIN0-AIN7,片上温度传感器的输出也可以选择作为 ADC的输入,用于温度测量。

    <4> 可以将一个对应AVDD5/3的电压作为ADC输入,实现电池电压监测。

    <5> 负电压和大于VDD的电压都不能用于这些引脚。

    <6> 单端电压输入AIN0~AIN7,以通道号码0~7表示;四个差分输入对则以 通道号码8~11表示;温度传感器的通道号码为14AVDD5/3电压输入的通道号码为15

    题目:定时采集电压数据发送到上位机

    将光照度传感器接到的Zigbee小模块上,每隔1秒以单通道的传送到上位机。上位机与CC2530的 串口0相连,系统时钟为传送到上位机。上位机与CC2530的 串口0相连,系统时钟为16MHz,波特率为9600BPS,发送数据采用查询的方式。数据帧有4个字节,格式如下: 0xFA (帧头) ADCH ADCL 0xAF (帧尾)

    思路:

    1.初始化定时器1,实现0.1秒定时。

     1 void Init_Timer1()
     2 {
     3   T1CC0L = 0xd4;        //设置最大计数值的低8位
     4   T1CC0H = 0x30;        //设置最大计数值的高8位
     5   T1CCTL0 |= 0x04;      //开启通道0的输出比较模式
     6   T1IE = 1;             //使能定时器1中断
     7   T1OVFIM = 1;          //使能定时器1溢出中断
     8   EA = 1;               //使能总中断
     9   T1CTL = 0x0e;         //分频系数是128,模模式
    10 }

    2.在定时中断函数中实现1秒定时。

     1 unsigned char count = 0;
     2 unsigned char F_time = 0;
     3 /*================定时器1服务函数====================*/
     4 #pragma vector = T1_VECTOR
     5 __interrupt void Timer1_Sevice()
     6 {
     7   T1STAT &= ~0x01;      //清除定时器1通道0中断标志
     8   count++;
     9   if(count == 10)       //定时1秒到
    10   {
    11     F_time = 1;
    12     count = 0;
    13   }
    14 }

    3.按照参数要求初始化串口0。

     1 void Init_Uart0()
     2 {
     3   PERCFG = 0x00;    //串口0的引脚映射到位置1,即P0_2和P0_3
     4   P0SEL = 0x0C;     //将P0_2和P0_3端口设置成外设功能
     5   U0BAUD = 59;      //16MHz的系统时钟产生9600BPS的波特率
     6   U0GCR = 9;
     7   U0UCR |= 0x80;    //禁止流控,8位数据,清除缓冲器
     8   U0CSR |= 0xC0;    //选择UART模式,使能接收器
     9   UTX0IF = 0;       //清除TX发送中断标志
    10   URX0IF = 0;       //清除RX接收中断标志
    11   URX0IE = 1;       //使能URAT0的接收中断
    12   EA = 1;           //使能总中断
    13 }

    4.设计字节数组发送函数。

    unsigned char dat[4];
    /*===================UR0发送字符串函数==================*/
    void UR0SendString(unsigned char *str, unsigned char count)
    {
      while(count--)       
      {
        U0DBUF = *str++;    //将要发送的1字节数据写入U0DBUF
        while(!UTX0IF);     //等待TX中断标志,即数据发送完成
        UTX0IF = 0;  
      }
    }

    5.初始化ADC (单通道采集)。

    配置APCFG寄存器

            当使用ADC时,端口0的引脚必须配置为ADC模拟输入。要配置一个端口0引脚为一个ADC输入,APCFG寄存器中相应的位必须设置为1。这个寄存器的默认值是0,选择端口0为非模拟输入,即作为数字I/O端口。

            注意:APCFG寄存器的设置将覆盖P0SEL的设置。

    主要对端口的功能进行选择,设置其传输方向,并将端口设置为模拟输入。

    1 void Init_ADC0()
    2 {
    3   P0SEL |= 0x01;      //P0_0端口设置为外设功能
    4   P0DIR &= ~0x01;     //P0_0端口设置为输入端口
    5   APCFG |= 0x01;      //P0_0作为模拟I/O使用
    6 }

    6.实现数据采集并发送到上位机。

     

    配置ADCCON3寄存器

            单通道的ADC转换,只需将控制字写入ADCCON3寄存器即可。

    例子:ADCCON3 = (0x80 | 0x10 | 0x00); //参考电压选择AVDD5引脚,256 抽取率,AINO通道0

    首先将ADCIF标志位清0,接着对ADCCON3寄存器设置,该寄存器一旦被写入,转换立即开启;然后等待ADCIF置1,这时候转换完成,读取数据即可。

     1 /*===================读取ADC的数据====================*/
     2 void Get_ADC0_Value()
     3 {
     4   ADCIF = 0;
     5   //参考电压选择AVDD5引脚,256抽取率,AIN0通道0
     6   ADCCON3 = (0x80 | 0x10 | 0x00);
     7   while(!ADCIF);      //等待A/D转换完成,
     8   dat[0] = 0xaf;
     9   dat[1] = ADCH;      //读取ADC数据低位寄存器
    10   dat[2] = ADCL;      //读取ADC数据高位寄存器
    11   dat[3] = 0xfa;
    12 }

    完整代码:

     1 #include "ioCC2530.h"
     2 /*===============定时器1初始化函数==================*/
     3 void Init_Timer1()
     4 {
     5   T1CC0L = 0xd4;        //设置最大计数值的低8位
     6   T1CC0H = 0x30;        //设置最大计数值的高8位
     7   T1CCTL0 |= 0x04;      //开启通道0的输出比较模式
     8   T1IE = 1;             //使能定时器1中断
     9   T1OVFIM = 1;          //使能定时器1溢出中断
    10   EA = 1;               //使能总中断
    11   T1CTL = 0x0e;         //分频系数是128,模模式
    12 }
    13 unsigned char count = 0;
    14 unsigned char F_time = 0;
    15 /*================定时器1服务函数====================*/
    16 #pragma vector = T1_VECTOR
    17 __interrupt void Timer1_Sevice()
    18 {
    19   T1STAT &= ~0x01;      //清除定时器1通道0中断标志
    20   count++;
    21   if(count == 10)       //定时1秒到
    22   {
    23     F_time = 1;
    24     count = 0;
    25   }
    26 }
    27 /*===================UR0初始化函数====================*/
    28 void Init_Uart0()
    29 {
    30   PERCFG = 0x00;    //串口0的引脚映射到位置1,即P0_2和P0_3
    31   P0SEL = 0x0C;     //将P0_2和P0_3端口设置成外设功能
    32   U0BAUD = 59;      //16MHz的系统时钟产生9600BPS的波特率
    33   U0GCR = 9;
    34   U0UCR |= 0x80;    //禁止流控,8位数据,清除缓冲器
    35   U0CSR |= 0xC0;    //选择UART模式,使能接收器
    36   UTX0IF = 0;       //清除TX发送中断标志
    37   URX0IF = 0;       //清除RX接收中断标志
    38   URX0IE = 1;       //使能URAT0的接收中断
    39   EA = 1;           //使能总中断
    40 }
    41 unsigned char dat[4];
    42 /*===================UR0发送字符串函数==================*/
    43 void UR0SendString(unsigned char *str, unsigned char count)
    44 {
    45   while(count--)       
    46   {
    47     U0DBUF = *str++;    //将要发送的1字节数据写入U0DBUF
    48     while(!UTX0IF);     //等待TX中断标志,即数据发送完成
    49     UTX0IF = 0;  
    50   }
    51 }
    52 /*===================ADC初始化函数====================*/
    53 void Init_ADC0()
    54 {
    55   P0SEL |= 0x01;      //P0_0端口设置为外设功能
    56   P0DIR &= ~0x01;     //P0_0端口设置为输入端口
    57   APCFG |= 0x01;      //P0_0作为模拟I/O使用
    58 }
    59 /*===================读取ADC的数据====================*/
    60 void Get_ADC0_Value()
    61 {
    62   ADCIF = 0;
    63   //参考电压选择AVDD5引脚,256抽取率,AIN0通道0
    64   ADCCON3 = (0x80 | 0x10 | 0x00);
    65   while(!ADCIF);      //等待A/D转换完成,
    66   dat[0] = 0xaf;
    67   dat[1] = ADCH;      //读取ADC数据低位寄存器
    68   dat[2] = ADCL;      //读取ADC数据高位寄存器
    69   dat[3] = 0xfa;
    70 }
    71 /*=======================主函数======================*/
    72 void main()
    73 {
    74   Init_Uart0();
    75   Init_Timer1();
    76   Init_ADC0();
    77   while(1)
    78   {
    79     if(F_time == 1)           //定时1秒时间到
    80     {
    81       Get_ADC0_Value();       //进行A/D转换并读取数据
    82       UR0SendString(dat,4);   //向上位机发送数据
    83       F_time = 0;             //定时1秒标志清0
    84     }
    85   }
    86 }
    View Code
  • 相关阅读:
    codevs1004 四子连棋
    codevs1009 产生数
    NOIP2014 寻找道路
    Tyvj1139 向远方奔跑(APIO 2009 抢掠计划)
    随机算法
    线性基
    线性基入门
    线性基 + 并查集
    欧拉公式 (平面)
    卡特兰数 + 大数
  • 原文地址:https://www.cnblogs.com/yuling520/p/12722735.html
Copyright © 2011-2022 走看看