Conversión Analógico-Digital (ADC)
El proceso de ADC permite transformar una señal analógica, como el voltaje en un pin, en un valor numérico que puede ser almacenado y procesado en memoria.
Estructura del ADC en STM32
- Canales de entrada: Seleccionan las señales analógicas a convertir.
- Multiplexor analógico: Conmuta entre los diferentes canales.
- Convertidor A/D: Realiza la conversión propiamente dicha.
- Grupos de canales: Grupo estándar (16 canales + 1 registro de datos) y grupo inyectado (4 canales + 4 registros).
- Fuentes de disparo: Pueden ser por software o por hardware (ej. timers).
- Alimentación analógica: VREF+, VREF-, VDDA+, VDDA- para el correcto funcionamiento del circuito analógico.
- Registros de datos: Almacenan los resultados de las conversiones.
- Perro guardián analógico: Detecta si la señal está fuera de un umbral predefinido.
Modos de conversión del grupo estándar
- No escaneo, una sola conversión: Convierte un único canal una vez.
- No escaneo, conversión continua: Convierte un único canal repetidamente.
- Escaneo, una sola conevrsión: Convierte múltiples canales una sola vez.
- Escaneo, conversión continua: Convierte múltiples canales repetidamente.
Configuración adicional
- Alineación de datos: Alineación derecha o izquierda.
- Tiempo de conversión: Tiempo total = tiempo de muestreo + 12.5 ciclos ADC.
- Calibración: Incluye calibración normal y calibración tras reset.
Ejemplo: Lectura de un potenciómetro con ADC
Archivo de inicialización ADC: adc.c
#include "stm32f10x.h"
void ConfigurarADC(void)
{
// Activar reloj del ADC1 y GPIOA
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
// Configurar reloj del ADC a 12MHz (72MHz / 6)
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
// Configurar GPIO como entrada analógica
GPIO_InitTypeDef gpioConf;
gpioConf.GPIO_Pin = GPIO_Pin_0;
gpioConf.GPIO_Mode = GPIO_Mode_AIN;
gpioConf.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpioConf);
// Configurar modo ADC
ADC_InitTypeDef adcConf;
adcConf.ADC_Mode = ADC_Mode_Independent;
adcConf.ADC_DataAlign = ADC_DataAlign_Right;
adcConf.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
adcConf.ADC_ContinuousConvMode = DISABLE;
adcConf.ADC_ScanConvMode = DISABLE;
adcConf.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &adcConf);
// Seleccionar canal analógico
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
// Activar ADC
ADC_Cmd(ADC1, ENABLE);
// Calibrar ADC
ADC_ResetCalibration(ADC1);
while (ADC_GetResetCalibrationStatus(ADC1) == SET);
ADC_StartCalibration(ADC1);
while (ADC_GetCalibrationStatus(ADC1) == SET);
}
uint16_t LeerADC(void)
{
// Iniciar conversión
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
// Esperar finalización
while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
// Devolver valor leído
return ADC_GetConversionValue(ADC1);
}
Archivo principal: main.c
#include "stm32f10x.h"
#include "Delay.h"
#include "OLED.h"
#include "adc.h"
uint16_t lecturaADC;
int main(void)
{
OLED_Init();
ConfigurarADC();
OLED_ShowString(1, 1, "ADC Valor: ");
while (1)
{
lecturaADC = LeerADC();
OLED_ShowNum(1, 9, lecturaADC, 5);
}
}