打印
[Zigbee]

CC2530温度串口显示(ADC电压表)

[复制链接]
1016|23
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gwsan|  楼主 | 2019-8-1 13:00 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
1 理论分析
1.1 CC2530 的 ADC 介绍
CC2530 的 ADC 支持多达 14 位的模拟数字转换,具有多达 12 位的 ENOB(有效数字位)。它包括一个模拟多路转换器,具有多达 8 个各自可配置的通道;以及一个参考电压发生器。转换结果通过 DMA 写入存储器。还具有若干运行模式。



图1 ADC方框图


使用特权

评论回复
评论
dirtwillfly 2019-8-3 20:46 回复TA
感谢分享 

相关帖子

沙发
gwsan|  楼主 | 2019-8-1 13:01 | 只看该作者

ADC 的主要特性如下:

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

图2 ADC 操作

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


使用特权

评论回复
板凳
gwsan|  楼主 | 2019-8-1 13:01 | 只看该作者
1.2流程图

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

图3 流程图

使用特权

评论回复
地板
gwsan|  楼主 | 2019-8-1 13:01 | 只看该作者
2实验详解
2.1实验目的
1)、通过实验掌握CC2530 芯片串口配置与使用;
2)、集到内部温度传感器信息通过串口发送到上位机。

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


使用特权

评论回复
5
gwsan|  楼主 | 2019-8-1 13:02 | 只看该作者
2.3相关电路图

图4 FT232

图5 USB

使用特权

评论回复
6
gwsan|  楼主 | 2019-8-1 13:02 | 只看该作者
2.4实验分析

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

表1 ADC控制1


使用特权

评论回复
7
gwsan|  楼主 | 2019-8-1 13:02 | 只看该作者
表2 ADC控制2


使用特权

评论回复
8
gwsan|  楼主 | 2019-8-1 13:03 | 只看该作者
表3 ADC控制3

ADCCON3 (0xB6)–ADC控制3


使用特权

评论回复
9
gwsan|  楼主 | 2019-8-1 13:03 | 只看该作者
表4测试寄存器0


使用特权

评论回复
10
gwsan|  楼主 | 2019-8-1 13:03 | 只看该作者
表5 模拟测试控制


使用特权

评论回复
11
gwsan|  楼主 | 2019-8-1 13:04 | 只看该作者
2.5参考代码(部分代码)
#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);


使用特权

评论回复
12
gwsan|  楼主 | 2019-8-1 13:04 | 只看该作者
/**
  * @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;
  }
}      

使用特权

评论回复
13
gwsan|  楼主 | 2019-8-1 13:46 | 只看该作者
/**
  * @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++);
}

使用特权

评论回复
14
gwsan|  楼主 | 2019-8-1 13:46 | 只看该作者
/**
  * @brief     初始化时钟参数
  * @param     None
  * @retval    None
  */
void ClockInit(void)
{
    CLKCONCMD = 0x28;           //时器计数时钟设定为1M Hz,  系统时钟设定为32 MHz
    while(CLKCONSTA & 0x40);    //等晶振稳定
}

使用特权

评论回复
15
gwsan|  楼主 | 2019-8-1 13:47 | 只看该作者
/**
  * @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
}

使用特权

评论回复
16
gwsan|  楼主 | 2019-8-1 13:47 | 只看该作者
/**
  * @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;
}

使用特权

评论回复
17
gwsan|  楼主 | 2019-8-1 13:48 | 只看该作者
/**
  * @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';
}

使用特权

评论回复
18
gwsan|  楼主 | 2019-8-1 13:49 | 只看该作者
/**
  * @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;
}

使用特权

评论回复
19
gwsan|  楼主 | 2019-8-1 13:49 | 只看该作者

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

图6

使用特权

评论回复
20
gwsan|  楼主 | 2019-8-1 13:50 | 只看该作者
2.7 实验总结
通过本实验,大家需要掌握以下 2 点:

        ADC 的主要特性如下:

(1) 可选的抽取率,这也设置了分辨率(7 到 12 位)
(2) 8 个独立的输入通道,可接受单端或差分信号
(3) 参考电压可选为内部单端、外部单端、外部差分或 AVDD5
(4) 产生中断请求
(5) 转换结束时的 DMA 触发
(6) 温度传感器输入
(7) 电池测量功能

        使用 ADC 的流程:

(1) P0.6 管脚设置为输入;
(2) 设置参考电压;
(3) 设置转换精度及 ADC 输入管脚;
(4) 读取转换结果并显示。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

68

主题

3426

帖子

1

粉丝