📄 adc.c
字号:
/******************** (C) COPYRIGHT 2010 Embest Info&Tech Co.,LTD. ************
* 文件名: adc.c
* 作者 : Wuhan R&D Center, Embest
* 日期 : 01/18/2010
* 描述 : 主程序源文件.
*******************************************************************************
*******************************************************************************
* 历史:
* 01/18/2010 : V1.0 初始版本
*******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "LPC11xx.h" /* LPC11xx 定义 */
#include "adc.h"
volatile uint32_t ADCValue[ADC_NUM];
volatile uint32_t ADCIntDone = 0;
#if BURST_MODE
volatile uint32_t channel_flag;
#endif
#if ADC_INTERRUPT_FLAG
/**
* @函数名:ADC_IRQHandler
* @描述:ADC中断处理函数
* @参数:无
* @返回值:无
*/
void ADC_IRQHandler (void)
{
uint32_t regVal;
/* 读ADC状态寄存器的值,清除中断 */
regVal = LPC_ADC->STAT;
if ( regVal & 0x0000FF00 ) /* 检测OVERRUN错误 */
{
regVal = (regVal & 0x0000FF00) >> 0x08;
/* 如果OVERRUN发生了,只需要读ADDR就可以清除它了 */
switch ( regVal )
{
case 0x01:
regVal = LPC_ADC->DR[0];
break;
case 0x02:
regVal = LPC_ADC->DR[1];
break;
case 0x04:
regVal = LPC_ADC->DR[2];
break;
case 0x08:
regVal = LPC_ADC->DR[3];
break;
case 0x10:
regVal = LPC_ADC->DR[4];
break;
case 0x20:
regVal = LPC_ADC->DR[5];
break;
case 0x40:
regVal = LPC_ADC->DR[6];
break;
case 0x80:
regVal = LPC_ADC->DR[7];
break;
default:
break;
}
LPC_ADC->CR &= 0xF8FFFFFF; /* 停止ADC */
ADCIntDone = 1;
return;
}
if ( regVal & ADC_ADINT )
{
switch ( regVal & 0xFF ) /* 检测DONE位 */
{
case 0x01:
ADCValue[0] = ( LPC_ADC->DR[0] >> 6 ) & 0x3FF;
break;
case 0x02:
ADCValue[1] = ( LPC_ADC->DR[1] >> 6 ) & 0x3FF;
break;
case 0x04:
ADCValue[2] = ( LPC_ADC->DR[2] >> 6 ) & 0x3FF;
break;
case 0x08:
ADCValue[3] = ( LPC_ADC->DR[3] >> 6 ) & 0x3FF;
break;
case 0x10:
ADCValue[4] = ( LPC_ADC->DR[4] >> 6 ) & 0x3FF;
break;
case 0x20:
ADCValue[5] = ( LPC_ADC->DR[5] >> 6 ) & 0x3FF;
break;
case 0x40:
ADCValue[6] = ( LPC_ADC->DR[6] >> 6 ) & 0x3FF;
break;
case 0x80:
ADCValue[7] = ( LPC_ADC->DR[7] >> 6 ) & 0x3FF;
break;
default:
break;
}
#if BURST_MODE
channel_flag |= (regVal & 0xFF);
if ( (channel_flag & 0xFF) == 0xFF )
{
/* 所有的位都要设置,它指出所有的ADC通道都已经转换过了 */
LPC_ADC->CR &= 0xF8FFFFFF; /* 停止ADC */
ADCIntDone = 1;
}
#else
LPC_ADC->CR &= 0xF8FFFFFF; /* 停止ADC */
ADCIntDone = 1;
#endif
}
return;
}
#endif
/**
* @函数名:ADCInit
* @描述:初始化ADC通道
* @参数:ADC_Clk ADC时钟频率
* @返回值:无
*/
void ADCInit( uint32_t ADC_Clk )
{
/* 除能ADC的供电下拉位 */
LPC_SYSCON->PDRUNCFG &= ~(0x1<<4);
/* 使能ADC的AHB时钟 */
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<13);
/* Unlike some other pings, for ADC test, all the pins need
to set to analog mode. Bit 7 needs to be cleared according
to design team. */
/* 不像其他的引脚,对ADC测试,所有的引脚需要设置为模拟模式。
根据设置,第7位需要被清除 */
#ifdef __JTAG_DISABLED
LPC_IOCON->JTAG_TDI_PIO0_11 &= ~0x8F; /* ADC I/O 配置 */
LPC_IOCON->JTAG_TDI_PIO0_11 |= 0x02; /* ADC IN0 */
LPC_IOCON->JTAG_TMS_PIO1_0 &= ~0x8F;
LPC_IOCON->JTAG_TMS_PIO1_0 |= 0x02; /* ADC IN1 */
LPC_IOCON->JTAG_TDO_PIO1_1 &= ~0x8F;
LPC_IOCON->JTAG_TDO_PIO1_1 |= 0x02; /* ADC IN2 */
LPC_IOCON->JTAG_nTRST_PIO1_2 &= ~0x8F;
LPC_IOCON->JTAG_nTRST_PIO1_2 |= 0x02; /* ADC IN3 */
LPC_IOCON->ARM_SWDIO_PIO1_3 &= ~0x8F;
LPC_IOCON->ARM_SWDIO_PIO1_3 |= 0x02; /* ADC IN4 */
#endif
LPC_IOCON->PIO1_4 &= ~0x8F; /* 清除第7位, 改变为模拟模式. */
LPC_IOCON->PIO1_4 |= 0x01; /* ADC IN5 */
LPC_IOCON->PIO1_10 &= ~0x8F; /* 清除第7位, 改变为模拟模式. */
LPC_IOCON->PIO1_10 |= 0x01; /* ADC IN6 */
LPC_IOCON->PIO1_11 &= ~0x8F; /* 清除第7位, 改变为模拟模式. */
LPC_IOCON->PIO1_11 |= 0x01; /* ADC IN7 */
LPC_ADC->CR = ( 0x01 << 0 ) | /* SEL=1, 选择ADC0里的0~7通道 */
( ( SystemAHBFrequency / ADC_Clk - 1 ) << 8 ) | /* CLKDIV = Fpclk / 1000000 - 1 */
( 0 << 16 ) | /* BURST = 0, no BURST, 软件控制 */
( 0 << 17 ) | /* CLKS = 0, 11 clocks/10 bits */
( 1 << 21 ) | /* PDN = 1, 正常操作 */
( 0 << 22 ) | /* TEST1:0 = 00 */
( 0 << 24 ) | /* START = 0 A/D 转换停止 */
( 0 << 27 ); /* EDGE = 0 (CAP/MAT下降信号, 触发A/D转换 */
/* 如果是轮询的话,不需要做接下来的工作 */
#if ADC_INTERRUPT_FLAG
NVIC_EnableIRQ(ADC_IRQn);
LPC_ADC->INTEN = 0x1FF; /* 使能所有的中断 */
#endif
return;
}
/**
* @函数名:ADCRead
* @描述:读ADC通道的值
* @参数:channelNum 要读的通道号
* @返回值:所读通道的值,如果是在中断模式下,则返回通道号
*/
uint32_t ADCRead( uint8_t channelNum )
{
#if !ADC_INTERRUPT_FLAG
uint32_t regVal, ADC_Data;
#endif
/* 通道号从0到7 */
if ( channelNum >= ADC_NUM )
{
channelNum = 0; /* 重置通道号为 0 */
}
LPC_ADC->CR &= 0xFFFFFF00;
LPC_ADC->CR |= (1 << 24) | (1 << channelNum);
/* 开始A/D转换 */
#if !ADC_INTERRUPT_FLAG
while ( 1 ) /* 等待,直到A/D转换结束 */
{
regVal = *(volatile unsigned long *)(ADC_BASE
+ ADC_OFFSET + ADC_INDEX * channelNum);
/* 读A/D转换的结果 */
if ( regVal & ADC_DONE )
{
break;
}
}
LPC_ADC->CR &= 0xF8FFFFFF; /* 停止ADC */
if ( regVal & ADC_OVERRUN ) /* 如果当前没有过载,就保存值,否则返回0 */
{
return ( 0 );
}
ADC_Data = ( regVal >> 6 ) & 0x3FF;
return ( ADC_Data ); /* 返回A/D转换的值 */
#else
return ( channelNum ); /* 如果是在中断模式下,则读ADC的值在中断处理函数
中进行,此处只返回通道号 */
#endif
}
/**
* @函数名:ADC0BurstRead
* @描述:使用burst模式,一次转换多个通道的值
* @参数:无
* @返回值:无
*/
void ADCBurstRead( void )
{
if ( LPC_ADC->CR & (0x7<<24) )
{
LPC_ADC->CR &= ~(0x7<<24);
}
/* 使用burst模式测试通道5,6,7,这是因为它们没有共享JTAG引脚 */
LPC_ADC->CR &= ~0xFF;
/* 读所有通道的值, 从0到7. */
LPC_ADC->CR |= (0xFF);
LPC_ADC->CR |= (0x1<<16); /* 设置burst模式,然后开始A/D转换 */
return; /* 读ADC是在中断处理函数里进行的,这里返回0. */
}
/*********************************************************************************
** End Of File
*********************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -