Electrical – STM8S ADC Always Reading 3.3v

adcmicrocontrollerstm8

I've just gotten into STM8 programming and am trying to figure out how to read voltages with its ADC. This was one of my first forays into embedded C programming, so "nooby" code mistakes aren't completely out of the question here. I've already had success getting UART and basic GPIO functionality working, but I just can't seem to figure out what's going on with the ADC. For some reason, as the title implies, I keep getting the maximum ADC value (Vdd = +3.3V), and the data registers read 1023, with a bit of fluctuation. I've tried different voltage sources (potentiometer, function gen. and even directly tying the pin to GND) to no avail. The particular device I have is the 20-pin STM8S103F3, and I'm using SDCC+STM8Flash to program the device. I'm using a custom header file defining register addresses, and have double-checked that they match the datasheet. My configurations are as follows:

//Code from an example I found online, modified to fit my device
//On the STM8S103F3, AIN0 and 1 are not physically mapped to a pin 
//so I'm using AIN2 (PC4). I'm just trying to poll the ADC without
//interrupts. Just reading the values directly.

//***This isn't the entire code here. Just the parts pertaining to the ADC.***

PC_DDR = 0b00000000; //Setting all of Port C to input
PC_CR1 = 0b00000000;
PC_CR2 = 0b00000000; //GPIO config registers set according to the datasheet
ADC_CSR = 0b00000010; //Set ADC channel to 2 for AIN2 (lower 4 bits set channel)
ADC_TDRL = 0b00000100; //Disable Schmitt trigger for channel 2
ADC_CR1 = 0b01000000; //Frequency prescaler = f/8
ADC_CR2 = 0b00001000; //Right-aligning data
ADC_CR3 = 0b00000000; //Disabling buffer

//Then, to poll the ADC by enabling the ADON bit
ADC_CR1 |= 0x00000001; //This was from the example code, what's the difference between 0x and 0b?
ADC_CSR &= 0x01111111; //Not entirely sure what's going on here, but maybe clearing the EOC flag?
while ((ADC_CSR & 0b10000000) == 0); //Waiting for the EOC bit to be set?
result = ((unsigned int)(ADC_DRH * 256) + (unsigned int)ADC_DRL); //Concatenating the upper and lower bytes to form a 10-bit value

With the above ADC configurations, I've only gotten values ranging from 1023..1016 or so, no matter what voltage I apply to the input. Any thoughts? Thanks!

Best Answer

Alright, I just figured it out. Turns out I actually did make a code mistake. The EOC flag wasn't getting toggled properly using ADC_CSR, and the boolean operation was indeed suspect. I think that boolean operation (ADC_CSR &= 0x01111111) was inadvertently resetting the channel as well, leading to the incorrect measurement. Whoops!