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;
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]);
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
- }
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