Mais preocupante é a questão de armazenar na Flash a matriz de caracteres e outras imagens. A matriz que usamos no Arduino tem 96x5 bytes o que é uma quantidade respeitável para os PICs mais simples. Além disso, os modelos mais tradicionais assumem que a Flash conterá apenas código, não tendo instruções específicas para acessar dados armazenados nela. Vamos usar aqui um PIC mais moderno, o 16F882, e deixar por conta do compilador CSC C o trabalho sujo de armazenar e extrair os dados da Flash.
Hardware
O hardware é bastante simples, principalmente se alimentarmos o PIC com 3V:
Montagem com alimentação de 3V |
Circuito para alimentação de 3V |
Montagem com alimentação de 5V |
Circuito para alimentação de 5V |
Software
O software a seguir é uma adaptação direta do primeiro exemplo que vimos com o Arduino. As principais mudanças se devem às diferenças entre os compiladores e as bibliotecas. Como não temos a função shiftOut, os sinais de dados e clock são pulsados manualmente.
#include <16f882.h> #device adc=8 #use delay(clock=8000000) #fuses NOWDT, NOCPD, NOPROTECT #fuses MCLR, INTRC_IO #use fast_io(A) // Conexões do display ao PIC #define PIN_SCE PIN_A0 #define PIN_RESET PIN_A1 #define PIN_DC PIN_A2 #define PIN_SDIN PIN_A3 #define PIN_SCLK PIN_A4 // Um LED para debug #define PIN_LED PIN_A5 // Seleção de dado ou comando #define LCD_CMD 0 #define LCD_DAT 1 // Tamanho da tela #define LCD_DX 84 #define LCD_DY 48 static const byte ASCII[][5] = { {0x00, 0x00, 0x00, 0x00, 0x00} // 20 ,{0x00, 0x00, 0x5f, 0x00, 0x00} // 21 ! ,{0x00, 0x07, 0x00, 0x07, 0x00} // 22 " ,{0x14, 0x7f, 0x14, 0x7f, 0x14} // 23 # ,{0x24, 0x2a, 0x7f, 0x2a, 0x12} // 24 $ // etc ,{0x10, 0x08, 0x08, 0x10, 0x08} // 7e ? ,{0x78, 0x46, 0x41, 0x46, 0x78} // 7f ? }; // Rotinas locais void InitHw (void); void LcdWrite (byte dc, byte data); void LcdInitialise (void); void LcdClear (void); void LcdPos (byte lin, byte col); void LcdWriteChar (char character); void LcdWriteString(char *characters, byte lin, byte col); // Ponto de entrada e loop principal void main (void) { InitHw (); LcdInitialise (); LcdClear (); LcdPos (2, 3); LcdWriteChar ('D'); LcdWriteChar ('Q'); LcdWriteChar ('S'); LcdWriteChar ('o'); LcdWriteChar ('f'); LcdWriteChar ('t'); output_high (PIN_LED); for (;;) ; } // Iniciação do hardware void InitHw (void) { // Bota para correr setup_oscillator (OSC_8MHZ); // Dispositivos não usados setup_comparator(NC_NC); setup_vref(FALSE); setup_adc(ADC_OFF); // E/S set_tris_a (0xC0); // RA0-RA5 output } // Envia um byte para o controlador do display // dc: LCD_CMD ou LCD_DAT // data: byte a enviar void LcdWrite(byte dc, byte data) { byte i; if (dc == LCD_CMD) output_low (PIN_DC); else output_high (PIN_DC); output_low (PIN_SCE); delay_us(10); for (i = 0; i < 8; i++) { if (data & 0x80) output_high (PIN_SDIN); else output_low (PIN_SDIN); output_high (PIN_SCLK); delay_us(10); output_low (PIN_SCLK); delay_us(10); data = data << 1; } delay_us(10); output_high (PIN_SCE); } // Iniciação do display void LcdInitialise(void) { output_low (PIN_SCLK); output_high (PIN_SCE); // executa um reset do controlador output_low (PIN_RESET); delay_us (10); output_high (PIN_RESET); // envia os comandos de iniciação LcdWrite( LCD_CMD, 0x21 ); // LCD Extended Commands. LcdWrite( LCD_CMD, 0xaf ); // Set LCD Vop (Contraste) LcdWrite( LCD_CMD, 0x04 ); // Set Temp coefficent LcdWrite( LCD_CMD, 0x14 ); // LCD bias mode 1:48 LcdWrite( LCD_CMD, 0x20 ); // LCD Basic Commands. LcdWrite( LCD_CMD, 0x0c ); // LCD no modo normal } // Limpa a tela void LcdClear(void) { int16 i; // posiciona ponteiro no inicio da memória LcdWrite( LCD_CMD, 0x40); LcdWrite( LCD_CMD, 0x80); // preenche a memória com zeros for (i = 0; i < ((LCD_DX * LCD_DY) / 8); i++) { LcdWrite(LCD_DAT, 0x00); } } // Posiciona em uma determina linha e coluna alfanuméricas void LcdPos(byte lin, byte col) { LcdWrite( LCD_CMD, 0x40 + lin); LcdWrite( LCD_CMD, 0x80 + col*7); } // Escreve um caracter na posição atual void LcdWriteChar(char character) { byte i; LcdWrite(LCD_DAT, 0x00); for (i = 0; i < 5; i++) { LcdWrite(LCD_DAT, ASCII[character - 0x20][i]); } LcdWrite(LCD_DAT, 0x00); } // Escreve um string a partir de uma certa // linha e coluna void LcdWriteString(char *characters, byte lin, byte col) { LcdPos (lin, col); while (*characters) LcdWriteChar(*characters++); }
Como de costume, o projeto completo está nos arquivos do blog, no arquivo Nokia5110_PIC.zip.
4 comentários:
Esses mesmos arquivos e bibliotecas funcionam com o 18F4550?
Nivaldo,
Não tenho experiência com o PIC18, mas acho que serão precisos ajustes, principalmente no InitHw(). Além disso, costuma ter uma diferença grande entre os compiladores C para PIC.
boa noite, no pic 16f877a é a mesma configuração?
Renato,
Em uma olhada rápida no datasheet do 16F877 reparei que ele não tem oscilador interno, portanto será necessário acrescentar componentes para gera o clock (por exemplo um cristal de 8MHz). Acho que o resto (inclusive o acesso ao gerador de caracteres na Flash) devem funcionar.
Postar um comentário