我是靠谱客的博主 快乐枫叶,最近开发中收集的这篇文章主要介绍CC2530之ADC采集,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

定时器部分:

定时器三种模式

定时公式:

定时器1配置步骤:

串口部分:

UART配置基本步骤:

ADC部分:

ADC 输入:

ADC 转换时间:

Tconv = (抽取率 + 16) x 0.25 μs。

ADC 转换结果:

ADC 转换序列:

ADC配置步骤:


定时器部分:

定时器三种模式:自由运行模式,模模式,正计数/倒计数模式

本次使用 模模式
当定时器运行在模模式, 16 位计数器从 0x0000 开始,每个活动时钟边沿增加 1 。当计数器达到 T1CC0 (溢 出),寄存器 T1CC0H:T1CC0L 保存的最终计数值,计数器将复位到 0x0000 ,并继续递增。如果定时器开始于 T1CC0 以上的一个值,当达到最终计数值( 0xFFFF )时,设置标志 IRCON.T1IF T1CTL.OVFIF 。如果设置 了相应的中断屏蔽位 TIMIF.OVFIM 以及 IEN1.T1EN ,将产生一个中断请求。模模式可以用于周期不是 0xFFFF 的应用程序。

实现定时多长时间的公式:

最大计数值=定时时长/定时计数周期

定时计数周期=(1/晶振)X 分频系数;

T1CC0HT1CC0L寄存器:

T1CTL 寄存器:

定时器1配置步骤:

(1)打开总中断,打开定时器1的中断

(2)选择计数模式,和分频系数

(3)通过T1CCTL0 寄存器,选择定时器 1 通 0 捕获/比较模式

(4)定时时长,将计数值分别配置给T1CC0HT1CC0L这两个寄存器

(5)编写定时器1相关中断服务函数

Timer.c

#include "Timer.h"
unsigned long SysTick= 0;
void TimerInit(void)
{
  IEN0  |= 0x01<<7;  //打开总中断
  IEN1  |= 0x01<<1;  //定时器1中断使能
  TIMIF |= 0x01<<6;  //定时器1溢出中断屏蔽
  T1CCTL0 |= 0x01<<2; //比较模式
  T1CTL = 0x0e;  //128分频,模模式
  T1CC0H = 0x61;   //定时0.1s
  T1CC0L = 0xA8;  //定时时间/(1/32)x128=oxc350
}
unsigned long TimerSet(unsigned long set){
    return SysTick + set;
}
unsigned char TimerCheck(unsigned long t){
  if(SysTick>=t)
    return 1;
  else
    return 0;
}
#pragma vector = T1_VECTOR //中断服务子程序
__interrupt void T1_ISR(void) 
{ 
  SysTick++;
  IRCON  &=~0x01<<1;  //清除定时器1中断标志
  T1STAT &=~0x01<<5;  //定时器 1 计数器溢出中断标志置0
}

串口部分:

本次选用UART模式:

UART配置基本步骤:

(1)UART引脚:P0_2和P0_3为外设功能,分别作为RX,TX;RX配置为输入,TX配置为输出

(2)偶校验,9位数据传输

(3)配置波特率为256

(4)使能UART0的TX,RX的中断

(5)编写中断服务函数

Uart.c

#include "Uart.h"
#include <string.h>
#define UART_TX_MAX_SIZE     255
#define UART_RX_MAX_SIZE     255
static unsigned char UartTxBuf[UART_TX_MAX_SIZE];
static unsigned char UartTxLen = 0;
static unsigned char UartTxPos = 0;
static unsigned char UartRxBuf[UART_RX_MAX_SIZE];
static unsigned char UartRxPos = 0;
void UartInit(void)
{
  P0SEL |=  0x01<<2|0x01<<3;  //设置P0_2和P0_3为外设功能,分别作为RX,TX
  P0DIR &= ~0x01<<2;    //配置RX为输入
  P0DIR |=  0x01<<3;    //配置TX为输出
  P1SEL &= ~(0x01<<0|0x01<<1);
  P1DIR |=  0x01<<0|0x01<<1; 
  P2DIR &= ~0xc0;
  PERCFG &= ~0x01<<0;
  U0CSR  |= 0x01<<7|0x01<<6;   //设置为UART模式,UART接收器使能
  U0UCR  |= 0x01<<3|0x01<<4|0x01<<5; //偶校验,9位传输
  U0GCR   = 8;
  U0BAUD  = 59;   //波特率为256
  IEN0   |= 0x01<<7|0x01<<2;  //打开总中断,使能UART0的RX中断
  IEN2   |= 0x01<<2;   //使能UART0的TX中断
}
void UartSend(unsigned char *data,unsigned char size){
    memcpy(UartTxBuf,data,size);  //将要发送的数据data复制到UartTxBuf,被复制的字节数为size
    UartTxLen = size;
    UartTxPos = 1;
    U0DBUF = UartTxBuf[0];  //U0DBUF接收/发送数据缓冲寄存器,将要发送的数据写入U0DBUF
}
unsigned char UartRecv(unsigned char *data,unsigned char size){
    unsigned char realLen = size;
    if(size > UartRxPos){
        realLen = UartRxPos;
    }    
    memcpy(data,UartRxBuf,realLen);
    memcpy(UartRxBuf,UartRxBuf + realLen,UartRxPos -  realLen);
    UartRxPos -= realLen;
    return realLen;
}
//TX中断服务函数
#pragma vector = UTX0_VECTOR
__interrupt void Uart0TxInterrupt(void){    
    UTX0IF = 0;
    if(UartTxPos < UartTxLen){
        U0DBUF = UartTxBuf[UartTxPos++];
    }
}
//RX中断服务函数
#pragma vector = URX0_VECTOR
__interrupt void Uart0RxInterrupt(void){    
    URX0IF = 0;
    if(UartRxPos < UART_RX_MAX_SIZE){
        UartRxBuf[UartRxPos++] = U0DBUF;
    }
}

ADC部分:

ADC简介:

ADC 支持多达 14 位的模拟数字转换,具有多达 12 位的 ENOB (有效数字位)。它包括一个模拟多路转换 器,具有多达 8 个各自可配置的通道;以及一个参考电压发生器。转换结果通过 DMA 写入存储器。还具有若 干运行模式。
ADC 的主要特性如下:
● 可选的抽取率,这也设置了分辨率(7 到 12 位)
8 个独立的输入通道,可接受单端或差分信号
● 参考电压可选为内部单端、外部单端、外部差分或 AVDD5
● 产生中断请求
● 转换结束时的 DMA 触发
● 温度传感器输入
● 电池测量功能

ADC 输入:

端口 0 引脚的信号可以用作 ADC 输入。在下面的描述中,这些端口引脚指的是 AIN0-AIN7 引脚。输入引 脚 AIN0-AIN7 是连接到 ADC 的。 可以把输入配置为单端或差分输入。在选择差分输入的情况下,差分输入包括输入对AIN0-1 AIN2-3 AIN4- 5 和 AIN6-7 。注意负电压不适用于这些引脚,大于 VDD (未调节电压)的电压也不能。它们之间的差别是在 差分模式下转换。它是在差分模式下转换的输入对之间的差。
注意:P0.0对应AIN0, P0.7对应AIN7

ADC 转换时间:

ADC 只能运行在 32 MHz XOSC 上,用户不能整除系统时钟。实际 ADC 采样的 4 MHz 的频率由固定的内
部划分器产生。执行一个转换所需的时间取决于所选的抽取率。总的来说,转换时间由以下公式给定:

Tconv = (抽取率 + 16) x 0.25 μs。

ADC 转换结果:

结果放在 ADCH ADCL 两个寄存器中。

 ADCL寄存器和ADCH寄存器保存的是AD转换完成的结果,数据以2的补码形式表现。下表为采样精度与有效数据解析表: 

ADC 转换序列:

通过写 ADCCON3 寄存器 触发,完成单个 ADC 转换

ADCCON3 :寄存器控制单个转换的通道号码参考电压和抽取率。

ADCCON1寄存器:判断有没有转换完成,通过while通过转换完成的标志位进行判断。

ADC配置步骤:

(1)使能模拟外设I/O

(2)选择有ADC功能的引脚配置为外设功能

(3)配置I/O的方向为输入

(4)通过ADCCON3配置ADC 参考电压和抽取率(本次选用AVDD5 引脚(3.3V)和选择512抽取率),模拟数字转换的正参考电压可选择为一个内部生成的电压,AVDD5 引脚;适用于 AIN7 输入引脚的外部电 压,或适用于 AIN6-AIN7 输入引脚的差分电压。

(5)将结果放在 ADCH 和 ADCL 两个寄存器中,结果=value/(2的12次方)* 3.3

ADC.c

#include "adc.h"
void ADCInit(void)
{
   APCFG |= 0x01;// 模拟I/O使能
   P0SEL |= 0x01; //P0_0当ADC0使用
   P0DIR &= ~0x01;  //配置为输入
}
float GetADCVoltage(void){
    unsigned int value;
    ADCCON3 = 0xB0;// 转换完成后 bit0-bit3 会自动清,所以每次读取都需要进行一次初始化
    while(!(ADCCON1 & 0x80)); 
    value = ADCH << 8;
    value |= ADCL;
    value >>= 3;    //ADCL低位寄存器 1:0没有使用
    return  value / 4096.0 * 3.3;
}

main.c:

使用UART0打印出ADC采集的数据

#include <ioCC2530.h>
#include "Uart.h"
#include "Timer.h"
#include "led.h"
#include "Uart.h"
#include "ADC.h"
#include <stdio.h>
static void SysClockInit(void)
{
    CLKCONCMD &= ~0x40;            //设置系统时钟源为32MHz晶振  
    for(; CLKCONSTA & 0x40;);      //等待晶振稳定  
    CLKCONCMD &= ~0X47;            //设置系统主时钟频率为32MHz  
}
void main(void)
{
    unsigned long timer = 0;
    unsigned char buf[100];
    unsigned char len;    
    SysClockInit();
    UartInit();
    TimerInit();
    ledinit();
    ADCInit();
    while(1)
    {
        if(TimerCheck(timer))
        {
            timer = TimerSet(10);
            ledtoggle(0);
            len = sprintf((char *)buf,"DC Vlotage = %.2fn",GetADCVoltage());
            UartSend(buf,len);
        }
    }
}
 

补充:sprintf函数的格式:int sprintf( char *buffer, const char *format [, argument,...] );

buffer:这个参数就是接收字符串的字符数组。其大小必须要大于所接收的字符串的大小,否则的话会有空间不够从而导致内存溢出的风险。(这里比较大小时还要考虑到字符串最后的 ‘’

format:要传的字符串

除了前两个参数固定外,可选参数可以是任意个

最后

以上就是快乐枫叶为你收集整理的CC2530之ADC采集的全部内容,希望文章能够帮你解决CC2530之ADC采集所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(50)

评论列表共有 0 条评论

立即
投稿
返回
顶部