cancel
Showing results for 
Search instead for 
Did you mean: 

Unable to init PA1 with ADC1 with no HAL or LL STM32F103C6T8 bluepill

mytechnotalent
Associate II

I am writing a bare-metal ADC driver from scratch and the issue that I am getting is on reading the value from PA1.

Here is my adc.c lib that I wrote.

#include "adc.h"
 
void ADC1_ADC_Init(void)
{
	RCC->APB2ENR |= (1U << 2U);					// IOPAEN I/O port A clk en							// rm 146
	GPIOA->CRL &= ~(1U << 5U);					// MODE1 input mode									// rm 171
	GPIOA->CRL &= ~(1U << 4U);					// MODE1 input mode									// rm 171
	GPIOA->CRL &= ~(1U << 7U);					// CNF1 analog mode									// rm 171
	GPIOA->CRL &= ~(1U << 6U);					// CNF1 analog mode									// rm 171
	RCC->APB2ENR |= (1U << 9U);					// ADC1EN ADC1 interface clk en						// rm 146
	ADC1->SQR3 &= ~(1U << 4U);					// SQ1 ADC_CH1 first conversion in reg seq			// rm 249
	ADC1->SQR3 &= ~(1U << 3U);					// SQ1 ADC_CH1 first conversion in reg seq			// rm 249
	ADC1->SQR3 &= ~(1U << 2U);					// SQ1 ADC_CH1 first conversion in reg seq			// rm 249
	ADC1->SQR3 &= ~(1U << 1U);					// SQ1 ADC_CH1 first conversion in reg seq			// rm 249
	ADC1->SQR3 |= (1U << 0U);					// SQ1 ADC_CH1 first conversion in reg seq			// rm 249
	ADC1->SQR1 &= ~(1U << 23U);					// SQ1 reg ch seq len, 1 conversion					// rm 247
	ADC1->SQR1 &= ~(1U << 22U);					// SQ1 reg ch seq len, 1 conversion					// rm 247
	ADC1->SQR1 &= ~(1U << 21U);					// SQ1 reg ch seq len, 1 conversion					// rm 247
	ADC1->SQR1 &= ~(1U << 20U);					// SQ1 reg ch seq len, 1 conversion					// rm 247
	ADC1->CR2 |= (1U << 0U);					// ADON A/D converter on/off en ADC start conv		// rm 243
 
}
 
void ADC1_ADC_StartConversion(void)
{
	ADC1->CR2 |= (1U << 22U);					// SWSTART start conversion of reg channels			// rm 240
}
 
uint32_t ADC1_ADC_Read(void)
{
	while(!(ADC1->SR & (1U << 1U))){};			// EOC end of conversion, conversion complete 		// rm 237
	return ADC1->DR;
}

Here is my main file.

#include "main.h"
#include "uart.h"
#include "adc.h"
 
uint32_t sensor_value;
 
int main(void)
{
//	RCC->APB2ENR |= (1U << 4U);					// IOPAEN I/O port C clk en							// rm 146
//	GPIOC->CRH |= (1U << 25U);					// MODE14 out mode, max speed 2 MHz					// rm 172
//	GPIOC->CRH &= ~(1U << 24U);					// MODE14 out mode, max speed 2 MHz					// rm 172
//	GPIOC->CRH &= ~(1U << 27U);					// CNF14 gp out push-pull							// rm 172
//	GPIOC->CRH &= ~(1U << 26U);					// CNF14 gp out push-pull							// rm 172						// rm 172
 
	USART1_UART_RxTxInit();
	ADC1_ADC_Init();
	ADC1_ADC_StartConversion();
 
	while(1)
	{
 
		sensor_value = ADC1_ADC_Read();
		printf("sensor value: %d\r\n", (int)sensor_value);
	}
}

One thing to note

void ADC1_ADC_StartConversion(void)
{
	ADC1->CR2 |= (1U << 22U);					// SWSTART start conversion of reg channels			// rm 240
}

When I watch the ADC1 CR2 register and try to set bit 22 it does NOT set for whatever reason.

The result is nothing gets printed to the UART1 to the terminal. I spent a few days on this and am reaching out here for assistance.

Thank you in advance.

3 REPLIES 3
mytechnotalent
Associate II

Found the answer after doing some reading of the reference manual.

Bit 0 ADON: A/D converter ON / OFF This bit is set and cleared by software. If this bit holds a value of zero and a 1 is written to it then it wakes up the ADC from Power Down state. Conversion starts when this bit holds a value of 1 and a 1 is written to it. The application should allow a delay of tSTAB between power up and start of conversion. Refer to Figure 23. 0: Disable ADC conversion/calibration and go to power down mode. 1: Enable ADC and to start conversion Note: If any other bit in this register apart from ADON is changed at the same time, then conversion is not triggered. This is to prevent triggering an erroneous conversion.

Instead of setting SWSTART simply set bit 0 once to wake up ADC from power down state and then set bit 0 a second time to turn on the A/D converter on.

You want to set CR2.EXTSEL to 0b111=SWSTART, to be able to trigger conversions using CR2.SWSTART.

JW

mytechnotalent
Associate II

@Community member​ 

	ADC1->CR2 |= (1U << 19U);
	ADC1->CR2 |= (1U << 18U);
	ADC1->CR2 |= (1U << 17U);
 
	ADC1->CR2 |= (1U << 22U);

this did not work however when I ran the below twice it did work.

ADC1->CR2 |= (1U << 0U);					// ADON A/D converter on/off en ADC start conv		// rm 243
ADC1->CR2 |= (1U << 0U);					// ADON A/D converter on/off en ADC start conv		// rm 243