STM32F303VC Diferansiyel ADC Sorunu

Başlatan NaMcHo, 28 Ocak 2013, 14:51:25

NaMcHo

Merhabalar,

STM32F3 Discovery kitiyle diferansiyel ADC okuması yapıyorum ancak ADC'den alınan sonuçlar hatalı oluyor.
Tablodaki V+ (PA6) ve V- (PA7) değerleri voltmetreyle ölcülen değerlerdir.

Sizce bunun sebebi nedir?







V+             V-             ADC'den Alınan Sonuc             ADC'den Okunması Gereken
2.71V             1.32V             2176mV             2.71-1.32V
2.57V             1.24V             2130mV             2.57-1.24V
2.35V             1.14V             2081mV             2.35-1.14V
2.21V             1.07V             2037mV             2.21-1.07V


Uygulama Kodu
#include <stm32f30x.h>

//Global Degiskenler
uint8_t nmos_offset=0,pmos_offset=0;
uint32_t kalibrasyon_degeri,voltaj_degeri,temp;

//Fonksiyon Ön Tanimlamalari
void Delay(uint32_t delay);
void OpampCalib(void);
void OpampHazirla(void);
void AdcHazirla(void);

//Ana Fonksiyon
int main()
{
	//uint32_t temp;
	SystemInit();
	//OpampHazirla();
	AdcHazirla();
	ADC_StartConversion(ADC2);
	while(1)
	{
			while(ADC_GetFlagStatus(ADC2, ADC_FLAG_EOC) == RESET);
			temp=ADC_GetConversionValue(ADC2);
		       //VDDA'ya 2.95 geliyor
			voltaj_degeri=(temp*2950)/0xFFF;	//0xfff yerine 4095 yazinca asm ciktisina bak.		
	}
}

void Delay(uint32_t delay)
{
	while(delay--);
}
void AdcHazirla(void)
{
		ADC_InitTypeDef 			adcInit;
		ADC_CommonInitTypeDef adcOrtak;
		GPIO_InitTypeDef 			gpioInit;
		//PLL cikisi 2ye bolunce ve ADC beslencek
		RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div2);
		//ADC1 ve ADC2 icin AHB'den clock saglancak.
		RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12, ENABLE);
		//PA3 -> ADC1_IN4, PA2 -> ADC1_IN3
		//PA6 -> ADC2_IN3, PA7 -> ADC2_IN4
		RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);		
		gpioInit.GPIO_Pin=GPIO_Pin_6 | GPIO_Pin_7;
		gpioInit.GPIO_Mode=GPIO_Mode_AN;
		gpioInit.GPIO_PuPd=GPIO_PuPd_NOPULL;
		GPIO_Init(GPIOA,&gpioInit);
	
		adcInit.ADC_ContinuousConvMode=ADC_ContinuousConvMode_Enable;
		adcInit.ADC_Resolution=ADC_Resolution_12b;
		adcInit.ADC_ExternalTrigConvEvent=ADC_ExternalTrigConvEvent_0;
		adcInit.ADC_ExternalTrigEventEdge=ADC_ExternalTrigEventEdge_None;
		adcInit.ADC_DataAlign=ADC_DataAlign_Right;
		adcInit.ADC_OverrunMode=ADC_OverrunMode_Disable;
		adcInit.ADC_AutoInjMode=ADC_AutoInjec_Disable;
		adcInit.ADC_NbrOfRegChannel=1;
		ADC_Init(ADC2,&adcInit);
	
		adcOrtak.ADC_Mode=ADC_Mode_Independent;
		adcOrtak.ADC_Clock=ADC_Clock_AsynClkMode;
		adcOrtak.ADC_DMAAccessMode=ADC_DMAAccessMode_Disabled;
		adcOrtak.ADC_DMAMode=ADC_DMAMode_OneShot;
		//Dual modda, 2 ornekleme arasindaki gecikmeyi belirliyor.
		adcOrtak.ADC_TwoSamplingDelay=0;
		ADC_CommonInit(ADC2,&adcOrtak);
		
		//ADC kalibrasyonu
		ADC_VoltageRegulatorCmd(ADC2, ENABLE);	//Kalibrasyon icin gerekli bu voltaj
		Delay(7200);	
		ADC_SelectCalibrationMode(ADC2, ADC_CalibrationMode_Differential);	
		ADC_StartCalibration(ADC2);
		//Kalibrasyon tamamlanana kadar bekle
		while(ADC_GetCalibrationStatus(ADC2) != RESET);
		kalibrasyon_degeri=ADC_GetCalibrationValue(ADC2);
		
		//Girisimiz diferansiyel olucak
		ADC_SelectDifferentialMode(ADC2,ADC_Channel_3,ENABLE);
		
		//ADC1 kanal3'ü birinci siraya yerlestir ve ornekleme zamani 181.5Cycle olsun
		//Opamp1'in cikisi ADC_Channel3 vasitasiyle okuncak.
		//											 ADCX	 Kanal         Rank      Ornekleme zamani
		ADC_RegularChannelConfig(ADC2, ADC_Channel_3, 1, ADC_SampleTime_7Cycles5);
		
		//ADC1 aktif et
		ADC_Cmd(ADC2, ENABLE);
		
		//ADC ayarlari hazir olana kadar bekle.
		while(!ADC_GetFlagStatus(ADC2, ADC_FLAG_RDY));
			
}


Referans Manual, Datasheet vs... : http://www.st.com/internet/mcu/product/252054.jsp