#define __AVR_ATmega2560__
#define F_CPU 16000000UL
#include <stdint.h>
#include <avr/io.h>
#include <stdbool.h>
#include <util/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include "usart.h"
/*Use o circuito anterior, com o dip switch conectado às portas
PB2 a PB0. O temporizador/contador TC0 gera interrupções a cada 1,8 ms. Usando
as interrupções, faça o LED em PB7 piscar na frequência de 0,8 Hz. A cada 1,2 s os
terminais PB[2:0] são lidos e transmitidos pela interface serial USART0 no formato
binário e decimal.*/
#define led_pin PB7
#define botao1 PB2
#define botao2 PB1
#define botao3 PB0
void configuracao_TC0(void) {
// Configura o timer0 para gerar interrupções a cada 1,8 ms
/*
CS02:CS01:CS00 Prescaler Frequência do timer (para F_CPU = 16 MHz)
000 Sem clock Contador parado
001 1 16 MHz
010 8 2 MHz
011 64 250 kHz
100 256 62,5 kHz
101 1024 15,625 kHz
110 e 111 Reservado Não deve ser usado
*/
/* Queremos 1,8ms, logo, 16MHz/64 = 250kHz = 4us; necessários 1,8ms/4us = 450 (não tem)
Logo, testaremos com N = 256 -> 16MHz/256 = 62.5kHz = 16us, necessários 1,8ms/16us = 112,5 = 112 (tem) */
TCCR0A = 0x02; // Modo CTC
TCCR0B = 0x04; // CS0[2:0]=100 N=256
TIMSK0 = 0x02; // Ativa OCIE0A (interrupção de comparação A)
OCR0A = 112; // TOP (valor de comparação)
TCNT0 = 0x00; // Zera o contador
sei(); // Ativa as interrupções globais
}
volatile int tick_led, tick_usart, b1, b2, b3;
int main(void) {
USART0_configura();
configuracao_TC0();
// Configura o pino do LED como saída e inicializa desligado
DDRB |= (1 << led_pin); // Configura PB7 como saída
PORTB &= ~(1 << led_pin); // Inicialmente, LED apagado
// Configura os botões como entrada com pull-up ativado
DDRB &= ~(1 << botao1); // Configura PB2 como entrada
DDRB &= ~(1 << botao2); // Configura PB1 como entrada
DDRB &= ~(1 << botao3); // Configura PB0 como entrada
// Adicionamos pull-up a essas portas
PORTB = PORTB | (1 << PORTB0);
PORTB = PORTB | (1 << PORTB1);
PORTB = PORTB | (1 << PORTB2);
while (1) {
// Loop principal vazio por enquanto
// A lógica de controle é feita nas interrupções
// O microcontrolador irá alternar o LED e ler os botões a cada interrupção
// Não há necessidade de código adicional aqui, a lógica é totalmente controlada pelas interrupções
}
}
// Interrupção do temporizador (TC0) chamada a cada 1,8 ms
ISR(TIMER0_COMPA_vect) {
tick_led++;
tick_usart++;
// A cada 694 interrupções (1,25s), o LED será alternado
if (tick_led == 694) { // 0,8Hz = 1,25s. Logo, 1,25/1,8ms = 694.44 = 694
led();
tick_led = 0;
}
// A cada 667 interrupções (1,2s), os botões serão lidos e transmitidos via USART
if (tick_usart == 667) { // 1,2s Logo, 1,2/1,8ms = 666,7
leitura_e_print();
tick_usart = 0;
}
}
// Função para alternar o estado do LED (piscar)
void led() {
PORTB ^= (1 << led_pin); // Inverte o estado do LED (acende/apaga)
}
// Função para ler os botões e enviar os valores via USART
void leitura_e_print() {
// Leitura dos botões (0 significa que o botão está pressionado)
uint8_t decimal;
b1 = !(PINB & (1 << botao1));
b2 = !(PINB & (1 << botao2));
b3 = !(PINB & (1 << botao3)); // faz a leitura dos botao;
decimal = (b1|b2<<1|b3<<2); // manda b1 pro bit 0, b2 pro bit 1 e b3 pro bit 2. Montando assim um decimal de 3 bits
USART0_transmite(b3 + '0'); // + '0' serve pra não paracer ? na usart
USART0_transmite(b2 + '0'); // vai mandando todos os bit, pra aparecer os 3
USART0_transmite(b1 + '0');
USART0_transmite(' ');// Adiciona espaço
USART0_transmite(decimal + '0'); //manda o decimal que é um uint_8 que tem o decimal em binario.
USART0_transmite_string_RAM("\r\n");// Adiciona uma nova linha
}