Semana 7 AVR Delay Loop Calculator (rsgc.on.ca) http://darcy.rsgc.on.ca/ACES/TEI4M/AVRdelay.html LDI OUT LDI OUT OUT LDI OUT RCALL IZQ: R18 OUT RCALL WAIT BRCC IZQ DER: ROR R18 OUT RCALL WAIT BRCC DER RJMP IZQ WAIT: LDI R19,41 LDI LDI L1: DEC BRNE L1 DEC BRNE L1 DEC BRNE L1 RET R16, 0XFF DDRD, R16 R17, 0X08 SPL, R16 SPH, R17 R18, 0X01 PORTD, R18 WAIT ROL PORTD, R18 PORTD,R18 R20,150 R21,128 R21 R20 R19 LDI OUT LDI OUT OUT R16, 0X00 DDRB, R16 R17, 0XFF PORTB,R17 DDRD, R17 //Configura puerdo D como entrada //Activa pull-up en los pines del puerto D //Configura el puerto B como salida VAL: IN ANDI SWAP ANDI N_ALTO: CP BRBS BRCC OUT RJMP OUT RJMP IGUAL: LDI OUT RJMP LDI OUT OUT LDI OUT OUT OUT VAL: IN N_ALTO: R18, PINB R18, 0X0F R19 R19,0X0F //Intercambio de nibbles R19, R18 //Compara los valores 1, IGUAL //Salta si son iguales N_ALTO //Salta si el nibble alto es mayor PORTD,R18 //Muestra nibble bajo al no saltar en anteriores VAL PORTD,R19 VAL R20, 0X80 PORTD,R20 VAL R16, 0X00 DDRB, R16 DDRC, R16 R17, 0XFF PORTB,R17 PORTC,R17 DDRD, R17 //Configura puerdo D como entrada //Configura puerdo D como entrada //Activa pull-up en los pines del puerto D //Activa pull-up en los pines del puerto D //Configura el puerto B como salida R18, PINB ANDI R18, 0X0F IN R19, PINC //SWAP R19 //Intercambio de nibbles ANDI R19,0X0F CP BRBS BRCC OUT RJMP OUT RJMP IGUAL: LDI OUT RJMP R19, R18 //Compara los valores 1, IGUAL //Salta si son iguales N_ALTO //Salta si el nibble alto es mayor PORTD,R18 //Muestra nibble bajo al no saltar en anteriores VAL PORTD,R19 VAL R20, 0X80 PORTD,R20 VAL ///////////////////////////////////////////// RJMP START //Salto a inicio .ORG 0X0002 //Escribe en RJMP RSI_0 // .ORG 0X0004 //Escribe en RJMP RSI_1 START: SEI LDI R16,0XFF OUT DDRB, R16 SBI PORTD, 2 SBI PORTD, 3 LDI R17, 0x08 OUT SPL, R16 OUT SPH, R17 LDI R18, 0x03 OUT EIMSK, R18 LDI R19, 0x0F STS EICRA, R19 WAIT: RJMP WAIT RSI_0: LDI OUT RCALL LDI OUT RCALL LDI OUT RCALL LDI OUT RCALL LDI OUT RCALL LDI OUT RCALL LDI OUT RSI_1: LDI R20,0X3F PORTB, R20 Mseg R20, 0X06 PORTB, R20 Mseg R20, 0X5B PORTB, R20 Mseg R20, 0X4F PORTB, R20 Mseg R20, 0X66 PORTB, R20 Mseg R20, 0X6D PORTB, R20 Mseg R20, 0X00 PORTB, R20 R20, 0X6D OUT PORTB, R20 RCALL Mseg LDI R20, 0X66 OUT PORTB, R20 RCALL Mseg LDI R20, 0X4F OUT PORTB, R20 RCALL Mseg LDI R20, 0X5B la localidad 0x0002 la localidad 0x0004 //Habilita las interrupciones globales //Configura puerto "B" como salida //Activa pull-up en los pines de INT0 e INT1 //Activa pull-up en los pines de INT0 e INT1 // //Inicializa puntero de pila //Habilita INT0 e INT1 //Configura flancos de subida //Muestra el valor 0 //Muestra el valor 1 //Muestra el valor 2 //Muestra el valor 3 //Muestra el valor 4 //Muestra el valor 5 // Apaga el display //Muestra el valor 0 //Muestra el valor 1 //Muestra el valor 2 OUT PORTB, R20 RCALL Mseg LDI R20, 0X06 OUT PORTB, R20 RCALL Mseg LDI R20, 0X3F OUT PORTB, R20 RCALL Mseg LDI R20, 0X00 OUT PORTB, R20 RETI Mseg: LDI R21, 3 LDI R22, 138 LDI R23, 84 L1: DEC R23 BRNE L1 DEC R22 BRNE L1 DEC R21 BRNE L1 NOP RET //Muestra el valor 3 //Muestra el valor 4 //Muestra el valor 5 // Apaga el display //////////////////////////// START: SEI LDI OUT SBI SBI LDI OUT OUT LDI OUT LDI STS LDI LDI EOR OUT RCALL LDI EOR OUT RCALL LDI EOR OUT RCALL LDI EOR OUT RCALL LDI EOR OUT RCALL LDI EOR OUT RCALL LDI EOR OUT RCALL LDI EOR OUT RCALL LDI EOR OUT RCALL LDI EOR OUT RCALL LDI EOR OUT Mseg: LDI LDI LDI L1: DEC BRNE DEC BRNE //Habilita las interrupciones globales R16,0XFF DDRD, R16 //Configura puerto "B" como salida PORTB, 2 PORTB, 3 //Activa pull-up en los pines de INT0 e INT1 R17, 0x08 // SPL, R16 SPH, R17 //Inicializa puntero de pila R18, 0x03 EIMSK, R18 //Habilita INT0 e INT1 R19, 0x0F EICRA, R19 //Configura flancos de subida R16,0XFF R20,0X7E R20,R16 PORTD, R20 Mseg R20, 0X30 R20,R16 PORTD, R20 Mseg R20, 0X6D R20,R16 PORTD, R20 Mseg R20, 0X79 R20,R16 PORTD, R20 Mseg R20, 0X33 R20,R16 PORTD, R20 Mseg R20, 0X5B R20,R16 PORTD, R20 Mseg R20, 0X5F R20,R16 PORTD, R20 Mseg R20, 0X70 R20,R16 PORTD, R20 Mseg R20, 0X7F R20,R16 PORTD, R20 Mseg R20, 0X7B R20,R16 PORTD, R20 Mseg R20, 0X00 R20,R16 PORTD, R20 R21, 41 R22, 150 R23, 128 R23 L1 R22 L1 //Muestra el valor 0 //Muestra el valor 1 //Muestra el valor 2 //Muestra el valor 3 //Muestra el valor 4 //Muestra el valor 5 //Muestra el valor 5 //Muestra el valor 5 //Muestra el valor 5 //Muestra el valor 5 // Apaga el display DEC BRNE NOP RET R21 L1 Reemplazar RAMMED por el registro solicitado para definir inicio y final Interrupciones por puerto B ; ; ; ; ; ; ; ; ; interrupciones2: uso de PCINT Realizar un contador de números positivos de dos dígitos que incremente su cuenta al presionar un pulsador P1, y la reduzca al presionar P2. P1 está conectado a PB1 con una resistencia de pull-up, y P2 está conectado a PB2 con una resistencia de pull-down. El resultado debe verse en el puerto D, siendo los 4 bits menos significativos las unidades, y los 4 bits más significativos las decenas. Autor : jtarrillo .def contador = R18 .def OLD_PB = R22 ; Vectores de interrupción .ORG 00 JMP RESET ; Dirección 0: vector de interrupciones del reset .ORG 06 JMP ISR_PB ; Dirección: vector de interrupción de PCINT - PUERTO B ;Inicio del programa principal .ORG 0x36 RESET: ; Configura la pila ldi r16, high(RAMEND) out SPH,r16 LDI r16, LOW(RAMEND) out SPL,r16 ; Configura puerto D como salida LDI R16, 0xFF OUT DDRD, R16 ;------------------------------------------------------------; CONFIGURA IRQ PCINT ;------------------------------------------------------------; Configura interrupciones por puerto B LDI r17, 0b00000001 STS PCICR, r17 ; Extended IO memory ; Configura máscara de pines PB1, PB2 LDI r17, 0b00000110 STS PCMSK0, R17 ; Extended IO memory ;------------------------------------------------------------IN OLD_PB, PINB ; Estado inicial del puerto B CLR Contador ; Inicializa el contador SEI ; Habilitar interrupciones generales ; Lazo infinito Inicio: mov r16, Contador ; Carga cuenta a convertir call bin22bcd ; Adapta el valor de salida out PORTD, R16 ; Envío de valor a LEDs rjmp Inicio ;********************************************************** ; SUBRUTINAS ;********************************************************** ;------------------------------------------------------------; Subrutina de interrupción IRQ PCINT - PUERTO B ;------------------------------------------------------------ISR_PB: push R16 ; Guarda registros in R16, SREG push R16 PUSH R17 IN R16, PINB ; Lectura del estado actual del puerto B IN R17, PINB EOR R16, OLD_PB ; Comparación con valor antiguo SBRS R16, 1 ; Verifica si P1 (PB1) cambió; Salta si P1 cambió RJMP CAMBIO_PB2 ; Cambió P2 (PB2) SBRS R17, 1 ; Cambió P1, evalúa si se presionó RJMP INCREMENTA ; Incrementó RJMP FIN_ISR_PB ; Se soltó P1 CAMBIO_PB2: SBRC R17, 2 ; Cambió P2, evalúa si se presionó RJMP REDUCE ; P2 presionado, se reduce la cuenta RJMP FIN_ISR_PB ; P2 soltado INCREMENTA: CPI Contador, 99 BREQ FIN_ISR_PB ; Compara límite INC Contador RJMP FIN_ISR_PB ; Llegó al límite REDUCE: CPI Contador, 0 BREQ FIN_ISR_PB ; Compara límite DEC Contador ; Llegó al límite FIN_ISR_PB: mov OLD_PB, R17 ; Actualiza valor anterior POP R17 ; Recupera registros pop R16 out SREG, R16 pop R16 reti ;****************************************************************** ; Subrutina que convierte un número binario positivo y menor a 100 ; almacenado en el registro R16, en su representación BCD de 2 ; dígitos: unidades (nibble menor) y decenas (nibble mayor) ; ; Registro de entrada: R16 (positivo menor a 100) ; Registro de salida: R16 (Unidades: nibble menor, Decenas: nibble mayor) ; Registros modificados: R16 ;****************************************************************** bin22bcd: push r17 clr r17; reinicia decenas eval_decenas: cpi r16, 10 brlo mayor_de_diez ;cuenta_decenas subi r16, 10 inc r17 rjmp eval_decenas mayor_de_diez: ;acondiciona salida swap r17 or r16, r17 pop r17 RET INT0 e INT1 ///////////////////////////////////////////// RJMP .ORG RJMP .ORG RJMP START: START //Salto a inicio 0X0002 //Escribe en la localidad 0x0002 RSI_0 // 0X0004 //Escribe en la localidad 0x0004 RSI_1 SEI LDI OUT R16,0XFF DDRB, R16 //Habilita las interrupciones globales //Configura puerto "B" como salida SBI SBI LDI PORTD, 2 PORTD, 3 R17, 0x08 //Activa pull-up en los pines de INT0 e INT1 //Activa pull-up en los pines de INT0 e INT1 // LDI OUT LDI OUT R16,LOW(RAMEND) ;Puntero de pila en el final de SPL,R16 ;la memoria SRAM R16,HIGH(RAMEND) SPH,R16 LDI OUT LDI STS WAIT: RSI_0: RJMP LDI OUT RCALL LDI OUT RCALL LDI OUT RCALL LDI OUT RCALL LDI R18, 0x03 EIMSK, R18 R19, 0x0F EICRA, R19 //Habilita INT0 e INT1 //Configura acceso a la interrupción por flancos de subida WAIT R20,0X3F PORTB, R20 //Muestra el valor 0 R20, 0X06 PORTB, R20 //Muestra el valor 1 R20, 0X5B PORTB, R20 //Muestra el valor 2 R20, 0X4F PORTB, R20 //Muestra el valor 3 Mseg Mseg Mseg Mseg R20, 0X66 RSI_1: OUT RCALL Mseg LDI OUT RCALL Mseg LDI OUT PORTB, R20 //Muestra el valor 4 R20, 0X6D PORTB, R20 //Muestra el valor 5 R20, 0X00 PORTB, R20 // Apaga el display LDI OUT RCALL LDI OUT RCALL LDI OUT RCALL LDI OUT RCALL LDI OUT RCALL LDI OUT RCALL LDI OUT RETI R20, 0X6D PORTB, R20 //Muestra el valor 0 R20, 0X66 PORTB, R20 //Muestra el valor 1 R20, 0X4F PORTB, R20 //Muestra el valor 2 R20, 0X5B PORTB, R20 //Muestra el valor 3 R20, 0X06 PORTB, R20 //Muestra el valor 4 R20, 0X3F PORTB, R20 //Muestra el valor 5 R20, 0X00 PORTB, R20 // Apaga el display Mseg: LDI Mseg Mseg Mseg Mseg Mseg Mseg R21, 3 LDI LDI L1: DEC BRNE DEC BRNE DEC BRNE NOP RET R22, 138 R23, 84 R23 L1 R22 L1 R21 L1 INT0 INT1 ; ; ejercicio interrupciones.asm ; ; Created: 11/05/2022 04:00:49 p. m. ; Author : phazefox ; .CSEG .ORG 0 JMP Inicio JMP INT0_IRQ JMP INT1_IRQ .ORG 0x100 .DEF Cont = R17 .DEF Bin2 = R18 Inicio: CLR LDI OUT LDI OUT R16 R16, SPL, R16, SPH, ;Define pila LOW(RAMEND) R16 HIGH(RAMEND) R16 LDI R16, 0b11111111 OUT DDRD, R16 ;configura puerto D como salida LDI R16, 0b00001100 ;configura los pines PB3 y PB2 como salida ya que están conectados a los LEDs L3 y L2 respectivamente OUT DDRB, R16 LDI R16, 0b00001011 STS EICRA, R16 LDI R16,0b00000011 OUT EIMSK, R16 ;interrupciones en flanco de bajada en INT1 y de subida en INT0 //Carga configuración de acceso a la interrupción ; Cargando valor a registro ; Habilitando periféricos interrupciones por INT1 e INT0 SEI ;Habilita interrupciones globales LDI R20,1 CLR R16 CLR Cont ;Regristro con valor 1 para delay ;R16 = 0 ;Cont = 0 Lazo: RCALL BIN2BCD LDI R16, 0b00001100 AND R16, Bin2 OUT PORTB, R16 LDI R16, 0b11110011 AND R16, Bin2 OUT PORTD, R16 ;extrae los valores de los bits 2 y 3 del contador ;Se escribe los bits 2 y 3 del contador en PB2 y PB3 respectivamente ;extraer los bits 7 a 4, 1 y 0 del contador ;y los excribe en PD7 a 4, PD1 y PD0 RJMP Lazo ;========================================================================== ; SUBRUTINAS ;========================================================================== BIN2BCD: PUSH R16 ;salva R16 en la pila IN R16,SREG ;salva SREG PUSH R16 ;en la pila CLR Bin2 MOV R16, Cont Loop1: CPI R16, 10 BRLO Loop2 SUBI R16,10 INC Bin2 RJMP Loop1 Loop2: SWAP Bin2 ADD Bin2, R16 significativo de R18 POP R16 OUT SREG, R16 POP R16 RET ;Se borra el valor que está en R18 ;Comprueba valor menor a 10 ;Si ya no se tiene más decenas procede a guardar los valores ;Cuenta las decenas ; SALTO INCONDICIONAL ;Mueve el valor de las decenas al nibble más significativo ;Registra el valor de las unidades restante en R16 en el nibble menos ;recupera ;SREG de la pila ;recupera R16 ;INT0_IRQ (PD2) se encarga de incrementar el valor del contador ;Registro modificado: R17(Cont) INT0_IRQ: PUSH R16 IN R16,SREG PUSH R16 CPI Cont, 99 ;salva R16 en la pila ;salva SREG ;en la pila ;Revisa que el contador sea menor a 99 BRLO INC_CUENTA RJMP INT0_END INC_CUENTA: INC Cont INT0_END: POP R16 OUT SREG, R16 POP R16 RETI ;recupera ;SREG de la pila ;recupera R16 ;regresa al punto del programa en el que ocurrió la interrupción ;INT1_IRQ se encarga de decrementar el valor del contador ;Registro modificado: R17(Cont) INT1_IRQ: PUSH R16 IN R16,SREG PUSH R16 ;salva R16 en la pila ;salva SREG ;en la pila CPI Cont, 0x00 BRNE DEC_CUENTA RJMP INT1_END ;Revisa que el contador sea mayor a 0 DEC_CUENTA: DEC Cont INT1_END: POP R16 OUT SREG, R16 POP R16 RETI ;recupera ;SREG de la pila ;recupera R16 ;regresa al punto del programa en el que ocurrió la interrupción ;******************************************** ; Introducción a Sistemas Embebidos ; Ejemplo de llamado de subrutina ;******************************************** .DEF estado_leds = R17 LDI R16,LOW(RAMEND) ; Puntero de pila OUT SPL,R16 ; en el final de LDI R16,HIGH(RAMEND); la memoria SRAM OUT SPH,R16 ; Ejemplo de carga de registros, solo para ; verificar el guardado de datos en la pila LDI R19, 27 LDI R20, 35 LDI R21, 55 CLR estado_leds SER R16 OUT DDRD, R16 ;Puerto D de salida Repite: RCALLCONMUTA ; llamado a subrutina RJMP Repite ; Continua el codigo NOP ; no hace nada NOP ; no hace nada ;...... ;*************************************** ; SUBRUTINA CONMUTA ; Evalúa el estado de leds y los conmuta ; Registros modificados: ; R17 (estado_leds) ;************************************** CONMUTA: ; Guarda registros en la pila PUSH R19 PUSH R20 PUSH R21 CPI estado_leds, 0xFF BREQ apaga SER estado_leds ; estaba apagado RJMP FIN_CONMUTA apaga: CLR estado_leds FIN_CONMUTA: OUT PORTD, estado_leds ; Recupera los registros ordenadamente (LIFO) POP R21 POP R20 POP R19 RET RJMP .ORG RJMP START 0X0020 RSI_T0 START SEI WAIT: RJMP RSI_T0: INC LDI LDI OUT OUT OUT LDI OUT LDI OUT LDI STS LDI OUT WAIT R16, 0XFF R17, 0X08 DDRD, R16 SPH, R17 SPL, R16 R18, 0X00 PORTD, R18 R19, 0X05 TCCR0B, R19 R20, 0X01 TIMSK0, R20 R21, 0X00 TCNT0, R21 R18 OUT RETI PORTD,R18 LDI OUT LDI OUT flanco de bajda LDI STS OUT CONTEO: IN de trabajo OUT RJMP R16,0XFF DDRB,R16 // //Configura puerto B como salida R17,0X06 TCCR0B, R17 //Configura oscialdor externo en flanco de bajada //Carga registro de configuracion como contador de R18, 0X00 TIMSK, R18 TCNT0, R18 R19, TCNT0 //Deshabilita interruciones para el timer 0 //Deshabilita interruciones para el timer 0 //Inicializar la cuenta en el valor 0 //Cargar el registro del timer y guardar en registro PORTB, R19 CONTEO RCALL 3 CICLOS Si usa pila Recuerda de donde salto y regresa con RET //Enviar a la salida del puerto B // RJMP 2 CICLOS No usa pila LDI OUT LDI OUT flanco de bajda LDI STS OUT CONTEO: IN de trabajo OUT RJMP R16,0XFF DDRB,R16 // //Configura puerto B como salida R17,0X06 TCCR0B, R17 //Configura oscialdor externo en flanco de bajada //Carga registro de configuracion como contador de R18, 0X00 TIMSK, R18 TCNT0, R18 R19, TCNT0 //Deshabilita interruciones para el timer 0 //Deshabilita interruciones para el timer 0 //Inicializar la cuenta en el valor 0 //Cargar el registro del timer y guardar en registro PORTB, R19 CONTEO //Enviar a la salida del puerto B // UART /* * UART.c * * Created: 24/02/2019 17:23:54 * Author : marlon */ #define F_CPU 16000000 // Definicion de frecuencia del cpu del atmega #include <avr/io.h> //Registros utilizados #include <util/delay.h> //Funciones de retardo #include <avr/interrupt.h> //Acceso a interrupciones #define numeroBits 13 char myBuffer = ' '; int main(void) { //char datos[numeroBits] = " "; cli(); //Iniciar apagando todas las interrupciones /* Configuración del USART como UART */ // USART configurado modo de operación como UART UCSR0C &=~ (1<<UMSEL00); UCSR0C &=~ (1<<UMSEL01); // Configuracion de Paridad desactivada // Configuracion 10 PAR // Configuracion 11 IMPAR UCSR0C &=~ (1<<UPM00); UCSR0C &=~ (1<<UPM01); // usart stop bit settings (0=1bit)(1=2bit) Stops = 1 UCSR0C &=~ (1<<USBS0); // Datos de 8 bits =011 UCSR0C |= (1<<UCSZ00); UCSR0C |= (1<<UCSZ01); UCSR0B &=~ (1<<UCSZ02); //9bit=111//7bit=010//6bit=001//5bit=000 //1 //1 //0 // Calculo del baudrate 9600 UCSR0A |= (1<<U2X0); //Modo de operación de comunicación double speed UBRR0 = (F_CPU/8/9600) - 1; // UCSR0B |= (1<<TXEN0); // Configuración de bit de transmisión UCSR0B |= (1<<RXEN0); // Configuración de bit de recepción UCSR0B |= (1<<RXCIE0); //Activar interrupción lectura sei();//Activar interrupciones while (1) { //while(!(UCSR0A & (1<<RXC0))); //myBuffer = UDR0; //Registro que almacena dato recibido // //while(!(UCSR0A & (1<<UDRE0))); //UDR0 = myBuffer; //Registro que almacena dato transmitido } } ISR(USART_RX_vect) { myBuffer = UDR0; // Lectura y almacenamiento del dato recibido while(!(UCSR0A & (1<<UDRE0))); UDR0 = myBuffer; } ADC /* * ADC.c * * Created: 26/03/2019 06:41:53 p.m. * Author : Marlon */ #include <avr/io.h> #include <avr/interrupt.h> #include "ADC/ADC.h" int main(void) { cli(); //Iniciar apagando todas las interrupciones DDRB |= (1<<DDB5); //Configuracion de salida para LED ADC_init();//Iniciar ADC sei(); while (1) { float adcV = ADC_GetData(0)*5.0f/1024.0f; if (adcV > 3.0f) { PORTB |= (1<<PORTB5); } else { PORTB &=~ (1<<PORTB5); } //Enciende LED //Apaga LED } } /* * ADC.c * * Created: 26/03/2019 06:43:35 p.m. * Author: Marlon */ #include "ADC.h" void ADC_init() { //Inicializar el ADC //Salida configurada a la derecha ADMUX &=~ (1<<ADLAR); // Voltage Reference = AVCC //Voltaje de referencia 5VDC ADMUX |= (1<<REFS0); ADMUX &=~ (1<<REFS1); // Frequency divisor = 128 -> 16000/128 = 125 KHz ADCSRA |= (1<<ADPS0); ADCSRA |= (1<<ADPS1); ADCSRA |= (1<<ADPS2); //Divisor de frencuencia } int ADC_GetData(int canal) { // Selección del canal de lADC // ADMUX &=~ 0x0F; //Enmascaramiento para guardar configuracion ADMUX |= canal; //Iniciamos ADC ADCSRA |= (1<<ADEN); _delay_us(10); // Tiempo para tomar lectura después de iniciar sistema //Lectura ADC ADCSRA |= (1<<ADSC); //Confirmamos lectura de la muestra con un flag while( !(ADCSRA & (1<<ADIF)) ); //Reinicio flag ADCSRA |= (1<<ADIF); // Reiniciamos el flag // Apagamos el ADC ADCSRA &=~ (1<<ADEN); return ADC; }