O Projeto
A origem deste projeto foi o desejo do meu amigo Tony colocar um display na bicicleta e poder selecionar a mensagem a apresentar através de teclas no guidão. Este firmware é apenas a parte inicial deste projeto, à medida em que ele evoluir eu vou documentado no blog.
Nós já vimos como apresentar uma mensagem no display, rolando o texto da direita para a esquerda. Para este novo projeto vamos precisar guardar várias mensagens, e a EEProm do ATmega é o lugar óbvio. Como colocar e editar estas mensagens? Em princípio daria para fazer pelo gravador, mas é mais versátil fazer isto pela serial do ATmega, que está disponível no conector de programação.
Usar a serial simplifica uma outra parte do projeto: como selecionar a mensagem a apresentar. Poderíamos, é claro, ligar diretamente um botão em uma porta digital do ATmega para cada mensagem, mas poucas entradas digitais estão disponíveis no conector de programação e ficaria um monte de fios. Com a serial, podemos ligar os botões a um outro microcontrolador no guidão (um ATtinyx5 ou x4 dependendo do número de botões) e fazer a conexão entre os dois por três fios (Vcc, Gnd e comunicação, supondo que baste comunicar em um sentido).
O firmware (que você pode baixar dos arquivos do blog como JYMCU3208_Banner2.zip) ilustra algumas técnicas interessantes de programação AVR.
Acesso à EEprom
A memória EEprom requer alguns cuidados no acesso. Felizmente, a avr-libc possui rotinas prontas para isto. O primeiro passo é marcar com EEMEN as estruturas que estarão na EEprom:
// Mapeamento das mensagens na EEProm // O ATmega8 tem 512 bytes de EEProm #define T_MSG 40 // tamanho máximo de cada mensagem #define N_MSG 8 // quantidade de mensagens uint8_t eepMsgs[N_MSG][T_MSG+1] EEMEM;Esta indicação é usada pelo linker, que mapeia estas estruturas no espaço de endereçamento da EEprom (que é separado da Ram e Flash).
Para ler e escrever usamos as rotinas eeprom_read_byte() e eeprom_update_byte(). Existe também a rotina eeprom_write_byte; a update verifica primeiro o que já está na eeprom e só grava se for diferente, evitando gastar a eeprom desnecessariamente (pois o número de gravações é limitado).
// Carrega da EEProm a mensagem atual
static void load_msg (uint8_t *pMsg)
{
int i;
for (i = 0; i < T_MSG; i++)
pMsg[i] = eeprom_read_byte (&eepMsgs[msg_atual][i]);
pMsg[i] = 0; // garante fim no final
}
// Salva a mensagem editada
for (j = 0; j <= i; j++)
eeprom_update_byte (&eepMsgs[msgEd][j], msg[2+j]);
Comunicação SerialO ATmega8 possui uma USART para comunicação serial síncrona e assíncrona. A programação é um pouco chatinha, mas basta suar um pouco sobre o manual para obter uma sequência de iniciação apropriada:
// Inicia a comunicação serial
static void init_serial ()
{
// Inicia a fila
poe = tira = 0;
// Programa a USART para 9600 8N1
UCSRA = _BV(U2X); // para maior resolução do baud rate
UCSRB = _BV(RXEN) | _BV(TXEN) | _BV(RXCIE); // liga recepção e transmissão
// com interrupção de Rx
UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0) ;// 8bit, 1 stop, sem paridade
UCSRC = 0; // UBRRH = 0
UBRRL = (CLK_CPU / (8 * 9600UL)) - 1; // 9600 bps
}
Uma coisa estranha é o registrador de controle UCSRC e a parte alta do registrador de programação do clock UBRR possuem o mesmo endereço. A seleção entre os dois é através de um dos bits escritos (URSEL).Optei por trabalhar com interrupção na recepção, os caracteres recebidos são guardados em uma fila circular para serem processados depois pelo programa principal:
// Fila de recepção da serial
#define T_FILA 16
static volatile uint8_t filaRx[T_FILA];
static volatile uint8_t poe, tira;
// Pega o próximo caracter da fila de recepção da serial
// Retorna -1 se fila vazia
static int le_serial ()
{
int c;
cli ();
if (poe == tira)
c = -1; // fila vazia
else
{
c = filaRx[tira];
if (++tira == T_FILA)
tira = 0;
}
sei ();
return c;
}
// Interrupção de recepção da USART
ISR(USART_RXC_vect)
{
uint8_t prox;
filaRx[poe] = UDR; // pega o caracter
prox = poe + 1; // avança o ponteiro de entrada
if (prox == T_FILA)
prox = 0;
if (prox != tira) // não atualizar se fila cheia
poe = prox;
}
Uso do Firmware
O firmware é razoavelmente fácil de usar.
Para gravar as mensagens, conecte a serial a um PC (usando um conversor TTL USB e um programa de comunicação como o PuTTY); a velocidade é 9600bps e o formato 8N1. Para alterar a mensagem "n" (onde n varia de 1 a 8) digite * n texto Enter. Se você digitar algo errado, use o backspace para apagar. ESC cancela a edição.
Para apresentar a mensagem n, basta digitar n. Você pode navegar também entre as mensagens usando as teclas 1 e 2 do display,
A pegadinha é que teclas e serial só são verificados ao final da apresentação da mensagem atual.
Nenhum comentário:
Postar um comentário