|
楼主 |
发表于 2019-10-10 21:07:44
|
显示全部楼层
/*****************************************************************************
* adc.c: ADC module file for NXP LPC17xx Family Microprocessors
*
* Copyright(C) 2009, NXP Semiconductor
* All rights reserved.
*
* History
* 2009.05.25 ver 1.00 Prelimnary version, first Release
*
******************************************************************************/
#include "lpc17xx.h"
#include "common.h"
#include "adc.h"
#include "queue_data.h"
#include "timer.h"
#include "app_adc.h"
/*********************************************************************************************************
** A/D Converters
*********************************************************************************************************/
#define ADC_DETECT_TOTAL 64
uint16_t ADC0Value[ADC_NUM];
uint32_t ADC0Value_total[ADC_NUM];
uint16_t ADC0Value_index[ADC_NUM];
uint8_t ADC0IntDone[ADC_NUM];
// 0,1,2,3,4,5,6,7
static const int channel_map[8]={0,0,0,1,2,3,0,0};
int adc_pclk;
static char flag_start=0;
uint32_t timer11;;
static u4t Round_schmitt_u4(u4t dividend, u4t divisor,u1t i)
{
static u4t backup[ADC_NUM];
u4t quotient;
quotient = dividend / divisor;
if ((dividend % divisor) != 0)
{
if (backup[i]>quotient)
{
++quotient;
}
}
backup[i] = quotient;
return (quotient);
}
#if BURST_MODE
volatile uint32_t channel_flag;
#endif
#define ADC_CHANNEL_MASK 0X3C //0x30 45 //0X3C 2345
#if ADC_INTERRUPT_FLAG
/******************************************************************************
** Function name: ADC_IRQHandler
**
** Descriptions: ADC interrupt handler
**
** parameters: None
** Returned value: None
**
******************************************************************************/
void ADC_IRQHandler (void)
{
volatile uint32_t regVal,tmp;
int index;
key_element_t el;
k3=regVal = LPC_ADC->ADSTAT; /* Read ADC will clear the interrupt */
++counter1;
el.dat=regVal;
el.index=counter1;
Key_queue_in(&el);
if ( regVal & 0x0000FF00 ) /* check OVERRUN error first */
{
regVal = (regVal & 0x0000FF00) >> 0x08;
/* if overrun, just read ADDR to clear */
/* regVal variable has been reused. */
switch ( regVal )
{
case 0x01:
regVal = LPC_ADC->ADDR0;
break;
case 0x02:
regVal = LPC_ADC->ADDR1;
break;
case 0x04:
regVal = LPC_ADC->ADDR2;
break;
case 0x08:
regVal = LPC_ADC->ADDR3;
break;
case 0x10:
regVal = LPC_ADC->ADDR4;
break;
case 0x20:
regVal = LPC_ADC->ADDR5;
break;
case 0x40:
regVal = LPC_ADC->ADDR6;
break;
case 0x80:
regVal = LPC_ADC->ADDR7;
break;
default:
break;
}
LPC_ADC->ADCR &= 0xF8FeFFFF; /* stop ADC now */
//ADC0IntDone = 1;
//el.dat=0;
//el.index=999;
// Key_queue_in(&el);
return;
}
if ( (regVal & ADC_ADINT)!=0 )
{
switch ( regVal & 0xFF ) /* check DONE bit */
{
case 0x01:
tmp=( LPC_ADC->ADDR0 >> 4 ) & 0xFFF;
ADC0Value_total[channel_map[0]] += tmp;
++ADC0Value_index[channel_map[0]];
break;
case 0x02:
tmp=( LPC_ADC->ADDR1 >> 4 ) & 0xFFF;
ADC0Value_total[channel_map[1]] += tmp;
++ADC0Value_index[channel_map[1]];
break;
case 0x04:
tmp=( LPC_ADC->ADDR2 >> 4 ) & 0xFFF;
ADC0Value_total[channel_map[2]] += tmp;
++ADC0Value_index[channel_map[2]];
el.dat=tmp;
el.index=2;
Key_queue_in(&el);
break;
case 0x08:
tmp=( LPC_ADC->ADDR3 >> 4 ) & 0xFFF;
ADC0Value_total[channel_map[3]] += tmp;
++ADC0Value_index[channel_map[3]];
break;
case 0x10:
tmp=( LPC_ADC->ADDR4 >> 4 ) & 0xFFF;
ADC0Value_total[channel_map[4]] += tmp;
++ADC0Value_index[channel_map[4]];
el.dat=tmp;
el.index=4;
Key_queue_in(&el);
break;
case 0x20:
tmp=( LPC_ADC->ADDR5 >> 4 ) & 0xFFF;
ADC0Value_total[channel_map[5]] += tmp;
++ADC0Value_index[channel_map[5]];
break;
case 0x40:
tmp=( LPC_ADC->ADDR6 >> 4 ) & 0xFFF;
ADC0Value_total[channel_map[6]] += tmp;
++ADC0Value_index[channel_map[6]];
break;
case 0x80:
tmp=( LPC_ADC->ADDR7 >> 4 ) & 0xFFF;
ADC0Value_total[channel_map[7]] += tmp;
++ADC0Value_index[channel_map[7]];
break;
default:
break;
}
if (flag_start==1 && ADC0Value_index[ADC_NUM-1]==ADC_DETECT_TOTAL)
{
flag_start=2;
regVal=TIMER0_get_value();
//el.dat=regVal-timer11;
//el.index=1000; // 10个周期时,5分频是12842个定时器节拍。
// Key_queue_in(&el);
for (index=0; index<ADC_NUM; index++)
{
ADC0Value[index]=Round_schmitt_u4(ADC0Value_total[index],ADC0Value_index[index],index);
ADC0Value_total[index]=0;
ADC0Value_index[index]=0; //有必要
ADC0IntDone[index] = 1;
}
LPC_ADC->ADINTEN = 0; /* disable interrupts, 虽然禁止了中断,但由于标志等下会产生,所以在下次再使能中断时会马上产生中断,所以在下次使能中断前先读一次所有的AD值(LPC_ADC->ADDRn)才清楚标志 */
LPC_ADC->ADCR &= 0xF8FeFFFF; /* stop ADC now 虽然停止了Burst,但还是会有一次中断进来,是最前那个道通的中断 执行LPC_ADC->ADINTEN = 0;可解决*/
}
}
return;
}
#endif
/*****************************************************************************
** Function name: ADCInit
**
** Descriptions: initialize ADC channel
**
** parameters: ADC clock rate
** Returned value: true or false
**
*****************************************************************************/
uint32_t ADCInit( uint32_t ADC_Clk )
{
uint32_t pclkdiv, pclk;
/* Enable CLOCK into ADC controller */
LPC_SC->PCONP |= (1 << 12);
/* all the related pins are set to ADC inputs, AD0.2~7 */
//LPC_PINCON->PINSEL0 |= 0x000000a0; /* P0.2~3, AD6,AD7, */
LPC_PINCON->PINSEL1 |= 0x00140000; /* P0.25~26, AD2,AD3, */
LPC_PINCON->PINSEL3 |= 0xF0000000; /* P1.30~31, AD4,AD5, */
/* By default, the PCLKSELx value is zero, thus, the PCLK for
all the peripherals is 1/4 of the SystemFrequency. */
pclkdiv = (LPC_SC->PCLKSEL0 >> 24) & 0x03;
switch ( pclkdiv )
{
case 0x00:
default:
pclk = SystemFrequency/4;
break;
case 0x01:
pclk = SystemFrequency;
break;
case 0x02:
pclk = SystemFrequency/2;
break;
case 0x03:
pclk = SystemFrequency/8;
break;
}
adc_pclk=pclk;
//AD0CR
LPC_ADC->ADCR = ( ADC_CHANNEL_MASK << 0 ) | /* SEL=0xdc,select channel 2~7 on ADC0 */
//18M pclk,CLKDIV=3(4分频)时机率性有AD值是FFF,CLKDIV=4(5分频)时没有FFF出现,但AD值有21个单位的波动
// CLKDIV=5(6分频)时D值有3个单位的波动
// ( ( pclk / ADC_Clk - 1 ) << 8 ) | /* CLKDIV = Fpclk / ADC_Clk - 1 */
( 2 << 8 ) |
( 0 << 16 ) | /* BURST = 0, no BURST, software controlled */
( 0 << 17 ) | /* CLKS = 0, 11 clocks/10 bits */
( 1 << 21 ) | /* PDN = 1, normal operation */
( 0 << 24 ) | /* START = 0 A/D conversion stops */
( 0 << 27 ); /* EDGE = 0 (CAP/MAT singal falling,trigger A/D conversion) */
/* If POLLING, no need to do the following */
#if ADC_INTERRUPT_FLAG
LPC_ADC->ADINTEN = 0x100|ADC_CHANNEL_MASK; /* Enable interrupts */
NVIC_EnableIRQ(ADC_IRQn);
#endif
return (TRUE);
}
static void get_adc0_value2(void)
{
key_element_t el;
if (ADC0IntDone[3]==(uint8_t)1)
{
ADC0IntDone[3]=(uint8_t)2;
app_adc_get16bit(ADC0Value);
el.dat=ADC0Value[0];
el.index=777;
Key_queue_in(&el);
}
}
boolt get_adc0_value(u2t* val,int channel)
{
if (ADC0IntDone[channel_map[channel]]==(uint8_t)1)
{
ADC0IntDone[channel_map[channel]]=(uint8_t)2;
*val=ADC0Value[channel_map[channel]];
return TRUE;
}
else
{
return FALSE;
}
}
volatile int _temp;
/*****************************************************************************
** Function name: ADC0BurstRead
**
** Descriptions: Use burst mode to convert multiple channels once.
**
** parameters: None
** Returned value: None
**
*****************************************************************************/
void ADCBurstRead( void )
{
int i;
for (i=0; i<ADC_NUM; i++)
{
ADC0Value_total[i]=0;
ADC0Value_index[i]=0;
ADC0IntDone[i]=0;
}
counter1=0;
_temp=LPC_ADC->ADDR0;
_temp=LPC_ADC->ADDR1;
_temp=LPC_ADC->ADDR2;
_temp=LPC_ADC->ADDR3;
_temp=LPC_ADC->ADDR4;
_temp=LPC_ADC->ADDR5;
_temp=LPC_ADC->ADDR6;
_temp=LPC_ADC->ADDR7;
/* Read all channels, 2 through 7. */
LPC_ADC->ADCR |= (ADC_CHANNEL_MASK);
LPC_ADC->ADCR |= (0x1<<16); /* Set burst mode and start A/D convert */
timer11 = TIMER0_get_value();
LPC_ADC->ADINTEN = ADC_CHANNEL_MASK; /* Enable interrupts */
return; /* the ADC reading is done inside the
handler, return 0. */
}
int j1=0;
void ADCTimer(void)
{
if (++j1==50)
{
j1=0;
flag_start=0;
}
//
}
void ADCProcess(void)
{
if (flag_start==0)
{
flag_start=1;
ADCBurstRead();
}
get_adc0_value2();
}
/*********************************************************************************
** End Of File
*********************************************************************************/
|
|