#include #include #include #include #include static void SetupADC(ADC_t* adc, uint8_t channelMask, enum adcch_positive_input input, enum adc_reference reference, uint8_t internalInput) { struct adc_config adcConfig = { }; struct adc_channel_config adcChannelConfig = { }; // adc_read_configuration(adc, &adcConfig); // adcch_read_configuration(adc, channelMask, &adcChannelConfig); adc_set_clock_rate(&adcConfig, 62500); adc_set_conversion_trigger(&adcConfig, ADC_TRIG_MANUAL, 1, 0); adc_set_conversion_parameters(&adcConfig, ADC_SIGN_OFF, ADC_RES_12, reference); adc_enable_internal_input(&adcConfig, internalInput); adcch_set_input(&adcChannelConfig, input, ADCCH_NEG_NONE, 1); adc_write_configuration(adc, &adcConfig); adcch_write_configuration(adc, channelMask, &adcChannelConfig); adc_enable(adc); } static float CalcVcc(uint16_t val) { if (val == 0) return 0.0; return (1.0f * 4096.0f) / (float)val * 1.6f; // 1V internal reference measure, Vref = Vcc/1.6 } // res = (vinp - (-delta v)) / vref * top // delta v = vref * 0.05 // -> // res / top = (vinp - (-delta v)) / vref; // res / top * vref = vinp - (-delta v); // res / top * vref + (-delta v) = vinp // res / top * vref - vref * 0.05 = vinp static float CalcVinp(uint16_t res, float vref) { float top = 4095.0f; float vinp = (float)res / top * vref - vref * 0.05f; return vinp; } int main(void) { volatile float vcc; volatile uint16_t res; volatile float vinp; char out_test[200]; board_init(); sysclk_init(); sleepmgr_init(); irq_initialize_vectors(); // cpu_irq_enable(); uint8_t ADC_INFO_CHANNEL_MASK = 1; #define RESULT adc_get_unsigned_result(&ADCA, ADC_INFO_CHANNEL_MASK) SetupADC(&ADCA, ADC_INFO_CHANNEL_MASK, ADCCH_POS_BANDGAP, ADC_REF_BANDGAP, ADC_BANDGAP_bm); delay_ms(20); adc_start_conversion(&ADCA, ADC_INFO_CHANNEL_MASK); adc_wait_for_interrupt_flag(&ADCA, ADC_INFO_CHANNEL_MASK); res = RESULT; // 4095 vinp = CalcVinp(res, 1.0f); sprintf(out_test, "adc=%" PRIu16 " ADCCH_POS_BANDGAP / ADC_REF_BANDGAP = %.4f", res, ((float)res) / 4096.0f); adc_flush(&ADCA); SetupADC(&ADCA, ADC_INFO_CHANNEL_MASK, ADCCH_POS_SCALED_VCC, ADC_REF_BANDGAP, ADC_BANDGAP_bm); delay_ms(20); adc_start_conversion(&ADCA, ADC_INFO_CHANNEL_MASK); adc_wait_for_interrupt_flag(&ADCA, ADC_INFO_CHANNEL_MASK); res = RESULT; // 1514 (1350 erwartet) -> 0,891 vinp = CalcVinp(res, 1.0f); sprintf(out_test, "adc=%" PRIu16 " ADCCH_POS_SCALED_VCC / ADC_REF_BANDGAP = %.4f -> vcc = %.3f V", res, ((float)res) / 4096.0f, ((float)res) / 4096.0f * 10.0f); adc_flush(&ADCA); SetupADC(&ADCA, ADC_INFO_CHANNEL_MASK, ADCCH_POS_BANDGAP, ADC_REF_AREFA, ADC_BANDGAP_bm); delay_ms(20); adc_start_conversion(&ADCA, ADC_INFO_CHANNEL_MASK); adc_wait_for_interrupt_flag(&ADCA, ADC_INFO_CHANNEL_MASK); res = RESULT; // 1761 (1241 erwartet) -> 0,705 vinp = CalcVinp(res,3.3f); sprintf(out_test, "adc=%" PRIu16 " ADCCH_POS_BANDGAP / ADC_REF_AREFA = %.4f -> Aref = %.4f V", res, ((float)res) / 4096.0f, 1.0f / (((float)res) / 4096.0f)); adc_flush(&ADCA); SetupADC(&ADCA, ADC_INFO_CHANNEL_MASK, ADCCH_POS_SCALED_VCC, ADC_REF_AREFA, 0); delay_ms(20); adc_start_conversion(&ADCA, ADC_INFO_CHANNEL_MASK); adc_wait_for_interrupt_flag(&ADCA, ADC_INFO_CHANNEL_MASK); res = RESULT; // 658 (410 erwartet) -> 0,623 vinp = CalcVinp(res, 3.3f); sprintf(out_test, "adc=%" PRIu16 " ADCCH_POS_SCALED_VCC / ADC_REF_AREFA = %.4f -> scaled vcc = %.4f V", res, ((float)res) / 4096.0f, ((float)res) / 4096.0f * 3.3f); adc_flush(&ADCA); SetupADC(&ADCA, ADC_INFO_CHANNEL_MASK, ADCCH_POS_BANDGAP, ADC_REF_VCC, ADC_BANDGAP_bm); delay_ms(20); adc_start_conversion(&ADCA, ADC_INFO_CHANNEL_MASK); adc_wait_for_interrupt_flag(&ADCA, ADC_INFO_CHANNEL_MASK); res = RESULT; // 2395 (1985 erwartet) -> 0,829 vinp = CalcVinp(res, 3.3f / 1.6f); sprintf(out_test, "adc=%" PRIu16 " ADCCH_POS_BANDGAP / ADC_REF_VCC = %.4f -> vcc = %.4f V", res, ((float)res) / 4096.0f, 1.6f / (((float)res) / 4096.0f)); adc_flush(&ADCA); SetupADC(&ADCA, ADC_INFO_CHANNEL_MASK, ADCCH_POS_SCALED_VCC, ADC_REF_VCC, ADC_BANDGAP_bm); delay_ms(20); adc_start_conversion(&ADCA, ADC_INFO_CHANNEL_MASK); adc_wait_for_interrupt_flag(&ADCA, ADC_INFO_CHANNEL_MASK); res = RESULT; // 843 (655 erwartet) -> 0,777 vinp = CalcVinp(res, 3.3f / 1.6f); sprintf(out_test, "adc=%" PRIu16 " ADCCH_POS_SCALED_VCC / ADC_REF_VCC = %.4f -> vcc = %.4f * vcc", res, ((float)res) / 4096.0f, ((float)res) / 4096.0f * 6.25f); adc_flush(&ADCA); SetupADC(&ADCA, ADC_INFO_CHANNEL_MASK, ADCCH_POS_SCALED_VCC, ADC_REF_VCCDIV2, ADC_BANDGAP_bm); delay_ms(20); adc_start_conversion(&ADCA, ADC_INFO_CHANNEL_MASK); adc_wait_for_interrupt_flag(&ADCA, ADC_INFO_CHANNEL_MASK); res = RESULT; // 1005 (819 erwartet) -> 0,815 vinp = CalcVinp(res, 3.3f / 2.0f); sprintf(out_test, "adc=%" PRIu16 " ADCCH_POS_SCALED_VCC / ADC_REF_VCCDIV2 = %.4f -> vcc = %.4f * vcc", res, ((float)res) / 4096.0f, ((float)res) / 4096.0f * 5.0f); adc_flush(&ADCA); while (1) { } }