#include #include "stm32c5xx.h" // Delay loop for 48 MHz void delay(uint32_t msec) { for (uint32_t j=0; j < msec * 9600; j++) { __NOP(); } } // Initialize ADC1 for single conversion mode void init_analog() { // ADC and DAC Clock use HCLK/4 STM32_MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_ADCDACSEL, 0b00 << RCC_CCIPR2_ADCDACSEL_Pos); STM32_MODIFY_REG(RCC->CCIPR2, RCC_CCIPR2_ADCDACPRE, 0b010 << RCC_CCIPR2_ADCDACPRE_Pos); // Enable ADC 1 and 2 STM32_SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_ADC12EN); // Exit ADC deep power down mode STM32_CLEAR_BIT(ADC1->CR, ADC_CR_DEEPPWD); // Enable ADC voltage regulator STM32_SET_BIT(ADC1->CR, ADC_CR_ADVREGEN); // Delay 1-2 ms delay(2); // Stop the ADC STM32_CLEAR_BIT(ADC1->CR, ADC_CR_ADEN); // (Re-)start calibration for single ended mode STM32_CLEAR_BIT(ADC1->CR, ADC_CR_ADCAL); STM32_SET_BIT(ADC1->CR, ADC_CR_ADCAL); // Wait until the calibration is finished while (STM32_READ_BIT(ADC1->CR, ADC_CR_ADCAL)); // Clear the ready flag STM32_SET_BIT(ADC1->ISR, ADC_ISR_ADRDY); // Enable the ADC and wait until it is ready STM32_SET_BIT(ADC1->CR, ADC_CR_ADEN); while (!STM32_READ_BIT(ADC1->ISR, ADC_ISR_ADRDY)); // Select software start trigger STM32_MODIFY_REG(ADC1->CFGR1, ADC_CFGR1_EXTEN, 0b00 << ADC_CFGR1_EXTEN_Pos); // Select single conversion mode STM32_CLEAR_BIT(ADC1->CFGR1, ADC_CFGR1_CONT); // Set sample time to 48 clock cycles for all 14 channels STM32_MODIFY_REG(ADC1->SMPR1, ADC_SMPR1_SMP0, 0b101 << ADC_SMPR1_SMP0_Pos); STM32_MODIFY_REG(ADC1->SMPR1, ADC_SMPR1_SMP1, 0b101 << ADC_SMPR1_SMP1_Pos); STM32_MODIFY_REG(ADC1->SMPR1, ADC_SMPR1_SMP2, 0b101 << ADC_SMPR1_SMP2_Pos); STM32_MODIFY_REG(ADC1->SMPR1, ADC_SMPR1_SMP3, 0b101 << ADC_SMPR1_SMP3_Pos); STM32_MODIFY_REG(ADC1->SMPR1, ADC_SMPR1_SMP4, 0b101 << ADC_SMPR1_SMP4_Pos); STM32_MODIFY_REG(ADC1->SMPR1, ADC_SMPR1_SMP5, 0b101 << ADC_SMPR1_SMP5_Pos); STM32_MODIFY_REG(ADC1->SMPR1, ADC_SMPR1_SMP6, 0b101 << ADC_SMPR1_SMP6_Pos); STM32_MODIFY_REG(ADC1->SMPR1, ADC_SMPR1_SMP7, 0b101 << ADC_SMPR1_SMP7_Pos); STM32_MODIFY_REG(ADC1->SMPR1, ADC_SMPR1_SMP8, 0b101 << ADC_SMPR1_SMP8_Pos); STM32_MODIFY_REG(ADC1->SMPR1, ADC_SMPR1_SMP9, 0b101 << ADC_SMPR1_SMP9_Pos); STM32_MODIFY_REG(ADC1->SMPR2, ADC_SMPR2_SMP10, 0b101 << ADC_SMPR2_SMP10_Pos); STM32_MODIFY_REG(ADC1->SMPR2, ADC_SMPR2_SMP11, 0b101 << ADC_SMPR2_SMP11_Pos); STM32_MODIFY_REG(ADC1->SMPR2, ADC_SMPR2_SMP12, 0b101 << ADC_SMPR2_SMP12_Pos); STM32_MODIFY_REG(ADC1->SMPR2, ADC_SMPR2_SMP13, 0b101 << ADC_SMPR2_SMP13_Pos); // Enable internal temperature sensor (channel 12) STM32_SET_BIT(ADC12_COMMON->CCR,ADCC_CCR_TSEN); // Enable internal reference (channel 13) STM32_SET_BIT(ADC12_COMMON->CCR,ADCC_CCR_VREFEN); } // Read from an analog input of ADC1 uint32_t read_analog(uint32_t channel) { // Number of channels to convert: 1 STM32_MODIFY_REG(ADC1->SQR1, ADC_SQR1_LEN, 0 << ADC_SQR1_LEN_Pos); // ADC does one conversion more than configured here // Select the channel STM32_MODIFY_REG(ADC1->SQR1, ADC_SQR1_SQ1, channel << ADC_SQR1_SQ1_Pos); // Clear the finish flag STM32_CLEAR_BIT(ADC1->ISR, ADC_ISR_EOC); // Start a conversion STM32_SET_BIT(ADC1->CR, ADC_CR_ADSTART); // Wait until the conversion is finished while (!STM32_READ_BIT(ADC1->ISR, ADC_ISR_EOC)); while (STM32_READ_BIT(ADC1->CR, ADC_CR_ADSTART)); // Return the lower 12 bits of the result return ADC1->DR & 0b111111111111; } int main() { init_analog(); // Enable port A STM32_SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOAEN); // Configure PA4 as analog input for ADC1_IN4 (=default after reset) STM32_MODIFY_REG(GPIOA->MODER, GPIO_MODER_MODE4, 0b11 << GPIO_MODER_MODE4_Pos); volatile uint32_t a; while (1) { a=read_analog(0); a=read_analog(1); a=read_analog(2); a=read_analog(3); a=read_analog(4); a=read_analog(5); a=read_analog(6); a=read_analog(7); a=read_analog(8); a=read_analog(9); a=read_analog(10); a=read_analog(11); a=read_analog(12); a=read_analog(13); } }