⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adc.c

📁 基于MDK的LPC1100处理器开发应用例程
💻 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 + -