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