欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

第二部分 基础篇-第7章 CC2530温度串口显示(ADC电压表)

程序员文章站 2022-04-01 22:05:05
...

1 理论分析

1.1 CC2530 的 ADC 介绍

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

第二部分 基础篇-第7章 CC2530温度串口显示(ADC电压表)

图1 ADC方框图

ADC 的主要特性如下:
 可选的抽取率,这也设置了分辨率(7 到 12 位)8 个独立的输入通道,可接受单端或差分信号
 参考电压可选为内部单端、外部单端、外部差分或 AVDD5
 产生中断请求
 转换结束时的 DMA 触发
 温度传感器输入
 电池测量功能
第二部分 基础篇-第7章 CC2530温度串口显示(ADC电压表)

图2 ADC 操作

图2是 CC2530ADC 的操作图,这里面就是讲解 ADC 是怎么操作的,待会我们的实验就按照这个图来开展。

1.2流程图

下面是本实验的流程图,大家可以结合这个图来学习编写程序

第二部分 基础篇-第7章 CC2530温度串口显示(ADC电压表)

图3 流程图

2实验详解

2.1实验目的

1)、通过实验掌握CC2530 芯片串口配置与使用;
2)、集到内部温度传感器信息通过串口发送到上位机。

2.2实验设备

硬件:PC 机一台 ZB2530(底板、核心板、仿真器、USB 线) 一套
软件:2000/XP/win7 系统,IAR 8.20 集成开发环境、串口助手

2.3相关电路图

第二部分 基础篇-第7章 CC2530温度串口显示(ADC电压表)

图4 FT232

第二部分 基础篇-第7章 CC2530温度串口显示(ADC电压表)

图5 USB

2.4实验分析

本实验需要用到IO口串口、中断及ADC等寄存器,在前面已经对IO口、串口、中断等寄存器详细分析了,在此只给出ADC相关的寄存器。

表1 ADC控制1

第二部分 基础篇-第7章 CC2530温度串口显示(ADC电压表)第二部分 基础篇-第7章 CC2530温度串口显示(ADC电压表)

表2 ADC控制2

第二部分 基础篇-第7章 CC2530温度串口显示(ADC电压表)

表3 ADC控制3

ADCCON3 (0xB6)–ADC控制3
第二部分 基础篇-第7章 CC2530温度串口显示(ADC电压表)第二部分 基础篇-第7章 CC2530温度串口显示(ADC电压表)

表4测试寄存器0

第二部分 基础篇-第7章 CC2530温度串口显示(ADC电压表)

表5 模拟测试控制

第二部分 基础篇-第7章 CC2530温度串口显示(ADC电压表)

2.5参考代码(部分代码)

/**Includes*********************************************************************/
#include <iocc2530.h>
#include "adc.h"
#include "uart.h"
#include "led.h"
#include <stdio.h>
#include <string.h>

/**函数声明*********************************************************************/
void DelayMS(uint msec);
void ClockInit(void);
void InitUart(void);
void UartTX_Send_String(char *Data,int len);
void format(float vol, char buf[6]);
float getVol(void);

/**
  * @brief     主函数
  * @param     None
  * @retval    None
  */
void  main(void)
{
  uchar i=0;
  char vol[6];
  float average;
  float temp;
  P1_0 = 0;
  ClockInit();
  InitUart();
  SET_IO_PORT_DIR(1,0,IO_OUT);         //设置LED,作为ADC采样进行的标志
  IO_FUNC_PORT_PIN(1, 0, IO_FUNC_GIO); //INIT_LED(); 
  IEN0 = IEN1 = IEN2 =0;

  while(1)
  { 
   for(i=0; i<16; i++)//取16次电压的平均值
   {
     temp = getVol();
     average += temp;
   }
   average = average / 16;
   format(average, vol);
   UartTX_Send_String(vol,6);  //向串口发送数据
   //UartTX_Send_String("\r",1); //发送换行
   P1_0 = ~P1_0;
   DelayMS(2000); //两秒钟发一次
   average = 0.0;
  }
}      


/**
  * @brief     延时函数
  * @param     msec 延时参数,值越大延时越久
  * @retval    None
  * @attention 以毫秒为单位延时 16M时约为535,32M时要调整,系统时钟不修改默认为16M
  */
void DelayMS(uint msec)
{  
  uint i,j;

  for (i=0; i<msec; i++)
    for (j=0; j<1070; j++);
}


/**
  * @brief     初始化时钟参数
  * @param     None
  * @retval    None
  */
void ClockInit(void)
{
    CLKCONCMD = 0x28;           //时器计数时钟设定为1M Hz,  系统时钟设定为32 MHz 
    while(CLKCONSTA & 0x40);    //等晶振稳定
}


/**
  * @brief     串口初始化函数
  * @param     None
  * @retval    None
  */
void InitUart(void)
{ 
  PERCFG = 0x00;           //外设控制寄存器 USART 0的IO位置:0为P0口位置1 
  P0SEL = 0x0c;            //P0_2,P0_3用作串口(外设功能)
  P2DIR &= ~0XC0;          //P0优先作为UART0

  U0CSR |= 0x80;           //设置为UART方式
  U0GCR |= 11;                     
  U0BAUD |= 216;           //波特率设为115200
  UTX0IF = 0;              //UART0 TX中断标志初始置位0
}


/**
  * @brief     串口发送函数
  * @param     None
  * @retval    None
  */
void UartTX_Send_String(char *Data,int len)
{
  int j;
  for(j=0;j<len;j++)
  {
    U0DBUF = *Data++;
    while(UTX0IF == 0);
    UTX0IF = 0;
  }
  U0DBUF = 0x0A;        // 换行
  while(UTX0IF == 0);
    UTX0IF = 0;
}

/**
  * @brief     格式化函数 将电压值转换成数组
  * @param     None
  * @retval    None
  */
void format(float vol, char buf[6])
{
    char ge = 0;           //个位
    char fen = 0;          //分位
    char shifen = 0;       //十分位
    char baifen = 0;       //百分位
    uint i = 0;
    vol = vol*1000;        //扩大1000倍
    i = (uint)vol;         //转换为整形
    ge = (i / 1000) + 0x30;//转成字符
    fen = (i / 100 % 10) + 0x30;
    shifen =(i % 100 / 10) + 0x30;
    baifen = (i % 10) + 0x30;
    buf[0] = ge;
    buf[1] = '.';
    buf[2] = fen;
    buf[3] = shifen;
    buf[4] = baifen;
    buf[5] = 'v';
}

/**
  * @brief     单次采样,采用端口为P0.6
  * @param     None
  * @retval    float
  */
float getVol(void)
{
  uchar i = 0;
  uint value = 0;
  long uint AdcValue = 0;     //防止溢出
  float vol = 0.0;
  SET_IO_PORT_DIR(0,6,IO_IN); //设置P0..6为输入模式
  ADC_ENABLE_CHANNEL(6);      //使能通道6作为ADC的采样通道
  for(i=0; i<4; i++)
  {
    ADC_SINGLE_CONVERSION(ADC_REF_AVDD | ADC_12_BIT | ADC_AIN6);//片上3.3V参考电压,12位,6通道
    ADC_SAMPLE_SINGLE(); 
    while(!(ADCCON1 & 0x80));              //等待AD转换完成
    /*value =  ADCL >> 2;                  //ADCL寄存器低2位无效
    value |= (((uint)ADCH) << 6); */    
    value = ADCL>>4;                      
    value |= (((uint)ADCH) << 4);         
    AdcValue += value;  
  }
  AdcValue = AdcValue >> 2;                 //累加除以4,得到平均值
  if(AdcValue > 4096)   // 输入的电压0V时,因为会满量程,检测到AdcValue的12位值为0xfff
    AdcValue = 0;
  vol = (float)(AdcValue/(float)2048)*3.3;  //换算成电压值

  return vol;
}

2.6实验现象

P0.6接底板上的3.3V和GND,波特率特率115200 8N10V 是 P06 接入 GND,3.3V 是 P06 接入 VCC
1.调整可调电阻;
2.下载程序到开发板中。打开串口助手设置参考为准;
3.观察串口数据的变化。

第二部分 基础篇-第7章 CC2530温度串口显示(ADC电压表)

图6

2.7 实验总结

通过本实验,大家需要掌握以下 2 点:
 ADC 的主要特性如下:
(1) 可选的抽取率,这也设置了分辨率(7 到 12 位)
(2) 8 个独立的输入通道,可接受单端或差分信号
(3) 参考电压可选为内部单端、外部单端、外部差分或 AVDD5
(4) 产生中断请求
(5) 转换结束时的 DMA 触发
(6) 温度传感器输入
(7) 电池测量功能
 使用 ADC 的流程:
(1) P0.6 管脚设置为输入;
(2) 设置参考电压;
(3) 设置转换精度及 ADC 输入管脚;
(4) 读取转换结果并显示。

附:管理 ADC 的寄存器类型

●ADCL (0xBA) – ADC 数据低位
●ADCH (0xBB) – ADC 数据高位
●ADCCON1 (0xB4)–ADC 控制 1
●ADCCON2 (0xB5)–ADC 控制 2
●ADCCON3 (0xB6)–ADC 控制 3
●TR0 (0x624B) –测试寄存器 0

本章参考代码

点击进入

相关标签: ADC CC2530