/*
1
Umdipswitchcom8chavestemasentradas1,2e3conectadas
as portas PB2 (terminal 51) e PB1 (terminal 52) e PB0 (terminal 53) da placa de
desenvolvimento ATmega 2560, respectivamente. Considere as chaves ideais. Um
LED L emPB7(terminal 13) deve acender se PB2 e PB1 estiverem ligadas e apagar
se PB1 e PB0 estiverem ligadas. O LED não deve mudar de estado para outras
combinações das chaves
2
Use o circuito anterior, com o dip switch conectado as portas
PB2 aPB0. Otemporizador/contador TC0 gera interrupções a cada 1,8ms. Usando
as interrupções, faça o LED em PB7 piscar na frequência de 0,8Hz. A cada 1,2s os
terminais PB[2:0] são lidos e transmitidos pela interface serial USART0 no formato
binário e decimal.
3
Use o circuito anterior. Usamos o conversor ADC para fazer
a leitura da tensão analógica no canal ADC1 (porta PF1), em intervalos de 1s.
QuandoatensãolidaformaiorqueovaloremPB[2:0],transmitimospelaUSART0a
mensagem“Tensãoacimadopermitido”2. Deve ser enviada uma única mensagem,
cada vez que a tensão lida for maior que PB[2:0]. Se a tensão não retornar a um
valor menorquePB[2:0],depoisde5s,oLEDemPB7acende. Eleéapagadoquando
a tensão é menor ou igual a PB[2:0]. Use AVCC como tensão de referência. Escreva
o programa em C.
*/
#define __AVR_ATmega2560__
#define F_CPU 16000000UL
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "usart.h"
// Função para configurar os pinos de entrada e saída
void configura_pinos()
{
// Configura PB2, PB1 e PB0 como entradas com resistores pull-up
DDRB &= ~(1 << DDB2);
PORTB |= (1 << PORTB2);
DDRB &= ~(1 << DDB1);
PORTB |= (1 << PORTB1);
DDRB &= ~(1 << DDB0);
PORTB |= (1 << PORTB0);
// Configura PB7 como saída para controle do LED
DDRB |= (1 << DDB7);
PORTB &= ~(1 << PORTB7);
// Configura PF1 como entrada tri-state para o ADC
DDRF &= ~(1 << DDF1);
PORTF &= ~(1 << PORTF1);
}
// Função para inicializar o conversor ADC
void inicializa_ADC()
{
// Configura o ADC com divisor de clock de 128 para obter 125KHz
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
ADCSRB = 0;
}
// Função para realizar uma leitura ADC em um canal específico
uint16_t leitura_ADC(uint8_t canal)
{
// Configura a referência de tensão como AVCC e seleciona o canal do ADC
ADMUX = (1 << REFS0) | canal;
// Inicia a conversão ADC
ADCSRA |= (1 << ADSC);
// Espera até que a conversão esteja completa
while (ADCSRA & (1 << ADSC))
{
continue;
}
// Retorna o valor da conversão ADC
return ADC;
}
int main()
{
// Configura os pinos, USART e ADC
configura_pinos();
USART0_configura();
inicializa_ADC();
uint8_t contador_5s = 0; // Contador para o intervalo de 5 segundos
uint8_t mensagem_enviada = 0; // Flag para controlar o envio de mensagem
while (1)
{
// Delay de 1 segundo entre cada leitura do ADC
_delay_ms(1000);
contador_5s++;
// Lê o valor dos pinos PB2, PB1 e PB0 como valor de referência
uint8_t valor_dip = !(PINB & (1 << PINB2));
valor_dip |= !(PINB & (1 << PINB1)) << 1;
valor_dip |= !(PINB & (1 << PINB0)) << 2;
// Realiza a leitura do ADC no canal 1 e converte para tensão (0-5V)
float tensao = leitura_ADC(1) * (5.0 / 1024);
// Verifica se a tensão está abaixo ou igual ao valor do dip switch
if (tensao <= valor_dip) {
// Desliga o LED e reseta o contador e a flag de mensagem
PORTB &= ~(1 << PORTB7);
mensagem_enviada = 0;
contador_5s = 0;
}
// Se a tensão estiver acima do valor e a mensagem ainda não foi enviada
else if (!mensagem_enviada) {
// Envia a mensagem pela USART e define a flag como enviada
USART0_transmite_string_RAM("Tensao acima do permitido\r\n");
mensagem_enviada = 1;
}
// Acende o LED se a tensão estiver acima do valor por 5 segundos
if(contador_5s == 5) {
contador_5s = 0;
PORTB |= (1 << PORTB7); // Liga o LED
}
}
return 0;
}