Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Empezar (index.html)
Hardware (hardware.html)
Programación (programming.html)
Cargador de arranque (bootloader.html)
Bit Twiddling (bittwiddling.html)
GPIO - Entrada/salida de uso general (gpio.html)
PMC - Reloj del sistema (clock.html)
INT - Interrupciones (interrupts.html)
UART - Receptor-Transmisor Asíncrono Universal (uart.html)
TC - Interrupción de desbordamiento de temporizador/contador (timercounter.html)
TC - Temporizador/Contador Comparar Interrupción (timercounterdelay.html)
I2C - Circuito interintegrado (i2c.html)
SPI - Interfaz periférica serie (spi.html)
GPIO - GLCD (gpio-glcd.html)
RTC - Reloj en tiempo real (rtc.html)
RTT - Temporizador de tiempo real (rtt.html)
ADC - Convertidor Digital Analógico (adc.html)
DACC - Convertidor Analógico Digital (dacc.html)
SUPCC - Ahorro de energía/sueño/despertar (sleep.html)
QDEC - Decodificador de señal de cuadratura (qdec.html)
PWM - Modulación de ancho de pulso (pwm.html)
Depuración (debugging.html)
*nota* Cada vez que cambie la referencia de voltaje de entrada en el ADVREF, se debe ejecutar una
configuración automática de una sola vez.
Configuración
habilitar el reloj ADC en PMC
permitir interrupciones para ADC en NVIC
habilitar canales ADC (deshabilitar PIO)
establecer el preescalador del reloj ADC
establecer IBCTL en REG_ADC_ACR dependiendo de la frecuencia del reloj ADC
habilitar el tipo de interrupción
iniciar una conversión
escribir controlador de interrupción
En el primer ejemplo conectaremos la salida de un sensor de temperatura externo al canal ADC 0, que está en
PA17.
www.mwmw.ca/adc.html 1/6
22/3/2020 ATSAM4S ADC
(images/adclm35.jpg)
Hay dos interrupciones que se pueden usar para desencadenar un evento de fin de conversión.
EOC (fin de la conversión) o DRDY (datos listos). Ambos bits se pueden establecer en el registro de
REG_ADC_IER. Para borrar el indicador de interrupción EOC en el REG_ADC_ISR el REG_ADC_CDRx (registro
de datos del canal) necesita ser leído. Para borrar el indicador de interrupción DRDY, es necesario leer el
REG_ADC_LCDR (último registro de datos convertido).
Después de iniciar una conversión estableciendo el bit de inicio en el REG_ADC_CR el ADC convertirá los datos
y desencadenará una interrupción cuando haya
terminado.
(images/reg_adc_cdrx.jpg)
*nota* En la página 1117 muestra el Registro de Datos del Canal ADC (REG_ADC_CDRx) Parece que se puede
leer los registros en REG_ADC_CDR0, REG_ADC_CDR1, ... , REG_ADC_CDR15, pero si nos fijamos en las
definiciones en adc.h sólo se puede encontrar REG_ADC_CDR que se establece en la dirección 0x40038050 que
es channel0.
Tenemos que hacer nuestras propias definiciones para leer los otros registros.
(images/reg_adc_cdr.jpg)
Aquí está una lista de los registros y direcciones para REG_ADC_CDRx: Entonces, si queremos leer el valor de
REG_ADC_CDR15 (registro de datos de canal 15) entonces en nuestra configuración podemos definir esto como:
Para este sensor en particular, emite 10mv para cada grado C. Eso significa que es 21.4 C en esta habitación.
www.mwmw.ca/adc.html 2/6
22/3/2020 ATSAM4S ADC
#include "sam.h"
#include "basic_uart.h"
void clock_init(){
REG_CKGR_MOR |= CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTEN;
while (!(REG_PMC_SR & PMC_SR_MOSCXTS));
REG_CKGR_MOR |= CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCSEL;
REG_PMC_MCKR |= MC_MCKR_CSS_MAIN_CLK;
while (!(REG_PMC_SR & PMC_SR_MCKRDY));
REG_PMC_MCKR |= PMC_MCKR_PRES_CLK_1;
while (!(REG_PMC_SR & PMC_SR_MCKRDY));
}
void ADC_init(){
/*enabling the channel automatically gives peripheral control of the pin instead of the PIO
automatically configures pin to input, pull up enabled and connect to ground*/
//Need to just run once. If you change the voltage on ADVREF you need to run again
//ADC software reset
//REG_ADC_CR |= ADC_CR_SWRST;
//autocalibration
//REG_ADC_CR |= ADC_CR_AUTOCAL;
}
int main(void)
{
/* Initialize the SAM system */
SystemInit();
clock_init();
UART_Init();
ADC_init();
//start a conversion
REG_ADC_CR |= ADC_CR_START;
while (1)
{
}
}
//when ADC conversion is complete it will trigger an interrupt and interrupt will end by starting
void ADC_Handler( void) {
//read interrupt flag status register
uint32_t status = REG_ADC_ISR;
uint32_t adcData;
if ((status & ADC_IMR_EOC15) > 0){
//reading this register clears flag in ISR
www.mwmw.ca/adc.html 3/6
22/3/2020 ATSAM4S ADC
//reading this register clears flag in ISR
adcData = REG_ADC_CDR;
printString("Sensor Output: ");
printWord(adcData);
printString("\r\n");
}
//start the next conversion
REG_ADC_CR |= ADC_CR_START;
}
www.mwmw.ca/adc.html 4/6
22/3/2020 ATSAM4S ADC
#include "sam.h"
#include "basic_uart.h"
void clock_init(){
REG_CKGR_MOR |= CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTEN;
while (!(REG_PMC_SR & PMC_SR_MOSCXTS));
REG_CKGR_MOR |= CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCSEL;
REG_PMC_MCKR |= MC_MCKR_CSS_MAIN_CLK;
while (!(REG_PMC_SR & PMC_SR_MCKRDY));
REG_PMC_MCKR |= PMC_MCKR_PRES_CLK_1;
while (!(REG_PMC_SR & PMC_SR_MCKRDY));
}
void ADC_init(){
/*enabling the channel automatically gives peripheral control of the pin instead of the PIO
automatically configures pin to input, pull up enabled and connect to ground*/
//Need to just run once. If you change the voltage on ADVREF you need to run again
//ADC software reset
//REG_ADC_CR |= ADC_CR_SWRST;
//autocalibration
//REG_ADC_CR |= ADC_CR_AUTOCAL;
}
#define REG_ADC_CDR15 (*(__I uint32_t*)0x4003808CU) /**< \brief (ADC) Channel Data Register */
int main(void)
{
/* Initialize the SAM system */
SystemInit();
clock_init();
UART_Init();
ADC_init();
//start a conversion
REG_ADC_CR |= ADC_CR_START;
while (1)
{
}
}
//when ADC conversion is complete it will trigger an interrupt and interrupt will end by starting
void ADC_Handler( void) {
www.mwmw.ca/adc.html 5/6
22/3/2020 ATSAM4S ADC
www.mwmw.ca/adc.html 6/6