Na dostępne wyjścia układu wyprowadzono piny ADC o numerach:
- PA0 - ADC kanał 0
- PF10 - ADC kanał 1
- PF9 - ADC kanał 2
- PF8 - ADC kanał 3
- PF7 - ADC kanał 4
- PF6 - ADC kanał 5
Inicjalizacja portu GPIO w trybie analogowym:
- void ADC_PA0_GPIO_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct;
- __GPIOA_CLK_ENABLE();
- //Konfiguracja GPIO PA0
- GPIO_InitStruct.Pin = GPIO_PIN_0;
- GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
- HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
- }
Włączenie układu ADC:
- ADC_HandleTypeDef Adc_Handle_Conf;
- void ADC1s_InitADC(void)
- {
- __HAL_RCC_ADC1_CLK_ENABLE();
- Adc_Handle_Conf.Instance = ADC1;
- Adc_Handle_Conf.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4; //ustawienie 25MHz
- /*
- * Dostepna konfiguracja prescalera dla taktowania linii 100MHz
- * #define ADC_CLOCKPRESCALER_PCLK_DIV1 ADC_CLOCK_SYNC_PCLK_DIV1 //100Mhz
- * #define ADC_CLOCKPRESCALER_PCLK_DIV2 ADC_CLOCK_SYNC_PCLK_DIV2 //50Mhz
- * #define ADC_CLOCKPRESCALER_PCLK_DIV4 ADC_CLOCK_SYNC_PCLK_DIV4 //25Mhz
- * #define ADC_CLOCKPRESCALER_PCLK_DIV6 ADC_CLOCK_SYNC_PCLK_DIV6 //16,66MHz
- * #define ADC_CLOCKPRESCALER_PCLK_DIV8 ADC_CLOCK_SYNC_PCLK_DIV8 //12.5MHz
- */
- Adc_Handle_Conf.Init.Resolution = ADC_RESOLUTION_12B;
- Adc_Handle_Conf.Init.ScanConvMode = DISABLE;
- Adc_Handle_Conf.Init.ContinuousConvMode = DISABLE;
- Adc_Handle_Conf.Init.DiscontinuousConvMode = DISABLE;
- Adc_Handle_Conf.Init.NbrOfDiscConversion = 0;
- Adc_Handle_Conf.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
- Adc_Handle_Conf.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1;
- Adc_Handle_Conf.Init.DataAlign = ADC_DATAALIGN_RIGHT;
- Adc_Handle_Conf.Init.NbrOfConversion = 1; //Pojedyncza konwersja
- Adc_Handle_Conf.Init.DMAContinuousRequests = DISABLE;
- Adc_Handle_Conf.Init.EOCSelection = DISABLE;
- HAL_ADC_Init(&Adc_Handle_Conf);
- }
Funkcja odczytująca pojedynczy wynik pomiaru:
- uint16_t ADC1s_Read_Data(ADC1s_NAME_t adc_name)
- {
- uint16_t wartosc_ADC=0;
- ADC_ChannelConfTypeDef ADC_Channel_Conf;
- ADC_Channel_Conf.Channel = ADC_CHANNEL_0;
- ADC_Channel_Conf.Rank = 1;
- ADC_Channel_Conf.SamplingTime = ADC_SAMPLETIME_3CYCLES;
- ADC_Channel_Conf.Offset = 0;
- if (HAL_ADC_ConfigChannel(&Adc_Handle_Conf, &ADC_Channel_Conf) != HAL_OK) { return 0; }
- if (HAL_ADC_Start(&Adc_Handle_Conf) != HAL_OK) { return 0; }
- HAL_ADC_PollForConversion(&Adc_Handle_Conf, 10);
- if(HAL_IS_BIT_CLR(HAL_ADC_GetState(&Adc_Handle_Conf), HAL_ADC_STATE_REG_EOC)) { return 0; }
- wartosc_ADC=HAL_ADC_GetValue(&Adc_Handle_Conf);
- return(wartosc_ADC);
- }
Tą funkcje można zmodyfikować tak aby były odczytywane większe ilości danych. Wykonuje się to poprzez zapętlenie pomiaru pojedynczego np. za pomocą pętli for. Dane po każdej konwersji zbiera się do wspólnej zmiennej (najbezpieczniej 32 bitowej uint32_t). Po przejściu zadanej liczby pomiarów wykonuje się dzielenie przez ilość pomiarów. Można też wykonać przesunięcia bitowe w lewo przy stosowaniu regularnych zakresów. Schemat poniżej:
Liczba pomiarów - 4; Przesunięcie - 2;
Liczba pomiarów - 8; Przesunięcie - 3;
Liczba pomiarów - 16; Przesunięcie - 4;
Liczba pomiarów - 32 Przesunięcie - 5;
Liczba pomiarów - 64; Przesunięcie - 6;
Liczba pomiarów - 128; Przesunięcie - 7;
Przesuniecie będzie wyglądało następująco: zmienna_32_bit = (zmienna_32_bit >> przesuniecie);