sábado, 2 de junio de 2018

CRONOMETRO AVR ATMEGA

Este es el programa de un cronómetro, con reinicio y pausa, implementado en un Atmega164p, los el tiempo se muestra en un display de 8 segmentos x4.
Circuito


/*
 * cronometro.c
 *
 * Created: 10/03/2016 8:43:06
 *  Author: Toshiba Satellite
 */ 


#include 
#define F_CPU 1000000UL
#include 
#include 

unsigned char u,d,c,m;
int contador,segundo;   //por q va hasta 9999
unsigned char display[10]={0b00111111,0b00000110,0b01011011,0b01001111,0b01100110,0b01101101,0b01111101,0b000000111,0b01111111,0b01101111};

void configurar(void);

int main(void)
{
 configurar();
 while(1)
 {
  u=segundo%10;
  m=segundo/1000;
  c=(segundo-m*1000)/100;
  d=(segundo-m*1000-c*100)/10;
  
  PORTA=display[u];
  PORTC=0b11111110;
  _delay_ms(5);
  PORTC=255;   //apagar
  PORTA=display[d];
  PORTC=0b11111101;
  _delay_ms(5);
  PORTC=255;
  PORTA=display[c];
  PORTC=0b11111011;
  _delay_ms(5);
  PORTC=255;
  PORTA=display[m];
  PORTC=0b11110111;
  _delay_ms(5);
  PORTC=255;
  
 }
}

void configurar(void)
{
 //configuracion de puertos
 DDRA=255;//salida
 DDRC=255;
 
 //configuracion de timer
 TCCR0A=0b00000010;
 OCR0A=38;
 TCCR0B=0b00000000;
 TIMSK0=0b00000010;
 TIFR0=TIMSK0;     //bajando banderas
 
 //configuracionde interrupciones externas
 EICRA=0b00101010;
 EIMSK=0b00000111;
 
 EIFR=0b00000111;//solo para simulacion
 
 sei();
}

//interrupcion por comparacion del timer 0
ISR(TIMER0_COMPA_vect)
{
 contador++;
 if (contador>100)
 {
  segundo++;
  contador=0;
 }
 
}

//INTERRUPCIONES EXTERNAS
//pausa
ISR(INT0_vect)
{
 TCCR0B=0b00000000;
}

//arrancar
ISR(INT1_vect)
{
 TCCR0B=0b00000100;
}

//reinicio
ISR(INT2_vect)
{
 segundo=0;
}


//

Medir velocidad con encoder, atmega AVR

En este programa se mide la velocidad con un encoder el primer microcontrolador simula los pulsos del encoder een el segundo se implementa el medidor de velocidad, deben tener la libreria del LCD Esta programado en el Atmega164p en lenguaje c

/*
 * medir_velocidad_con_encoder.c
 *
 * Created: 17/03/2016 12:31:58
 *  Author: Toshiba Satellite
 */ 


#include 
#define F_CPU 8000000UL
#include 
#include 
#include "lcd.h"
#include 

uint8_t EEMEM   dir_distancia;

int pulsosv,velocidad;
int danterior;
unsigned int pulsosd;
unsigned int distancia;
unsigned int msm[16];

void configurar(void);

int main(void)
{
 configurar();
    while(1)
    {
        //TODO:: Please write your application code 
  //calculo de la disttancia
  distancia=(pulsosd*0.0261666*0.001)+danterior;
  
  lcd_gotorc(1,1);
  sprintf(msm,"%d   ",distancia);
  lcd_puts(msm);
  lcd_gotorc(1,7);
  lcd_puts("Km");
  
  lcd_gotorc(2,1);
  sprintf(msm,"%d   ",velocidad);
  lcd_puts(msm);
  lcd_gotorc(2,5);
  lcd_puts("Km/h");
    }
}

void configurar(void)
{
 DDRD=0b00000000;   //entrada para int0 sin pull up porq viene de un sensor
 DDRA=255;
 PORTD=0b00001000;
 
 //configuracion de la interruptions
 EICRA=0b00001011;
 EIMSK=0b00000011;
 EIFR=0b00000011;
 
 //inicializar lcd
 lcd_init();
 
 //
 
 //configurar eeprom
 danterior=eeprom_read_byte(&dir_distancia);
 
 //configuracion del timer
 TCCR1A=0;
 OCR1A=31249;
 TCCR1B=0b00001100;
 TIMSK1=2;
 TIFR1=2;
 
 sei();
 
}

ISR(INT0_vect)

{
 pulsosd++;
 pulsosv++;
}

ISR(TIMER1_COMPA_vect)
{
 
 
 if (pulsosv>36)
 {
  velocidad=pulsosv*0.08333*6.28*0.05*3.6;
  pulsosv=0;
 }
 
}

ISR(INT1_vect)
{
 eeprom_write_byte(&dir_distancia,distancia);
 sbi(PORTB,0);
}

//
Aqui esta el programa que genera los pulsos del encoder
/*
 * variador_de_frecuencia.c
 *
 * Created: 18/03/2016 11:47:32
 *  Author: Toshiba Satellite
 */ 


#include 
#define F_CPU 8000000UL
#include 
#include 

void configurar(void);

int main(void)
{
 configurar();
    while(1)
    {
        //TODO:: Please write your application code 
  
  ADCSRA=0b11000110;
  _delay_ms(2);
  OCR0A=ADCH;
    }
}

void configurar(void)
{
 DDRB=0b00001000;  //salida de OC0A
 
 //configuracion del timer
 TCCR0A=0b01000010;
 TCCR0B=0b00000100;
 
 
 //configuracion del ADC
 ADMUX=0b01100000;
 DIDR0=0b00000000;
 
}
//

MANEJO DE LCD ASSEMBLER

Para los que están aprendiendo lenguaje ensamblador y quieren manejar un LCD 16x2 les traigo el siguiente código espero que les ayude para sus trabajos o proyectos.
Está implementado en el microcontrolador Atmega164P.



/*
/*
 * LCD.asm
 *
 *  Created: 30/05/2016 10:34:05
 *   Author: CRIS
 */ 

.INCLUDE "m164pdef.inc"

; ASIGNACIÓN DE ETIQUETAS A REGISTROS
.DEF AUX1 = R16 ; REGISTRO AUX1
.DEF AUX2 = R17 ; REGISTRO AUX2
.DEF AUX3 = R18 ; REGISTRO AUX3

.DSEG
BUFFER: .BYTE 10
COLUM: .BYTE 4
; SEGMENTO DE PROGRAMA o MEMORIA FLASH
.CSEG
; ASIGNACIÓN DE ETIQUETAS PARA EL MANEJO DEL DISPLAY
.EQU BUSSAL = PORTC ; BUS PARA ESCRITURA
.EQU BUSINP = PINC ; BUS PARA LECTURA
.EQU CONTROL = PORTD ; LÍNEAS DE CONTROL
.EQU ENABLE = PD7 ; HABILITACIÓN
.EQU RW = PD6 ; LEER=1 ESCRIBIR=0
.EQU RS = PD5 ; DATOS=1 COMANDO=0


; INICIALIZACIÓN DEL STACK
LDI AUX1,LOW(RAMEND)
OUT SPL,AUX1
LDI AUX1,HIGH(RAMEND)
OUT SPH,AUX1
RCALL LCDRST

ESCRIBIR:
LDI ZL,LOW(TEXT1<< 1)
LDI ZH,HIGH(TEXT1<< 1)
RCALL WRTMSJ
RJMP ESCRIBIR

; SUBRUTINA DE INICIALIZACIÓN DEL LCD CON BUS DE 8 BITS

LCDRST: 

LDI AUX1,0xFF ; BUS DEL LCD COMO SALIDA
OUT DDRC,AUX1
LDI AUX1,0xE0 ; LINEAS DE CONTROL DEL LCD
OUT DDRD,AUX1

LDI ZL,LOW(TBLLCD<< 1)
LDI ZH,HIGH(TBLLCD<< 1)
LDI AUX2,5

LCDRST1:
LPM AUX1,Z+
RCALL WRTCMD
DEC AUX2
BRNE LCDRST1
RET
TBLLCD: 
.DB 0x33,0x32,0x38,0x06,0x0E,0x00

; SUBRUTINA PARA ESCRIBIR UN MENSAJE EN EL LCD
WRTMSJ: LDI AUX1,0x80
RCALL WRTCMD
RCALL WRTLIN
LDI AUX1,0xC0
RCALL WRTCMD
RCALL WRTLIN
LDI AUX1,0x94
RCALL WRTCMD
RCALL WRTLIN
LDI AUX1,0xD4
RCALL WRTCMD
RCALL WRTLIN
RET

; SUBRUTINA PARA ESCRIBIR UNA LINEA DE 20 CARACTERES
WRTLIN: LDI AUX2,20
WRTLIN1:LPM AUX1,Z+
RCALL WRTDAT
DEC AUX2
BRNE WRTLIN1
RET
; SUBRUTINA PARA ESCRIBIR UN NÚMERO DESDE EL BUFFER
WRTNUM: RCALL POSCUR
LDI XL,LOW(BUFFER)
LDI XH,HIGH(BUFFER)
CLR AUX3
WRTNUM1:LD AUX1,X+
CPI AUX1,0
BRNE WRTNUM2
CPI AUX3,0
BREQ WRTNUM3
WRTNUM2:INC AUX3
RCALL WRTDIG
WRTNUM3:CPI XL,LOW(BUFFER)+10
BRNE WRTNUM1
CPI AUX3,0
BRNE WRTNUM4
RCALL WRTDIG
WRTNUM4:RET

; SUBRUTINA PARA ESCRIBIR UN CARACTER
WRTCHR: RJMP WRTDAT
; SUBRUTINA PARA ESCRIBIR UN BYTE
WRTBYT: PUSH AUX1
SWAP AUX1
RCALL WRTDIG
POP AUX1
RCALL WRTDIG
RET
; SUBRUTINA PARA ESCRIBIR UN DIGITO
WRTDIG: ANDI AUX1,0x0F
ORI AUX1,0x30
CPI AUX1,0x3A
BRCS WRTDAT
LDI AUX2,7
ADD AUX1,AUX2

RJMP WRTDAT
; SUBRUTINA PARA MOSTRAR EL CURSOR
ONCUR: LDI AUX1,0x0E
RJMP WRTCMD
; SUBRUTINA PARA APAGAR EL CURSOR
OFFCUR: LDI AUX1,0x0C
RJMP WRTCMD
; SUBRUTINA PARA QUE PARPADEE EL CARACTER Y MOSTRAR EL CURSOR
TITCHR: LDI AUX1,0x0F
RJMP WRTCMD
; SUBRUTINA PARA QUE PARPADEE EL CARACTER
TITCUR: LDI AUX1,0x0D
RJMP WRTCMD
; SUBRUTINA PARA MOVER EL CURSOR EN 80 CARACTERES
POSCUR: CPI AUX1,20
BRCS POSCUR4
SUBI AUX1,20
CPI AUX1,20
BRCS POSCUR3
SUBI AUX1,20
CPI AUX1,20
BRCS POSCUR2
SUBI AUX1,20
CPI AUX1,20
BRCS POSCUR1
RET
POSCUR1:LDI AUX2,0xD4
RJMP POSCUR5
POSCUR2:LDI AUX2,0x94
RJMP POSCUR5
POSCUR3:LDI AUX2,0xC0
RJMP POSCUR5
POSCUR4:LDI AUX2,0x80
POSCUR5:ADD AUX1,AUX2
RJMP WRTCMD
; SUBRUTINA PARA ESCRIBIR UN COMANDO
WRTCMD: CBI CONTROL,RS
RJMP WRTDAT1
; SUBRUTINA PARA ESCRIBIR UN DATO
WRTDAT: SBI CONTROL,RS
WRTDAT1:CBI CONTROL,RW
OUT BUSSAL,AUX1
SBI CONTROL,ENABLE
CBI CONTROL,ENABLE
RCALL BUSY
RET
; SUBRUTINA QUE ESPERA MIENTRAS EL LCD ESTÁ OCUPADO
BUSY: LDI AUX1,0x00
OUT DDRC,AUX1
CBI CONTROL,RS
SBI CONTROL,RW
BUSY1: SBI CONTROL,ENABLE
NOP
IN AUX1,BUSINP

CBI CONTROL,ENABLE
SBRC AUX1,7
RJMP BUSY1
LDI AUX1,0xFF
OUT DDRC,AUX1
RET

TEXT1: 
.DB "Hola "
.DB "              Cristian "
.DB "Ponce "
.DB "         "