adc.c 5.74 KB
Newer Older
李俭双's avatar
李俭双 committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
#include "adc.h"
#include "cgc.h"


/**
  * @brief  Enable the specified ADC channel .
  * @param  None
  * @retval None
  */
void ADC_Start(ADC_Channel_t ch)
{
	 ADC->ADS = ch;             //specify adc channel 
	 INTC_ClearPendingIRQ(ADC_IRQn); // clear INTAD interrupt flag	 
	 NVIC_ClearPendingIRQ(ADC_IRQn); // clear INTAD interrupt flag 
	 INTC_EnableIRQ(ADC_IRQn);		 // enable INTAD interrupt 
	 NVIC_EnableIRQ(ADC_IRQn);		 // enable INTAD interrupt

	if((ADC->ADTRG >> 6) != 3)		// write ADCS except for hardwait mode 
	{
		ADC->ADM0 |= (1<<7);            // enables conversion operation 
	}
}

/**
  * @brief  Disable the specified ADC peripheral.
  * @param  None
  * @retval None
  */
void ADC_Stop(void)
{
	ADC->ADM0 &= ~ADC_Start_Cmp; 			/* stops conversion operation */
	INTC_DisableIRQ(ADC_IRQn);      /* disable INTAD interrupt */
	INTC_ClearPendingIRQ(ADC_IRQn); /* clear INTAD interrupt flag */
	NVIC_ClearPendingIRQ(ADC_IRQn); /* clear INTAD interrupt flag */
}

/**
  * @brief  Initializes the ADC peripheral according to the specified
  *         parameters in the ADC_InitStruct .
  * @param  ADC_InitTypeDef: pointer to a ADC_InitTypeDef structure that contains
  *         the configuration information for the specified ADC peripheral.
  * @retval None
  */
void ADC_Init(ADC_InitTypeDef* ADC_InitStruct)
{
	assert_param(IS_ADC_MODE(ADC_InitStruct->ADC_Mode));
	
	CGC_PER0PeriphClockCmd(CGC_PER0Periph_ADC,ENABLE);
	ADC->ADM0  = 0x00U;                 // disable AD conversion and clear ADM0 register 
	INTC_DisableIRQ(ADC_IRQn);          // disable INTAD interrupt 
	INTC_ClearPendingIRQ(ADC_IRQn);     // clear INTAD interrupt flag    
	NVIC_ClearPendingIRQ(ADC_IRQn);     // clear INTAD interrupt flag 

	ADC->ADM1 |= ADC_InitStruct->ADC_ConvSpeed; //0x03 low current convertion mode

	ADC->ADM1 |= ADC_InitStruct->ADC_Mode;

	if(ADC_InitStruct->ADC_Mode == ADC_Mode_Scan)
	{
		ADC->ADM2 |= ADC_InitStruct->ADC_ScanConf.ADC_ChannelSign << 1;
	}


	ADC->ADM1 |= ADC_InitStruct->ADC_ContinuousConvMode;

	if (ADC_InitStruct->ADC_RefVoltage == ADC_Ref_Vdd)
	{
		ADC->ADM2 |= 0x00;
	}
	else if (ADC_InitStruct->ADC_RefVoltage == ADC_Ref_Extern)
	{
		ADC->ADM2 |= 0x40|0x20|0x00; // (refer voltage +) and (refer voltage -) are provided by extern voltage
	}
	else
	{
		ADC->ADM2 |= 0x80 | 0x00 ; // (refer voltage +) provided by internal 1.45v voltage and (refer voltage -)  provided by VSS
	}

	ADC->ADTRG |= ADC_InitStruct->ADC_ExternalTrigConv;
	ADC->ADTRG |= ADC_InitStruct->ADC_HardwareTrigSour;

	ADC->ADUL = ADC_InitStruct->ADC_UpLimit;
	ADC->ADLL = ADC_InitStruct->ADC_LowLimit;

	ADC->ADM0 &= ~(7 << 3);
	ADC->ADM0 |= ADC_InitStruct->ADC_Prescaler << 3;
	ADC->ADNSMP = ADC_InitStruct->ADC_TwoSamplingDelay;
	
	ADC->ADM0 |= ADC_Enable;
}

/**
  * @brief  Set the ADC peripheral running clock.
  * @param  fr:the specific clock 
  *         @arg ADC_Prescaler_Div32 
  *         @arg ADC_Prescaler_Div16 
  *         @arg ADC_Prescaler_Div8
  *         @arg ADC_Prescaler_Div4
  *         @arg ADC_Prescaler_Div2
  *         @arg ADC_Prescaler_Div1
  * @retval None
  */
void ADC_Set_Clock(ADC_Prescaler_t fr)
{
	ADC->ADM0 &= ~(7 << 3);
	ADC->ADM0 |= fr << 3;
}

/**
  * @brief  get ADC scan result of the specified adc channel.it scans 4
			channels one time
  * @param  ch:the specific ADC channel channel0~channel12
  * @param  times:the numer of scan times 
  * @param  buf:the scan result of  adc channel  
  * @retval  the average value of scann adc channel
  */
extern uint32_t   g_AdcIntTaken;

uint16_t ADC_Converse_Scan(ADC_Channel_t ch, uint32_t times, uint16_t *buf)
{
	uint32_t i,j;
	volatile uint8_t  flag;
	uint32_t total = 0;
陈家乐's avatar
陈家乐 committed
124
	uint16_t *buff = buf;
125 126 127 128 129 130
	if(times == 0)
	{
		return 0;
	}
	else{
		assert_param(IS_SCAN_START_CHAN(ch));
李俭双's avatar
李俭双 committed
131
	
132
		INTC_DisableIRQ(ADC_IRQn);     // disable INTAD interrupt 
李俭双's avatar
李俭双 committed
133

134
		ADC->ADM0 &= ~ADC_Enable;
李俭双's avatar
李俭双 committed
135

136 137
		ADC->ADM1 |= 0x08; //enable one-shot convertion
		ADC->ADM1 |= 0x80; //set sacn mode
李俭双's avatar
李俭双 committed
138

139 140
		ADC->ADTRG = ADC_ExternalTrig_Software;
		ADC->ADM0 |= ADC_Enable;
李俭双's avatar
李俭双 committed
141

142
		ADC->ADS  = ch;
李俭双's avatar
李俭双 committed
143

144
		for(i=0; i<times;i++)
李俭双's avatar
李俭双 committed
145
		{
146 147 148 149 150
			ADC->ADM0 |= ADC_Start_Cmp; //adc start
			for (j=0; j<4; j++)
			{
				while(INTC_GetPendingIRQ(ADC_IRQn) == 0);
				INTC_ClearPendingIRQ(ADC_IRQn); 	// clear INTAD interrupt flag 
李俭双's avatar
李俭双 committed
151

陈家乐's avatar
陈家乐 committed
152
				*buff++ = ADC->ADCR;
153
				total += ADC->ADCR;
李俭双's avatar
李俭双 committed
154 155


156 157 158
			}
		}
		return (uint16_t)(total / times); // return average value
李俭双's avatar
李俭双 committed
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
		}
}

/**
  * @brief  get ADC sample result of the specified adc channel.
  * @param  ch:the specific ADC channel
  * @param  times:the numer of adc sample times 
  * @param  buf:the scan result of  adc channel  
  * @retval  the average value of  adc sample
  */
uint16_t ADC_Converse(ADC_Channel_t ch, uint32_t times, uint16_t *buf)
{
	uint32_t i;
	volatile uint8_t  flag;
	uint32_t total = 0;

175 176 177 178 179 180 181
	if(times == 0)
	{
		return 0;
	}
	else
	{
		INTC_DisableIRQ(ADC_IRQn);     // disable INTAD interrupt 
李俭双's avatar
李俭双 committed
182

183
		ADC->ADM0 &= ~ADC_Enable;
李俭双's avatar
李俭双 committed
184

185 186 187
		ADC->ADM1 |= ADC_Conv_Oneshot; //enable one-shot convertion
		ADC->ADTRG = ADC_ExternalTrig_Software;
		ADC->ADM0 |= ADC_Enable;
李俭双's avatar
李俭双 committed
188

189
		ADC->ADS  = ch;
李俭双's avatar
李俭双 committed
190

191 192 193 194 195 196
		for(i=0; i<times;i++)
		{
			ADC->ADM0 |= ADC_Start_Cmp;  //adc start
			
			while(INTC_GetPendingIRQ(ADC_IRQn) == 0);
			INTC_ClearPendingIRQ(ADC_IRQn); 	// clear INTAD interrupt flag 
李俭双's avatar
李俭双 committed
197

198 199 200
			*buf++ = ADC->ADCR;
			total += ADC->ADCR;
		}
201
		return (uint16_t)(total / times); // return average value
李俭双's avatar
李俭双 committed
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
	}
}



/**
  * @brief  Set ADC hard trigger   .
  * @param  wait:the different ways of adc hard trigger
			it contains :ADC_ExternalTrig_Hardware_Wait
						ADC_ExternalTrig_Hardware_NoWait
  * @param  trg:it chooses hardware trigger source 
  * @retval  None
  */
void ADC_Set_HardTrigger(uint8_t wait, ADC_HardwareTrig_t trg)
{
	assert_param(IS_ADC_TRIGGER(wait));
	assert_param(IS_ADC_HARDTRIGGER(trg));	
	ADC->ADM0 &= ~ADC_Enable;

	ADC->ADTRG = wait | trg;

	ADC->ADM0 |= ADC_Enable;
}