大家好,我是考100分的小小码 ,祝大家学习进步,加薪顺利呀。今天说一说CC2530(zigbee)入门开发: ADC应用「建议收藏」,希望您对编程的造诣更进一步.
小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
一、ADC功能介绍
ADC功能是将模拟量转为数字量的数模转换器;平时测量的温度、光照强度、烟雾浓度、酒精浓度这些数据都是属于模拟量,需要使用相关的线性变化传感器进行检测,然后通过ADC采样转为数字量,得到最终的一组数据。
ADC这个功能在很多低配单片机上是不自带的,CC2530是带了ADC采集功能,做一些模拟转换的应用就很方便,不需要再去额外的挂载其他外设ADC芯片。
二、配置ADC相关寄存器
要使用ADC功能,需要配置APCFG寄存器,下面截图来至官方的数据手册,将寄存器对应位配置为1即可开启模拟IO功能。
三、示例代码
3.1 配置ADC采集内部温度示例代码
/****************************************************************************** CC2530模块AD测试程序 通过内置温度传感器实现温度采集 ******************************************************************************/
#include <ioCC2530.h>
#include <stdio.h>
#define uint unsigned int
// Data
typedef unsigned char BYTE;
// Unsigned numbers
typedef unsigned char UINT8;
typedef unsigned char INT8U;
typedef unsigned short UINT16;
typedef unsigned short INT16U;
typedef unsigned long UINT32;
typedef unsigned long INT32U;
// Signed numbers
typedef signed char INT8;
typedef signed short INT16;
typedef signed long INT32;
#define ADC_REF_1_25_V 0x00
#define ADC_14_BIT 0x30
#define ADC_TEMP_SENS 0x0E
#define DISABLE_ALL_INTERRUPTS() (IEN0 = IEN1 = IEN2 = 0x00)
#define ADC_SINGLE_CONVERSION(settings) \ do{ ADCCON3 = (settings); }while(0)
#define ADC_SAMPLE_SINGLE() \ do { ADC_STOP(); ADCCON1 |= 0x40; } while (0)
#define ADC_SAMPLE_READY() (ADCCON1 & 0x80)
#define ADC_STOP() \ do { ADCCON1 |= 0x30; } while (0)
#define ADC14_TO_CELSIUS(ADC_VALUE) ( ((ADC_VALUE) >> 4) - 335)
/************************** 系统时钟 不分频 计数时钟 32分频 **************************/
void InitClock(void) {
CLKCONCMD = 0x28; //时器计数时钟设定为1M Hz, 系统时钟设定为32 MHz
while(CLKCONSTA & 0x40); //等晶振稳定
}
/***************************************** 串口初始化函数:初始化串口 UART0 *****************************************/
void InitUART0(void) {
PERCFG = 0x00; //位置1 P0口
P0SEL = 0x3c; //P0用作串口
P2DIR &= ~0XC0; //P0优先作为UART0
U0CSR |= 0x80; //串口设置为UART方式
U0GCR |= 9;
U0BAUD |= 59; //波特率设为19200
UTX0IF = 1; //UART0 TX中断标志初始置位1
U0CSR |= 0X40; //允许接收
IEN0 |= 0x84; //开总中断,接收中断
}
/**************************************************************** 串口发送字符串函数 ****************************************************************/
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;
}
/**************************************************************** 延时函数 ****************************************************************/
void Delay(uint n) {
uint i;
for(i=0;i<n;i++);
for(i=0;i<n;i++);
for(i=0;i<n;i++);
for(i=0;i<n;i++);
for(i=0;i<n;i++);
}
INT16 AvgTemp;
/**************************************************************** 温度传感器初始化函数 ****************************************************************/
void initTempSensor(void) {
DISABLE_ALL_INTERRUPTS(); //关闭所有中断
InitClock(); //设置系统主时钟为32M
*((BYTE __xdata*) 0x624B) = 0x01; //开启温度传感器
*((BYTE __xdata*) 0x61BD) = 0x01; //将温度传感器与ADC连接起来
}
/**************************************************************** 读取温度传感器AD值函数 ****************************************************************/
INT8 getTemperature(void) {
UINT8 i;
UINT16 AdcValue;
UINT16 value;
AdcValue = 0;
for( i = 0; i < 4; i++ )
{
ADC_SINGLE_CONVERSION(ADC_REF_1_25_V | ADC_14_BIT | ADC_TEMP_SENS); // 使用1.25V内部电压,12位分辨率,AD源为:温度传感器
ADC_SAMPLE_SINGLE(); //开启单通道ADC
while(!ADC_SAMPLE_READY()); //等待AD转换完成
value = ADCL >> 2; //ADCL寄存器低2位无效
value |= (((UINT16)ADCH) << 6);
AdcValue += value; //AdcValue被赋值为4次AD值之和
}
value = AdcValue >> 2; //累加除以4,得到平均值
return ADC14_TO_CELSIUS(value); //根据AD值,计算出实际的温度
}
/**************************************************************** 主函数 ****************************************************************/
void main(void) {
char i;
char TempValue[10];
InitUART0(); //初始化串口
initTempSensor(); //初始化ADC
while(1)
{
AvgTemp = 0;
for(i = 0 ; i < 64 ; i++)
{
AvgTemp += getTemperature();
AvgTemp >>= 1; //每次累加后除2.
}
sprintf(TempValue, (char *)"%d ℃", (INT8)AvgTemp);
UartTX_Send_String(TempValue,4);
Delay(50000);
}
}
3.2 配置ADC通道0采集模拟数据
#include "ioCC2530.h"
/*===============定时器1初始化函数==================*/
void Init_Timer1() {
T1CC0L = 0xd4; //设置最大计数值的低8位
T1CC0H = 0x30; //设置最大计数值的高8位
T1CCTL0 |= 0x04; //开启通道0的输出比较模式
T1IE = 1; //使能定时器1中断
T1OVFIM = 1; //使能定时器1溢出中断
EA = 1; //使能总中断
T1CTL = 0x0e; //分频系数是128,模模式
}
unsigned char count = 0;
unsigned char F_time = 0;
/*================定时器1服务函数====================*/
#pragma vector = T1_VECTOR
__interrupt void Timer1_Sevice() {
T1STAT &= ~0x01; //清除定时器1通道0中断标志
count++;
if(count == 10) //定时1秒到
{
F_time = 1;
count = 0;
}
}
/*===================UR0初始化函数====================*/
void Init_Uart0() {
PERCFG = 0x00; //串口0的引脚映射到位置1,即P0_2和P0_3
P0SEL = 0x0C; //将P0_2和P0_3端口设置成外设功能
U0BAUD = 59; //16MHz的系统时钟产生9600BPS的波特率
U0GCR = 9;
U0UCR |= 0x80; //禁止流控,8位数据,清除缓冲器
U0CSR |= 0xC0; //选择UART模式,使能接收器
UTX0IF = 0; //清除TX发送中断标志
URX0IF = 0; //清除RX接收中断标志
URX0IE = 1; //使能URAT0的接收中断
EA = 1; //使能总中断
}
unsigned char dat[4];
/*===================UR0发送字符串函数==================*/
void UR0SendString(unsigned char *str, unsigned char count) {
while(count--)
{
U0DBUF = *str++; //将要发送的1字节数据写入U0DBUF
while(!UTX0IF); //等待TX中断标志,即数据发送完成
UTX0IF = 0;
}
}
/*===================ADC初始化函数====================*/
void Init_ADC0() {
P0SEL |= 0x01; //P0_0端口设置为外设功能
P0DIR &= ~0x01; //P0_0端口设置为输入端口
APCFG |= 0x01; //P0_0作为模拟I/O使用
}
/*===================读取ADC的数据====================*/
void Get_ADC0_Value() {
ADCIF = 0;
//参考电压选择AVDD5引脚,256抽取率,AIN0通道0
ADCCON3 = (0x80 | 0x10 | 0x00);
while(!ADCIF); //等待A/D转换完成,
dat[0] = 0xaf;
dat[1] = ADCH; //读取ADC数据低位寄存器
dat[2] = ADCL; //读取ADC数据高位寄存器
dat[3] = 0xfa;
}
/*=======================主函数======================*/
void main() {
Init_Uart0();
Init_Timer1();
Init_ADC0();
while(1)
{
if(F_time == 1) //定时1秒时间到
{
Get_ADC0_Value(); //进行A/D转换并读取数据
UR0SendString(dat,4); //向上位机发送数据
F_time = 0; //定时1秒标志清0
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13043.html