2013-11-14

LPC1114 ADC learning notes


UM10398 Chapter 25: LPC111x/LPC11Cxx ADC Rev. 12.1 — 7 August 2013 User manual

25.1 How to read this chapter

The ADC block is identical for all LPC111x, LPC11D14, and LPC11Cxx parts.

All HVQFN33 and LQFP48 packages support eight ADC channels. On the small packages (TSSOP28/DIP28/TSSOP20/SO20), only five or six ADC channels are pinned out (see Table 3).

25.2 Basic configuration

The ADC is configured using the following registers:

1. Pins: The ADC pin functions are configured in the IOCONFIG register block (Section 7.4).

2. Power and peripheral clock: In the SYSAHBCLKCTRL register, set bit 13 (Table 21).

Power to the ADC at run-time is controlled through the PDRUNCFG register (Table 44).

Remark: Basic clocking for the A/D converters is determined by the APB clock (PCLK). A programmable divider is included in the A/D converter to scale this clock to the 4.5 MHz (max) clock needed by the successive approximation process. An accurate conversion requires 11 clock cycles.

25.3 Features

10-bit successive approximation Analog-to-Digital Converter (ADC).

• Input multiplexing among 8 pins.

• Power-down mode.

• Measurement range 0 to 3.6 V. Do not exceed the VDD voltage level.

• 10-bit conversion time 2.44 us.

• Burst conversion mode for single or multiple inputs.

• Optional conversion on transition on input pin or Timer Match signal.

• Individual result registers for each A/D channel to reduce interrupt overhead.


// *** adc.h ***

#ifndef __NXP_ADC_H
#define __NXP_ADC_H

#define  Vref   3280

extern void ADC_Init(void); // 初始化ADC口(AD7)
extern uint32 ADC_Read(void);   // 读取电压值(AD7)
extern uint32 ADC_To_Res(uint32 adc_value); // 把从AD7口读到的电压值转变为热敏电阻的电阻值
extern uint8 Res_To_Temp(uint32 res_value); // 把热敏电阻的电阻值转变为温度值
extern uint8 Fetch_sign(uint32 res_value);  // 检测温度是在零上还是零下

#endif


#include "nxplpc11xx.h"
#include "adc.h"

/*****************************************/
/* 函数名称:初始化ADC口(AD7)          */
/*****************************************/
void ADC_Init(void)
{
SYSCON->PDRUNCFG &= ~(0x1<<4);        // ADC模块上电
SYSCON->SYSAHBCLKCTRL |= (1<<13);     // 使能ADC时钟

SYSCON->SYSAHBCLKCTRL |= (1<<16);     // 使能IOCON时钟
IOCON->PIO1_11 &= ~0x9F;              // 把P1.11引脚选择模拟输入方式
  IOCON->PIO1_11 |= 0x01;               // 把P1.11引脚设置为AD7功能
SYSCON->SYSAHBCLKCTRL &= ~(1<<16);    // 关闭IOCON时钟
ADC->CR = (1<<7)|                     /* bit7:bit0   选择通道7作为ADC输入,即P1.11引脚 */
         (23<<8 )|                   /* bit15:bit8  把采样时钟频率设置为2MHz 48/(23+1)*/
         (1<<16 )|      /* bit16       硬件扫描模式  */
         (0<<17 )|        /* bit19:bit17 10位模式 */
 (0<<24 );           /* bit26:bit24 硬件扫描模式下这些位置0 */
}

/********************************************/
/* 函数功能:读取电压值(AD7)              */
/* 出口参数:adc_value, 读到的电压值        */
/********************************************/
uint32 ADC_Read(void)
{
uint32 adc_value=0;
uint8 i;

for(i=0;i<10;i++)  // 再连续读取10个电压值
{
delay_us(6);
adc_value += ((ADC->DR[7]>>6)&0x3FF);
}
adc_value = adc_value/10;  // 把读到的10个电压值取平均值
adc_value = (adc_value*Vref)/1024; // 转换为真正的电压值

return adc_value;  // 返回结果
}

/************************************************************/
/* 函数功能:把从AD7口读到的电压值转变为热敏电阻的电阻值    */
/* 入口参数:adc_value, 电阻值                              */
/* 出口参数:res_value, 电阻值                              */
/************************************************************/
uint32 ADC_To_Res(uint32 adc_value)
{
uint32 res_value;

res_value = (adc_value*10000)/(Vref-adc_value);

return res_value;
}

/************************************************************/
/* 函数功能:把热敏电阻的电阻值转变为温度值                 */
/* 入口参数:res_value, 电阻值                              */
/* 出口参数:temp, 温度值                                   */
/* 说    明:本函数根据MF58的数据手册编排,结果非常准确!   */
/************************************************************/
uint8 Res_To_Temp(uint32 res_value)
{
uint32 k;   // 斜率
int32 temp;  // 温度值

if( (res_value<29371)&&(res_value>18680) ) // 0~10摄氏度
{
k = 1069;
temp = ((29370-res_value)/k)+0;
}
else if( (res_value<18681)&&(res_value>12240) ) // 10~20摄氏度
{
  k = 644;
temp = ((18680-res_value)/k)+10;
}
else if( (res_value<12241)&&(res_value>8221) ) // 20~30摄氏度
{
  k = 402;
temp = ((12240-res_value)/k)+20;
}
else if( (res_value<8222)&&(res_value>5648) ) // 30~40摄氏度
{
  k = 257;
temp = ((8221-res_value)/k)+30;
}
else if( (res_value<5649)&&(res_value>3958) ) // 40~50摄氏度
{
  k = 169;
temp = ((5648-res_value)/k)+40;
}
else if( (res_value<47731)&&(res_value>29370) ) // -10~0摄氏度
{
  k = 1836;
temp = ((47730-res_value)/k)-10;
}
else if( (res_value<80361)&&(res_value>47730) ) // -20~-10摄氏度
{
  k = 3263;
temp = ((80360-res_value)/k)-20;
}
else if( (res_value<140001)&&(res_value>80360) ) // -30~-20摄氏度
{
  k = 5964;
temp = ((140000-res_value)/k)-30;
}
else if( (res_value<249600)&&(res_value>140000) ) // -40~-30摄氏度
{
  k = 10960;
temp = ((249600-res_value)/k)-40;
}

return((uint8)temp);   // 返回温度值
}

/*****************************************/
/* 函数功能:检测温度是在零上还是零下    */
/* 入口参数:热敏电阻的阻值              */
/* 出口参数:sign_sign, 1:零上          */
/*                      0:零下          */
/*****************************************/
uint8 Fetch_sign(uint32 res_value)
{
uint8 sign_sign;

if(res_value<29371)sign_sign = 1;
else sign_sign = 0;

return sign_sign;
}


//////////////////////////////////////////////////////////

.END

No comments:

Post a Comment