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 Serial
O 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