adc 8 bits atmega48 avrgcc
Página 1 de 1.
adc 8 bits atmega48 avrgcc
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
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
maigke- Asiduo del Foro
- Mensajes : 210
Fecha de inscripción : 12/04/2009
Edad : 47
Localización : Mexico
Re: adc 8 bits atmega48 avrgcc
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);
}
maigke- Asiduo del Foro
- Mensajes : 210
Fecha de inscripción : 12/04/2009
Edad : 47
Localización : Mexico
maigke- Asiduo del Foro
- Mensajes : 210
Fecha de inscripción : 12/04/2009
Edad : 47
Localización : Mexico
Temas similares
» MyOpenLab controlando un motor DC con microcontrolador AVR ATmega48 (Link)
» sumador\restador de 4 bits y comparador de 8
» Libreria LCD 20x 4 Flexible 3 bits SDCC PIC18F2550
» Libreria LCD 20 x 4 Flexible 4 bits SDCC PIC18F2550
» LCD 44780 4-bits para PIC16F, driver y ejemplo.
» sumador\restador de 4 bits y comparador de 8
» Libreria LCD 20x 4 Flexible 3 bits SDCC PIC18F2550
» Libreria LCD 20 x 4 Flexible 4 bits SDCC PIC18F2550
» LCD 44780 4-bits para PIC16F, driver y ejemplo.
Página 1 de 1.
Permisos de este foro:
No puedes responder a temas en este foro.