#define RCC_BASE 0x40021000
#define ADC_BASE 0x40012400
#define RCC_APBENR2 (*((volatile uint32_t*)(RCC_BASE + 0x40)))
#define ADC_ISR (*((volatile uint32_t*)(ADC_BASE + 0x00)))
#define ADC_CR (*((volatile uint32_t*)(ADC_BASE + 0x08)))
#define ADC_CFGR2 (*((volatile uint32_t*)(ADC_BASE + 0x10)))
#define ADC_SMPR (*((volatile uint32_t*)(ADC_BASE + 0x14)))
#define ADC_CHSELR (*((volatile uint32_t*)(ADC_BASE + 0x28)))
#define ADC_DR (*((volatile uint32_t*)(ADC_BASE + 0x40)))
#define ADC_CFGR1 (*((volatile uint32_t*)(ADC_BASE + 0x0C)))
#define RCC_APBENR2_ADCEN (1<<20)
#define ADC_CR_ADEN (1<<0)
#define ADC_CR_ADCAL (1<<31)
#define ADC_CFGR2_CKMODE (1<<30)
#define ADC_CHSELR_CHSEL0 (1<<0)
#define ADC_CHSELR_CHSEL1 (1<<1)
#define ADC_CHSELR_CHSEL2 (1<<2)
#define ADC_SMPR_SMP_1_5 0 //(0<<0);
#define ADC_CR_ADSTART (1<<2)
#define ADC_ISR_ADRDY (1<<0)
#define ADC_ISR_EOC (1<<2)
#define AWD1CH0 (0x0<<26)
#define AWD1CH1 (0x1<<26)
#define AWD1CH2 (0x2<<26)
#define AWD1EN (1<<23)
#define AWD1SGL (1<<22)
#define CHSELRMOD (1<<21)
#define CONT (1<<13)
#define EXTEN (3<<10)
#define SCANDIR (1<<2)
#define CCRDY (1<<13)
#define SMPSEL0 (1<<8)
#define SMPSEL1 (1<<9)
#define SMPSEL2 (1<<10)
#define RES (3<<3)
#define ALIGN (1<<5)
void ADC_Init(void) {
// Enable ADC clock
RCC_APBENR2 |= RCC_APBENR2_ADCEN;
ADC_CR |= ADC_CR_ADDIS;//disable ADC
while (ADC_CR & ADC_CR_ADDIS);
ADC_CR |= ADC_CR_ADCAL; // Start calibration
while (ADC_CR & ADC_CR_ADCAL); // Wait for calibration to complete
// Configure ADC clock mode (HCLK/1)
ADC_CFGR2 &= ~ADC_CFGR2_CKMODE;
// Configure sampling time for all channels (use SMP1 setting)
ADC_SMPR = SMPSEL0 | SMPSEL1 | SMPSEL2; // Use SMP1 for all channels
ADC_SMPR |= (0x0 << 0); // Sampling time: 1.5 cycles
// Disable continuous conversion, enable single conversion
ADC_CFGR1 &= ~CONT; // Single conversion mode
ADC_CFGR1 &= ~SCANDIR; // Forward scan direction
ADC_CFGR1 &= ~CHSELRMOD; // Non-configurable sequencer
// Enable ADC
ADC_CR |= ADC_CR_ADEN;
while (!(ADC_ISR & ADC_ISR_ADRDY)); // Wait until ADC is ready
}
uint16_t ADC_Read(uint8_t channel) {
// Ensure ADC is not running a conversion
if (ADC_CR & ADC_CR_ADSTART) {
ADC_CR |= ADC_CR_ADSTP; // Stop any ongoing conversion
while (ADC_CR & ADC_CR_ADSTART); // Wait for stop
}
ADC_CHSELR = (1 << channel);
while (!(ADC_ISR & CCRDY));
ADC_ISR |= CCRDY; // Clear CCRDY flag
// Start conversion
ADC_CR |= ADC_CR_ADSTART;
while (!(ADC_ISR & ADC_ISR_EOC));
return ADC_DR;
}
int main(void) {
Serial.begin(115200);
ADC_Init();
while (1) {
uint16_t adc_value_ch0 = ADC_Read(0); // Channel 0
uint16_t adc_value_ch1 = ADC_Read(1); // Channel 1
uint16_t adc_value_ch2 = ADC_Read(2); // Channel 2
Serial.print("value1:");
Serial.println(adc_value_ch0);
Serial.print("value2:");
Serial.println(adc_value_ch1);
Serial.print("value3:");
Serial.println(adc_value_ch2);
for (volatile int i = 0; i < 100000; i++);
}
}