/**
* @file lista_4_problema_2.c
* @author Giovani Baratto ([email protected])
* @brief Este programa imprime a mensagem "Chave pressionada." a cada pulso em
* uma chave tipo push-button no terminal PB0.
* @version 0.1
* @date 2023-04-19
Escreva um programa para piscar um LED no terminal PB7 de um microcontrolador ATmega
2560. O LED deve piscar uma sequência de pulsos em intervalos de 2 segundos (veja a figura
1). O LED deve piscar uma vez na primeira sequência, duas vezes na segunda, continuando
até uma sequência de 5 vezes. Em seguida as sequências são repetidas. Faça a simulação.
*/
#include <stdint.h>
#define __AVR_ATmega2560__
#ifndef F_CPU /* se não foi definida a frequência de relógio do microcontrolador */
#define F_CPU 16000000UL /* definimos a frequência de relógio da placa Arduino Mega: 16 MHz */
#endif /* F_CPU */
#include <avr/io.h> /* definição das entradas/saÃdas do sistema */
#include <avr/pgmspace.h> /* Usamos procedimentos para ler dados da memória de programa */
#include <util/delay.h>
// definição das variáveis do programa
uint8_t estado_atual_chave; // o estado da chave: valor da chave sem debounce
uint8_t estado_anterior_chave; // armazena o estado anterior da chave
uint8_t leitura_atual_chave; // a leitura atual do valor da chave
uint8_t leitura_anterior_chave; // a leitura anterior do valor da chave
uint8_t chave_pressionada; // 1 se é reconhecida uma borda de descida
/**
* @brief AtribuÃmos os valores inciais para as variáveis usadas para o debounce da chave.
*/
void variaveis_configura(void)
{
// configuração das variáveis para a leitura da chave em PB0 e estado LED
leitura_atual_chave = ((PINB & (1 << PINB0)) == 0x01); // lemos o valor da chave
estado_atual_chave = leitura_atual_chave; // O estado inicial da chave é o valor da chave
}
/**
* @brief Realizamos a leitura e o debounce da chave em PBO. Este procedimento
* deve ser chamada em intervalos iguais ou maiores ao intervalo de repique da
* chave.
*/
void leitura_chave(void)
{
// faz a leitura da chave eliminando o debounce
leitura_anterior_chave = leitura_atual_chave; // atualizamos a leitura anterior da chave
leitura_atual_chave = ((PINB & (1 << PINB0)) == 0x01); // realizamos a leitura de PB0
estado_anterior_chave = estado_atual_chave; // atualiza o estado anterior da chave
if (leitura_atual_chave == leitura_anterior_chave) // se o sinal da chave permanece estável no intervalo
{
estado_atual_chave = leitura_atual_chave; // o estado da chave é igual ao valor da chave
}
// verificamos se a chave foi pressionada
chave_pressionada = (estado_anterior_chave == 0x01) && (estado_atual_chave == 0x00); // é uma borda de descida?
}
/**
* @brief Configura o periférico USART no modo assÃncrono e quadros no formato 8N1. A taxa de transmissão é 57600 BAUD,
* considerando uma frequência de relógio de 16 MHz. Habilita a USART para receber e transmitir (full-duplex). Veja
* página 206 do manual de especificações do ATMega2560
*/
void USART0_configura(void)
{
UBRR0 = 0x022; // UBRR0H = 0 e UBRR0H = 0x22
UCSR0A = 0x02; // RXC0=0, TXC0=0, UDRE0=0, FE0=0, DOR0=0, UPE0=0, U2X0=1 e MPCM0 = 0
UCSR0B = 0x18; // RXCIE0=0, TXCIE0=0, UDRIE0=0, RXEN0=1, TXEN0=1, UCSZ0[2]=0, RXB80=0 e TXB80=0
UCSR0C = 0x06; // UMSEL0[1:0]=00, UPM0[1:0]=00, USBS0=0, UCSZ0[1:0]=11 e UCPOL0=0
}
/**
* @brief Transmite um byte (dado) pela USART0. Veja a página 207 do manual de especificações do ATmega2560
* @param dado O byte qye será transmitido.
*/
void USART0_transmite(uint8_t dado)
{
while (!(UCSR0A & (1 << UDRE0))) // esperamos o buffer de transmissão ficar vazio
;
UDR0 = dado; // colocamos o dado a ser transmitido no buffer de transmissão
}
//
/**
* @brief Recebe um byte da USART0
* @return uint8_t. Byte recebido da USART0. Veja a página 210 do manual de
* especificações do ATMega2560.
*/
uint8_t USART0_recebe(void)
{
while (!(UCSR0A & (1 << RXC0))) // espera o dado ser recebido
;
return UDR0; // retorna o dado recebido no buffer de recepção
}
/**
* @brief Transmite pela USART os bytes da string str, armazenada na memória SRAM
* @param str Ponteiro para uma string armazenada na memória RAM
*/
void USART0_transmite_string_RAM(uint8_t *str)
{
uint8_t ch;
// Este laço while é executado até encontrarmos o caractere ch = 0x00, marcando o final da string
while (ch = *str++) // carregamos um caractere da string e apontamos para o próximo caractere
{
USART0_transmite(ch); // transmite o caractere pelo terminal TX da USART0
}
}
/**
* @brief Transmite pela USART os bytes da string str, armazenada na memória FLASH
* @param str Ponteiro para uma string armazenada na memória FLASH
*/
void USART0_transmite_string_FLASH(uint8_t *str)
{
uint8_t ch;
// Este laço while é executado até que o caractere ch = 0x00, marcando o final da string.
// Os caracteres são lidos da memória FLASH.
while (ch = pgm_read_byte(str++)) // carregamos um caractere da string e apontamos para o próximo caractere
{
USART0_transmite(ch); // transmite o caractere pelo terminal TX da USART0
}
}
/**
* @brief Configuramos a porta PB0 como entrada e adicionamos o resistor de pull-up
*/
void PORTAS_configura(void)
{
DDRB = DDRB & (~(1 << DDB0)); // fazemos PB0 uma entrada
PORTB = PORTB | (1 << PORTB0); // adicionamos um resistor de pull-up interno a PB0
}
/**
* @brief Procedimento principal. Envia pela USART0 a string "Chave pressionada"
* @return int Este procedimento não retorna.
*/
int main(void)
{
USART0_configura(); // configuramos a USART0 para receber e transmitir a 57600 BAUD quadros no formato 8N1
PORTAS_configura(); // Fazemos PB0 uma entrada para uma chave tipo push-button.
variaveis_configura(); // Configura os valores iniciais das variáveis do programa
while (1)
{
_delay_ms(10); // esperamos um intervalo de tempo maior que o intervalo de repique da chave
leitura_chave(); // realizamos a leitura da chave em PB0
if (chave_pressionada) // se a chave foi pressionada
{
USART0_transmite_string_FLASH(PSTR("Chave pressionada.\n")); // enviamos uma mensagem pela USART0, com uma string da memória FLASH
}
}
}