#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
#include <util/delay_basic.h>
#define Bus_Datos PORTK
#define Bus_Control PORTF
#define RS PORTF5
#define RW PORTF6
#define E PORTF7
//Inicializar
void inicializar();
void inicializar_timer4(void);
void inicializar_timer0(void);
void inicializar_adc(void);
//Comandos para situar el cursor en inicio de líneas.
#define DDRA_LINEA1 0x80 //1000 0000
#define DDRA_LINEA2 0xC0 //1100 0000
#define DDRA_LINEA3 0x94 //1001 0100
#define DDRA_LINEA4 0xD4 //1101 0100
//Funciones para escribir en el LCD
void lcd_inicializar();
void lcd_escribir_c(char caracter);
void lcd_escribir(char *cadena);
void posicionar_cursor(unsigned char x, unsigned char y);
void lcd_comando(unsigned char comando);
void escribir_valor_decimal(unsigned int registro);
void escribir_espacio(unsigned long int registro);
void escribir_direccion(unsigned char valorl, unsigned char valorh);
/***************** VARIABLES ***********************/
volatile unsigned int cuenta;
volatile unsigned int cuenta_old;
volatile unsigned char contador;
volatile unsigned int suma_cuenta;
volatile unsigned long int espacio;
volatile unsigned char direccionl;
volatile unsigned char direccionh;
volatile unsigned char contador2;
int main(void)
{
inicializar();
lcd_inicializar();
inicializar_timer4();
inicializar_timer0();
inicializar_adc();
ADCSRA|= (1<<ADSC); //Comenzar conversiones.
char linea1[]="www.jmnlab.com"; //Poner en la Flash de programa las cadenas.
char linea2[]="Contar los pulsos";
char linea3[]="de un encoder";
char linea4[]="Pulsos/seg:";
char linea5[]="Velocidad:";
char linea6[]="Espacio:";
char linea7[]="V. Direccion:";
posicionar_cursor(1,4);
lcd_escribir(linea1);
posicionar_cursor(3,3);
lcd_escribir(linea2);
posicionar_cursor(4,4);
lcd_escribir(linea3);
_delay_ms(3000);
lcd_comando(0x01);
posicionar_cursor(1,1);
lcd_escribir(linea7);
posicionar_cursor(2,1);
lcd_escribir(linea4);
posicionar_cursor(3,1);
lcd_escribir(linea5);
posicionar_cursor(4,1);
lcd_escribir(linea6);
posicionar_cursor(3,17);
lcd_escribir_c('m');
lcd_escribir_c('m');
lcd_escribir_c('/');
lcd_escribir_c('s');
posicionar_cursor(4,17);
lcd_escribir_c('m');
unsigned int suma_cuenta_local=0;
unsigned int velocidad=0;
unsigned char direccion_locall=0;
unsigned char direccion_localh=0;
while(1)
{
if(contador>62)
{
suma_cuenta_local=suma_cuenta;
contador=0;
suma_cuenta=0;
posicionar_cursor(2,13);
escribir_valor_decimal(suma_cuenta_local);
velocidad= suma_cuenta_local*12;
posicionar_cursor(3,12);
escribir_valor_decimal(velocidad);
espacio= espacio + (unsigned long int)suma_cuenta_local*12036;
posicionar_cursor(4,10);
escribir_espacio(espacio);
}
if(contador2>10)
{
direccion_locall=direccionl;
direccion_localh=direccionh;
posicionar_cursor(1,15);
escribir_direccion(direccion_locall, direccion_localh);
contador2=0;
}
}
}
void
inicializar()
//Configurar hardware del micro.
{
DDRK=0xFF; //1111 1111
PORTK=0x00;
DDRF|=((1<<RS)|(1<<RW)|(1<<E)); //1110 0000
PORTF &= ~(1<<E);
}
void inicializar_adc(void)
{
ADMUX
|=(1<<REFS0);
//Tensión de referencia 5 voltios.
ADMUX
|=(1<<ADLAR);
//8 bits de
resolución.
//Canal ADC por defecto ADC0, no tenemos que cambiarlo.
ADCSRA |=(1<<ADATE);
//Habilitamos el
Free Running Mode, por defecto seleccionado
ADCSRA |=((1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0)); //Prescaler 128, Fadc 125 KHz @ 16MHz.
DIDR0 |=
((1<<ADC0D)|(1<<ADC1D));
//Apagamos la parte digital del puerto.
}
/*************************************************************************/
void lcd_inicializar() //Se mandan los comandos de configuración según el dibujo.
{
_delay_ms(100);
lcd_comando(0x3C); //Function Set RS0 RW0 0011NF** 0011 1100
lcd_comando(0x3C); //Function Set
lcd_comando(0x0C); //Display ON/OFF Control RS0 RW0 00001DCB 0000 1100
lcd_comando(0x01); //Display Clear RS0 RW0 00000001
lcd_comando(0x06); //Entry Mode Set RS0 RW0 000001I/DS 0000 0110
}
void lcd_escribir_c(char caracter)
{
Bus_Control |= (1<<RS); //RS1 Dato
Bus_Control &= ~(1<<RW); //RS0
Bus_Datos = caracter;
Bus_Control |= (1<<E);
_delay_us(100);
Bus_Control &= ~(1<<E);
_delay_ms(10);
}
void lcd_comando(unsigned char comando)
{
Bus_Control &= ~(1<<RS); //RS0 Comando
Bus_Control &= ~(1<<RW); //RW0
Bus_Datos = comando; //Comando
Bus_Control |= (1<<E);
_delay_us(100);
Bus_Control &= ~(1<<E);
_delay_ms(10);
}
void lcd_escribir(char *cadena)
{
char *inicio = cadena;
unsigned char i=0;
for(i=0;((inicio[i]!='\0')&&(i<20));i++)
{
Bus_Control |= (1<<RS); //RS0 RW0 caracter
Bus_Control &= ~(1<<RW);
Bus_Datos = inicio[i];
Bus_Control |= (1<<E);
_delay_us(100);
Bus_Control &= ~(1<<E);
_delay_ms(3);
}
}
void posicionar_cursor(unsigned char x, unsigned char y) //línea x 1 a 4, carácter y de 1 a 20.
{
unsigned char comando=DDRA_LINEA1;
switch(x)
{
case 1:
{
comando=DDRA_LINEA1+y-1;
}break;
case 2:
{
comando=DDRA_LINEA2+y-1;
}break;
case 3:
{
comando=DDRA_LINEA3+y-1;
}break;
case 4:
{
comando=DDRA_LINEA4+y-1;
}break;
default:break;
}
lcd_comando(comando);
}
/****************************************************************************************************/
void inicializar_timer4(void) //Configura el timer y la interrupción.
{
DDRA |= (1<<PA7); //Puerto A7 pin osciloscopio
// OCR4A= 0x0F9F; //16 ms
OCR4A= 0x0534; //5.33 ms
TCCR4B
|=((1<<WGM42)|(1<<CS41)|(1<<CS40));
//Los bits que no se tocan a 0 por defecto
TIMSK4 |= (1<<OCIE4A);
sei();
}
void inicializar_timer0(void)
{
TCCR0B
|=((1<<CS02)|(1<<CS01)|(1<<CS00));
//Normal Mode y reloj externo flanco de subida
}
/***************************************************************************************************/
ISR(TIMER4_COMPA_vect)
{
unsigned int cuenta_actual=TCNT0;
static char cont_int = 0;
static unsigned char seleccion = 0;
static unsigned int velocidad = 2000;
static unsigned int posicion = 2000;
unsigned int copia_ADCH=0;
cont_int++;
switch(cont_int)
{
case 1:
{
//Se lee el potenciometro y se asigna a posición o velocidad.
ADMUX &=
~(1<<MUX0);
//Canal 0.
ADMUX |=
(1<<ADLAR);
//8 bits.
ADCSRA |=
(1<<ADEN);
//Encendemos ADC
ADCSRA |= (1<<ADSC);
_delay_us(350);
//Captura y
conversión de la señal.
copia_ADCH=ADCH;
ADCSRA &=
~(1<<ADEN);
//Apagamos ADC
//Asignar velocidad y dirección.
if((PIND & (1<<PIND2))==0)
seleccion=0;
else if((PIND & (1<<PIND3))==0)
seleccion=1;
if(seleccion==0)
posicion=copia_ADCH*16;
else
velocidad=copia_ADCH*16;
//Señal de control MiniZ
PORTA |=(1<<PORTA7);
_delay_us(400);
PORTA &= ~(1<<PORTA7);
_delay_loop_2(2400+posicion);
PORTA |=(1<<PORTA7);
_delay_us(400);
PORTA &= ~(1<<PORTA7);
_delay_loop_2(2400+velocidad);
PORTA |=(1<<PORTA7);
_delay_us(400);
PORTA &= ~(1<<PORTA7);
}break;
case 2:
{
//Código del micro (leer enconders)
if (cuenta_actual>cuenta_old)
{
cuenta=cuenta_actual-cuenta_old;
suma_cuenta=suma_cuenta+cuenta;
}
else if(cuenta_actual<cuenta_old)
{
cuenta=256+cuenta_actual-cuenta_old;
suma_cuenta=suma_cuenta+cuenta;
}
cuenta_old=TCNT0;
contador++;
}break;
case 3:
{
//Código micro (se lee la realimentación)
cont_int=0;
ADMUX |=
(1<<MUX0);
//Seleccionamos ADC1 y 5V
ADMUX
&= ~(1<<ADLAR);
//10 bits
ADCSRA |=
(1<<ADEN);
//Encendemos ADC
ADCSRA |= (1<<ADSC);
_delay_us(350);
direccionl = ADCL;
direccionh = ADCH;
ADCSRA &=
~(1<<ADEN);
//Apagamos ADC
contador2++;
}break;
default:break;
}
TIFR4 |= (1<<OCF4A);
}
/************************* Escribir registros *****************************************************/
void escribir_valor_decimal(unsigned int registro) //Escribir binario a decimal.
{
char miles=0;
char centenas = 0;
char decenas = 0;
char unidades = 0;
while(registro>=1000)
{
registro= registro -1000;
miles++;
}
while(registro>=100)
{
registro= registro -100;
centenas++;
}
while(registro>=10)
{
registro=registro -10;
decenas++;
}
while(registro>0)
{
registro=registro-1;
unidades++;
}
lcd_escribir_c(miles | 0b00110000);
lcd_escribir_c(centenas | 0b00110000);
lcd_escribir_c(decenas | 0b00110000);
lcd_escribir_c(unidades | 0b00110000);
}
void escribir_espacio(unsigned long int registro)
{
char miles=0;
char centenas = 0;
char decenas = 0;
char unidades = 0;
char decena_cm=0;
while(registro>=1000000000)
{
registro= registro -1000000000;
miles++;
}
while(registro>=100000000)
{
registro= registro -100000000;
centenas++;
}
while(registro>=10000000)
{
registro= registro -10000000;
decenas++;
}
while(registro>=1000000)
{
registro= registro -1000000;
unidades++;
}
while(registro>=100000)
{
registro= registro -100000;
decena_cm++;
}
lcd_escribir_c(miles | 0b00110000);
lcd_escribir_c(centenas | 0b00110000);
lcd_escribir_c(decenas | 0b00110000);
lcd_escribir_c(unidades | 0b00110000);
lcd_escribir_c('.');
lcd_escribir_c(decena_cm | 0b00110000);
}
void escribir_direccion(unsigned char valorl, unsigned char valorh)
{
unsigned int registro=0;
registro= (int)valorh*256+valorl;
char miles=0;
char centenas = 0;
char decenas = 0;
char unidades = 0;
while(registro>=1000)
{
registro= registro -1000;
miles++;
}
while(registro>=100)
{
registro= registro -100;
centenas++;
}
while(registro>=10)
{
registro= registro -10;
decenas++;
}
while(registro>=1)
{
registro= registro -1;
unidades++;
}
lcd_escribir_c(miles | 0b00110000);
lcd_escribir_c(centenas | 0b00110000);
lcd_escribir_c(decenas | 0b00110000);
lcd_escribir_c(unidades | 0b00110000);
}