adc 8 bits atmega48 avrgcc

Ir abajo

adc 8 bits atmega48 avrgcc

Mensaje por maigke el Mar 7 Mayo 2013 - 5:02

El código que presento a continuación se basó en tres ejemplos, uno de ellos de la página de cursomicros, cuyo autor es Shawn Johnson y el otro de comunidadatmel y avrFreaks, sin mas preámbulo

Circuito propuesto en Fritzing




Esquemático





La razón para elegir un reloj para el adc de 125kHz, no es ninguna en partícular, pero habrá que tomar en cuenta lo siguiente:

De acuerdo a Coughlin y Driscoll (1999), [libro de amplificadores operacionales y circuitos integrados lineales] un ADC de aproximaciones sucesivas, el tiempo de conversión se determina mediante la siguiente ecuación:

Tiempo de conversión = Tiempo reloj del ADC* (numero de bits del ADC + 1)

y del datasheet del propio ATmega48 que menciona que la frecuencia de muestreo a la máxima resolución es de 15kSps (miles de muestras por segundo). Se tiene entonces que el tiempo de conversión seria de

Tiempo de conversión = (1/15 000) = 67us (aproximadamente)

Por lo tanto, el tick requerido para que sea posible esa tasa de muestreo de acuerdo a la ecuación de Coughlin y Driscoll sería de:

Tiempo reloj del ADC = (67us/11 bits) = 6us (aproximadamente)
lo que nos da una frecuencia de reloj del adc de 164.1kHz, dado este valor límite, una frecuencia de operación menor, entregará una menor tasa de muestreo.

En este sentido, si se opera el Reloj RC interno del ATmega48, con el preescaler de los fuses seleccionado F_CPU/8, entonces, el valor de pre-escalamiento será de

PRE = F_CPU / F_deseada
PRE = 1000000Hz/125kHz (menor que 164.1kHz) = 8
avatar
maigke
Asiduo del Foro
Asiduo del Foro

Mensajes : 210
Fecha de inscripción : 12/04/2009
Edad : 41
Localización : Mexico

Volver arriba Ir abajo

Re: adc 8 bits atmega48 avrgcc

Mensaje por maigke el Mar 7 Mayo 2013 - 5:09

Aquí los fuentes
Código:

#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>
#include "lcd.h"

#define setbit(sfr,bit) (_SFR_BYTE(sfr)|=(_BV(bit)))
#define clearbit(sfr,bit) (_SFR_BYTE(sfr)&=~(_BV(bit)))

void adc_setup(void);
unsigned char adc_read(char channel);

int main(void)
{
    unsigned char n; // variable que recibira la lectura de 8 bits
    char buff[4];    //Buffer para lectura de ADC


    lcd_init();
    adc_setup();
    lcd_gotorc(1,5);
    lcd_puts("ADC0");
    while(1)
    {
        n = adc_read(0);


        sprintf(buff,"%3d",n); //campo de numeros

        lcd_gotorc(2,1);
        lcd_puts("val: ");
        lcd_gotorc(2,5);
        lcd_puts(buff);

    }
}

void adc_setup(void)
{
    //vref+ y Vref-: Vcc y GND
    //Justificación: Izquierda (Para lectura de 8 bits)
   
 
    clearbit(ADMUX,REFS1); //Referencia a AVcc
    setbit(ADMUX,REFS0);
   
    setbit(ADMUX,ADLAR);
   
    // Reloj del ADC0:        F_CPU/8 = 125kHz
    // Estado del convertidor:    ON
    // Modo:            Manual
   
    setbit(ADCSRA,ADEN);      //ADC habilitado
    clearbit(ADCSRA,ADATE);  //Modo manual (Normal)
   
    clearbit(ADCSRA,ADPS2); //Seleccion del  Prescalador reloj
    setbit(ADCSRA,ADPS1);    // n = 8
    setbit(ADCSRA,ADPS0);
}
unsigned char adc_read(char channel)
{
    ADMUX&=0xFF;
    ADMUX|=channel;
    _delay_us(10); //delay para estabilizar el voltaje de entrada del ADC
    setbit(ADCSRA,ADSC);  //se inicia la conversion
   
    while(bit_is_clear(ADCSRA,ADIF));  //Espera a que termine la conversion
   
    return ADCH;
}


Código:

/******************************************************************************
 * FileName:  lcd.h
 * Purpose:    Librería de funciones para controlar un display LCD con chip
 *            Hitachi HD44780 o compatible. La interface es de 4 bits.
 * Processor:  ATmel AVR
 * Compiler:  AVR IAR C y AVR GCC (WinAVR)
 * Author:    Shawn Johnson. http://www.cursomicros.com.
 *
 * Copyright (C) 2008 - 2013 Shawn Johnson. All rights reserved.
 *
 * License:    Se permiten el uso y la redistribución de este código con
 *            modificaciones o sin ellas, siempre que se mantengan esta
 *            licencia y las notas de autor y copyright de arriba.
 *****************************************************************************/

#include <avr/io.h>
#define F_CPU 1000000UL
#include <util/delay.h>
//****************************************************************************
//    CONFIGURACIÓN DE LOS PINES DE INTERFACE
//****************************************************************************

/* Define el puerto a donde se conectará el bus de datos del LCD
 * Se utilizará el nible alto del puerto escogido (ejem. PB4-DB4,...,PB7-DB7)
 */
#define  lcd_DATAout  PORTB      // Registro PORT del puerto
#define  lcd_DATAin    PINB      // Registro PIN del puerto
#define  lcd_DATAddr  DDRB      // Registro DDR del puerto

/* Define el puerto a donde se conectarán las líneas de control del LCD
 * E, RW y RS. Puede ser el mismo puerto del bus de datos.
 */
#define  lcd_CTRLout  PORTB      // Registro PORT del puerto
#define  lcd_CTRLin    PINB      // Registro PIN del puerto
#define  lcd_CTRLddr  DDRB      // Registro DDR del puerto

/* Define los números de los pines del puerto anterior que corresponderán a
 * las líneas E, RW y RS del LCD.
 */
#define  lcd_E        3          // Pin Enable
#define  lcd_RW        2          // Pin Read/Write
#define  lcd_RS        1          // Pin Register Select


//****************************************************************************
//    CÓDIGOS DE COMANDO USUALES
//****************************************************************************
#define  LCD_CLEAR    0x01    // Limpiar Display
#define  LCD_RETHOM  0x02    // Cursor a inicio de línea 1
#define  LCD_LINE1    0x80    // Línea 1 posición 0
#define  LCD_LINE2    0xC0    // Línea 2 posición 0
#define  LCD_DDRAM    0x80    // Dirección 0x00 de DDRAM
#define  LCD_CGRAM    0x40    // Dirección 0x00 de CGRAM
#define  LCD_CURSOR  0x0E    // Mostrar solo Cursor
#define  LCD_BLINK    0x0D    // Mostrar solo Blink
#define  LCD_CURBLK  0x0F    // Mostrar Cursor + Blink
#define  LCD_NOCURBLK 0x0C    // No mostrar ni Cursor ni Blink

//****************************************************************************
//    PROTOTIPOS DE FUNCIONES
//****************************************************************************
void lcd_init(void);                // Inicializa el LCD
void lcd_puts(char * s);            // Envía una cadena ram al LCD
void lcd_gotorc(char r, char c);    // Cursor a fila r, columna c
void lcd_clear(void);          // Limpia el LCD y regresa el cursor al inicio
void lcd_data(char dat);            // Envía una instrucción de dato al LCD
void lcd_cmd(char com);            // Envía una instrucción de comando al LCD
char lcd_read(char RS);            // Lee un dato del LCD
void lcd_write(char inst, char RS); // Escribe una instrucción en el LCD
void lcd_nibble(char nibble);
void ldelay_ms(unsigned char );


Código:

/******************************************************************************
 * FileName:  lcd.c
 * Purpose:    Librería de funciones para controlar un display LCD con chip
 *            Hitachi HD44780 o compatible. La interface es de 4 bits.
 * Processor:  ATmel AVR
 * Compiler:  AVR IAR C y AVR GCC (WinAVR)
 * Author:    Shawn Johnson. http://www.cursomicros.com.
 *
 * Copyright (C) 2008 - 2013 Shawn Johnson. All rights reserved.
 *
 * License:    Se permiten el uso y la redistribución de este código con
 *            modificaciones o sin ellas, siempre que se mantengan esta
 *            licencia y las notas de autor y copyright de arriba.
 *****************************************************************************/

#include "lcd.h"

//****************************************************************************
// Ejecuta la inicialización software completa del LCD. La configuración es
// de: interface de 4 bits, despliegue de 2 líneas y caracteres de 5x7 puntos.
//****************************************************************************
void lcd_init(void)
{
    /* Configurar las direcciones de los pines de interface del LCD */
    lcd_DATAddr |= 0xF0;
    lcd_CTRLddr |= (1<<lcd_E)|(1<<lcd_RW)|(1<<lcd_RS);

    /* Secuencia de inicialización del LCD en modo de 4 bits*/
    lcd_CTRLout &= ~((1<<lcd_E)|(1<<lcd_RW)|(1<<lcd_RS));
    ldelay_ms(45);        // > 40 ms
    lcd_nibble(0x30);      // Function Set: 8-bit
    ldelay_ms(5);          // > 4.1 ms
    lcd_nibble(0x30);      // Function Set: 8-bit
    ldelay_ms(1);          // > 100 µs
    lcd_nibble(0x30);      // Function Set: 8-bit
    ldelay_ms(1);          // > 40 µs
    lcd_nibble(0x20);      // Function Set: 4-bit
    ldelay_ms(1);          // > 40 µs
    lcd_nibble(0x20);      // Function Set: 4-bit, 2lines, 4×7font
    lcd_nibble(0x80);      //
    lcd_write(0x0C, 0); // Display ON/OFF Control: Display on, Cursor off, Blink off
    lcd_write(0x01, 0);    // Clear Display
    lcd_write(0x06, 0);    // Entry Mode Set
}

//****************************************************************************
// Escribe una instrucción en el LCD:
// Si RS = 0 la instrucción es de comando (Function Set, Entry Mode set, etc).
// Si RS = 1 la instrucción es de dato y va a la DDRAM o CGRAM.
//****************************************************************************
void lcd_write(char inst, char RS)
{
    while(lcd_read(0)&0x80);        // Esperar mientras LCD esté ocupado
    if(RS)
        lcd_CTRLout |= (1<<lcd_RS);  // Para escribir en DDRAM o CGRAM
    else
        lcd_CTRLout &= ~(1<<lcd_RS); // Para escribir en Registro de Comandos
    _delay_us(5);                    // Permite actualizar el Puntero de RAM
    lcd_nibble(inst);                // Enviar nibble alto
    lcd_nibble(inst<<4);            // Enviar nibble bajo
}

//****************************************************************************
// Envía el nibble alto de 'nibble' al LCD.
//****************************************************************************
void lcd_nibble(char nibble)
{
    lcd_CTRLout &= ~(1<<lcd_RW);    // Establecer Modo de escritura
    lcd_DATAddr |= 0xF0;            // Hacer nibble alto de bus de datos salida
    lcd_DATAout = (nibble&0xF0)|(lcd_DATAout&0x0F); // Colocar dato
    _delay_us(2);                    // tAS, set-up time > 140 ns
    lcd_CTRLout |= (1<<lcd_E);      // Pulso de Enable
    _delay_us(2);                    // Enable pulse width > 450 ns
    lcd_CTRLout &= ~(1<<lcd_E);      //
    lcd_DATAddr &= 0x0F;            // Hacer nibble alto entrada
}

//****************************************************************************
// Lee un byte de dato del LCD.
// Si RS = 1 se lee la locación de DDRAM o CGRAM direccionada actualmente.
// Si RS = 0 se lee el 'bit de Busy Flag' + el 'Puntero de RAM'.
//****************************************************************************
char lcd_read(char RS)
{
    char high, low;
    if(RS)
        lcd_CTRLout |= (1<<lcd_RS);  // Para leer de DDRAM o CGRAM
    else
        lcd_CTRLout &= ~(1<<lcd_RS); // Para leer Busy Flag + Puntero de RAM
    lcd_CTRLout |= (1<<lcd_RW);      // Establecer Modo Lectura
    lcd_DATAddr &= 0x0F;            // Hacer nibble alto entrada   
    _delay_us(2);                    // tAS, set-up time > 140 ns
    lcd_CTRLout |= (1<<lcd_E);      // Habilitar LCD
    _delay_us(2);                    // Data Delay Time > 1320 ns
    high = lcd_DATAin;              // Leer nibble alto
    lcd_CTRLout &= ~(1<<lcd_E);      // Para que el LCD prepare el nibble bajo
    _delay_us(2);                    // Enable cycle time > 1200 ns
    lcd_CTRLout |= (1<<lcd_E);      // Habilitar LCD
    _delay_us(2);                    // Data Delay Time > 1320 ns
    low = lcd_DATAin;                // Leer nibble bajo
    lcd_CTRLout &= ~(1<<lcd_E);      //
    return (high&0xF0)|(low>>4);    // Juntar nibbles leídos
}

//****************************************************************************
// Envían cadenas RAM terminadas en nulo al LCD.
//****************************************************************************
void lcd_puts(char * s)
{
    unsigned char c, i=0;
    while(c = s[i++])
        lcd_write(c, 1);        // Instrucción 'Write Data to DDRAM/CGRAM'
}

//****************************************************************************
// Ubica el cursor del LCD en la columna c de la línea r.
//****************************************************************************
void lcd_gotorc(char r, char c)
{
    if(r==1)  r = LCD_LINE1;
    else      r = LCD_LINE2;
    lcd_write(r+c-1, 0);        // Instrucción 'Set DDRAM Address'
}

//****************************************************************************
// Limpia la pantalla del LCD y regresa el cursor a la primera posición
// de la línea 1.
//****************************************************************************
void lcd_clear(void)
{
    lcd_write(LCD_CLEAR, 0);    // Instrucción 'Clear Display'
}

//****************************************************************************
// Envían instrucciones de comando y de datos al LCD.
//****************************************************************************
void lcd_cmd(char com)
{
    lcd_write(com, 0);          // Cualquier instrucción de comando
}
void lcd_data(char dat)
{
    lcd_write(dat, 1);          // Instrucción 'Write Data to DDRAM/CGRAM'
}

//****************************************************************************
// Genera un delay de n milisegundos
//****************************************************************************
void ldelay_ms(unsigned char n)
{
    while(n--)
        _delay_us(1000);
}
avatar
maigke
Asiduo del Foro
Asiduo del Foro

Mensajes : 210
Fecha de inscripción : 12/04/2009
Edad : 41
Localización : Mexico

Volver arriba Ir abajo

Re: adc 8 bits atmega48 avrgcc

Mensaje por maigke el Mar 7 Mayo 2013 - 5:15

Simulacióń en Proteus





What a Face What a Face What a Face What a Face
avatar
maigke
Asiduo del Foro
Asiduo del Foro

Mensajes : 210
Fecha de inscripción : 12/04/2009
Edad : 41
Localización : Mexico

Volver arriba Ir abajo

Re: adc 8 bits atmega48 avrgcc

Mensaje por Contenido patrocinado


Contenido patrocinado


Volver arriba Ir abajo

Volver arriba

- Temas similares

 
Permisos de este foro:
No puedes responder a temas en este foro.