Mostragem em display LCD

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Mostragem em display LCD

Mensagempor buiz » 11 Set 2008 19:46

Ola amigos,

Estou com uma duvida em C que parece simples mas tem me tirado o sono para resolver.

Estou fazendo os menus de um novo projeto, e nos campos ainda sem valores ao inves de mostrar 00 tera que mostrar -- (dois tracinhos)

Mas como minha variavel e um numero inteiro, e nao tem como trabalhar com dois tipos de mostragem em um mesmo campo do display, ou seja para inteiro uso %u e para caracteres %s, como faco para mostra -- quando o valor for 0?

Desculpe os erros de acentuacao mas meu note ta meio louco esta semana e nao aceita nada.

Um exemplo do que tera que acontecer:

Hora: 00:00 (assim e o normal)
Hora: --:-- (Preciso que apareca assim e ao digitar o valor substitua o -- pelo valor digitado)

Se alguem tiver alguma solucao, ficarei eternamente grato, pois faz tempo que este problema me atormenta.

So lembrando programo em C no CCS.

Um abraco a todos!
Avatar do usuário
buiz
Byte
 
Mensagens: 165
Registrado em: 20 Out 2006 14:59
Localização: Cachoeira do Sul - RS

Mensagempor microcontrolador.pic » 11 Set 2008 23:20

Olá amigo,

Na linguagem BASIC (a que eu entendo) eu faria o seguinte:

print at 1,1, "Hora: 00:00" ;(mostrar na tela normal)

para programar a hora eu faria

print at 1,1, "Hora: --:--"

e na media que pressionar alguma tecla, incrementa uma variável que deslocará o número na posição contida a string "-" da tela acima;
por exemplo:


print at 1,7 "2" ; isto mostraria no display "Hora: 2-:--"
print at 1,8 "1" ; isto mostraria no display "Hora: 21:--"
print at 1,10 "1" ; isto mostraria no display "Hora: 21:1-"
print at 1,11 "6" ; isto mostraria no display "Hora: 21:16"


agora para o problema da conversão para número inteiro:
"1" = "01"
"2" = "02"
você deveria comparar se a string a ser mostrada houver 2 digitos, senão deveria adicionar o "0" antes para obter dois dígitos.


Obs.: desculpe o código ou a explicação bastante resumida, espero ter lhe ajudado.

Abraços!
:D
Avatar do usuário
microcontrolador.pic
Nibble
 
Mensagens: 50
Registrado em: 08 Set 2008 19:51

Mensagempor buiz » 12 Set 2008 07:51

Realmente o que eu necessito e isso mesmo, trocar os tracinhos pelo valor digitado

Mas nao estou achando como fazer isso em C, obrigado pela dica, vou dar uma analisada e ver o que posso aproveitar dela.

Valeu, se alguem tiver mais alguma dica fico grato,

Um bom dia a todos!
Avatar do usuário
buiz
Byte
 
Mensagens: 165
Registrado em: 20 Out 2006 14:59
Localização: Cachoeira do Sul - RS

Mensagempor phophollety » 12 Set 2008 08:17

buiz escreveu:Realmente o que eu necessito e isso mesmo, trocar os tracinhos pelo valor digitado

Mas nao estou achando como fazer isso em C, obrigado pela dica, vou dar uma analisada e ver o que posso aproveitar dela.

Valeu, se alguem tiver mais alguma dica fico grato,

Um bom dia a todos!


Como está escrevendo no lcd? printf direto!?

Procure fazer um vetor com o nome de bufferLcd[][]. com o número de linhas correspondende ao seu display e o número de colunas correspondente também.

Faça um driver que por timer pegue esse vetor todo e reescreve no LCD.

Faça um buffer constante com as mensagens , supomos que seu display é um 2 * 16

Código: Selecionar todos
const unsigned char Mensagens [QUANTIDADE_DE_MENSAGENS][NUMERO_DE_COLUNAS] { "mensagem 1  ", // 0
                                        "mensagem 2  ", // 1
                                        "mensagem n..." // 2
                                         "Hora: --:--     "}; // 3 Mantenha os 16 caracteres!!!

Quando for chamar a mensagem, você carrega do constante para o buffer do driver, faça um for

for ( i = 0; i < NUMERO_DE_COLUNAS, i ++ )
{
      bufferLcd[ LINHA_1 ][ i ] = Mensagens[ 3 ] [ i ]
}

O buffer estará escrito;

crie uma variável cont, que vc usará por todo o programa

unsigned char cont = 0;

tem sua variavel hora, um int.

unsigned int hora = 0;

switch( cont )
{
    case 0:
         bufferLcd[ LINHA _ 1][ 11 ] = ( ( hora & 0x000f ) + 0x40 );
         break;

    case 1:
         bufferLcd[ LINHA _ 1][ 12 ] = unsigned int( ( ( hora & 0x00f0 ) + 0x40 ) >> 4 );
         break;

    case 2 :
         bufferLcd[ LINHA _ 1][ 13 ] = unsigned int (( ( hora & 0x0f00 ) + 0x40 ) >> 8 );
         break;

    case 3:
         bufferLcd[ LINHA _ 1][ 14 ] = unsigned int (( ( hora & 0xf000 ) + 0x40 ) >> 12 );
         break;
         break;

}

Toda vez que o seu usuário colocar uma hora, você chama essa rotina..

Faça uma rotina com todas as telas do display, fica melhor estruturado.
Basicamente assim, quando ele colcar uma hora, você vai no switch.

Claro, coloque as variáveis na área de variaveis ou no começo da função, não se esqueça dos idents, faça uma boa estrutura, é vitál quando o programa começa a crescer ou numa futura manutenção.




"3 minutes of boring code review means 3 hours less fixing LSD (Little Stupid Detail)" Dr. Mike Smith
"Dê-me um ponto de apoio e uma alavanca e moverei o mundo" Arquimedes
"Quando vejo um Alfa Romeo passar eu tiro o meu chapéu" Henry FORD.
Avatar do usuário
phophollety
Dword
 
Mensagens: 1511
Registrado em: 15 Out 2006 13:00
Localização: Santo André São Paulo, Brasil

Mensagempor buiz » 12 Set 2008 08:38

Muito boa a sua a idéia phophollety,

Ainda não tinha pensado em fazer desta forma, ficou pratico, estou dando uma olhada para ver como poderei implementar no meu programa, pois ele ja estava quase pronto, na realidade esta pronto, só estou tentando acertar esta parte agora, pois meu chefe acha melhor que apareça tracinhos ao inves de 00000000000......

Outra duvida, andei dando uma olhada nos ATOIs ATOLs mas com eles posso passar uma string para inteiro, e para passar de inteiro para string, tem alguma solução?

Andei dando uma olhada no Help do CCS mas não encontrei nada de inteiro para String.

Tambem seria uma solução para mim se eu conseguisse fazer desta forma.

Obrigado pelas dicas.
Avatar do usuário
buiz
Byte
 
Mensagens: 165
Registrado em: 20 Out 2006 14:59
Localização: Cachoeira do Sul - RS

Mensagempor buiz » 12 Set 2008 09:22

Ola,

Bom, achei como fazer usando o ITOA(), mas ocupa muita memoria do uC, mas funcionou, vou ver se consigo otimizar um pouco o meu codigo.

Continuo na luta!
Avatar do usuário
buiz
Byte
 
Mensagens: 165
Registrado em: 20 Out 2006 14:59
Localização: Cachoeira do Sul - RS

Mensagempor joao » 12 Set 2008 10:00

Ola,

Não sei se funcionaria para microcontrolador, mas acho que sim. Se não rolar, avisa:

o que você tem hoje em dia é algo deste tipo?

Código: Selecionar todos
int hora[4]; //quatro posicoes, sendo duas para hora e 2 para minuto

printf(lcd,"hora: %d%d:%d%d", hora[0],hora[1],hora[2],hora[3]);


O que eu sugeriria era fazer o seguinte:
Código: Selecionar todos
int hora[4]; //quatro posicoes, sendo duas para hora e 2 para minuto

for (int i=0; i<4; i++) //Zerando as variaveis com -1
    hora[i] = -1;

/*Aqui neste espaço vc faz a captura dos valores, e joga na variavel hora*/

printf(lcd,"hora: %c%c:%c%c",
               hora[0] == -1 ? '-':'0'+hora[0],
               hora[1] == -1 ? '-':'0'+hora[1],
               hora[2] == -1 ? '-':'0'+hora[2],
               hora[3] == -1 ? '-':'0'+hora[3]);


Explicando essa linha aqui: hora[0] == -1 ? '-':'0'+hora[0]
é um if ternario que é isso:
condicao ? retorno_se_verdadeiro: retorno_se_falso

A condição é: hora[0] == -1 verifica se a variavel tem o valor original.
retorno_se_verdadeiro é: '-' se for -1, retorna o traço
retorno_se_falso é: '0'+hora[0] que retorna o valor ASCII de '0' MAIS o valor de hora. Entao imagine que vc tem 1 na variavel hora[0], ele vai retornar o valor ASCII de '0' +1 que é na verdade '1'.

Bem, seilá se pirei muito. :)

Mas quem sabe lhe de uma idéia melhor do que fazer.

[]'s
Avatar do usuário
joao
Byte
 
Mensagens: 463
Registrado em: 17 Out 2006 08:21

Mensagempor ze » 12 Set 2008 10:39

ocupar muita memória é o resultado de usar rotinas préprontas.
mas de int (na verdade char) pra string não é só somar 0x30?
um ex. que funciona nos meus projs pra 4 (ou -) dígitos:
Código: Selecionar todos
void lcd_dec(unsigned char li,unsigned char co,unsigned char nd,unsigned int dado)
{
unsigned int mil,cen,dez,un;
mil=dado/1000;
cen=(dado-mil*1000)/100;
dez=(dado-mil*1000-cen*100)/10;
un=dado-mil*1000-cen*100-dez*10;
LCD_RS=0;
lcd_write(li+co);//posiciona cursor
LCD_RS=1;
switch(nd) { //num de dígitos
   case 4: lcd_write(mil+0x30);//sem break
   case 3: lcd_write(cen+0x30);
   case 2: lcd_write(dez+0x30);
   case 1: lcd_write(un+0x30);
   }
}
substitui o itoa() e come menos mem. ah, o lcdwrite() é uma rotininha que escreve 1 caracter no disp.
abs
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Mensagempor joao » 12 Set 2008 10:43

Lellis,

A unica diferença que eu vejo é em relação a valores maiores que 9...
com o itoa, vc consegue tranformar 1234567 para "1234567"
Enquanto que somando apenas 0x30 não rola.

0x30 = 48 decimal = '0' em ASCII.

Por isso que somando 0x30 dá certo, mas usando apenas 1 casa decimal apenas. Mais do que isso é erro na certa!
Avatar do usuário
joao
Byte
 
Mensagens: 463
Registrado em: 17 Out 2006 08:21

Mensagempor ze » 12 Set 2008 13:18

corretíssimo joão padre marcelo!!! é claro que percebeste que a rotininha acima desmonta o int e coloca cada asc com uma pinça no display. e pode ser menor que 9 sim. se não quiser o zero a esquerda (= eu), é só "argumentar" 1 no nd. aquele ex. é de pobre pra pobre (de memória). tente ver que aqui em baixo temos que trabalhar as vezes com 16 bytes de ram e 256 de rom total e em 100% C e é possível! o itoa() é pra ricos e inteligentes. mas tem sua utilidade. na verdade prefiro sprintf().
ah, tá...aquelas continhas não deixam o valor > 9 se dado<=9999
abs.....
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Mensagempor joao » 12 Set 2008 13:50

Tá reclamando do que?

Olha a gambiarra que eu fiz ali no código...
Só que eu uso direto em ASCII ao invés de hexa como tu...
Pq saber valores hexa é para poucos e ricos!
Eu, pobre mortal, uso o ASCII mesmo...
hehehe

[]'s
Avatar do usuário
joao
Byte
 
Mensagens: 463
Registrado em: 17 Out 2006 08:21

Mensagempor buiz » 12 Set 2008 14:56

Ai pessoal, por questão de tempo estourado para entregar o projeto, e sem falar que ja esta praticamente 98% pronto, apelei para o ITOA().

Ficou +/- assim, esse foi um teste apenas.

Código: Selecionar todos
int val=123;//Variavel que muda conforme a programação
char string[4];
char zero[]={"--"};//Substitui o zero no display
char mostra[];// Variavel de mostragem


if (val>0) {itoa(val,10,string);// Se val maior que zero usa o itoa
                mostra=string;}// Atribui o valor de String a Variavel mostra
                                       

if (val==0) mostra=zero;// Se val igual a zero escreve --

printf (LCD,"teste: %s",mostra);// Escreve no Lcd




Mas para os proximos projetos vou estudar cada uma das sugestões dadas.

Obrigado microcontrolador.pic.
Obrigado phophollety
Obrigado Joao
Obrigado Lellis

Um abraço a todos! Um otimo final de semana!
Avatar do usuário
buiz
Byte
 
Mensagens: 165
Registrado em: 20 Out 2006 14:59
Localização: Cachoeira do Sul - RS

Mensagempor Maurício » 12 Set 2008 18:34

buiz,

Já que vc está trabalhando com tempo de relógio, que varia no máximo até 59D (3BH), substitua os traços por 0xFFH e testa!

Se for 0xFF, sua rotina de impressão substitui o byte 0xFF por traços.
O que está no LCD, só vale pro LCD. Na memória continua tudo como está.

Eu faço isso!

[]'s
"Não leve a vida tão à sério, afinal, nenhum de nós sairá vivo, dela!"
Avatar do usuário
Maurício
Word
 
Mensagens: 678
Registrado em: 14 Out 2006 17:23
Localização: São Paulo - SP

Mensagempor phophollety » 14 Set 2008 09:17

Maurício escreveu:buiz,

Já que vc está trabalhando com tempo de relógio, que varia no máximo até 59D (3BH), substitua os traços por 0xFFH e testa!

Se for 0xFF, sua rotina de impressão substitui o byte 0xFF por traços.
O que está no LCD, só vale pro LCD. Na memória continua tudo como está.

Eu faço isso!

[]'s


Simples e funcional...

A vantagem de se usar como eu mostrei é que é prático poder alterar um só caracter, sem ter que rescrever o display todo...

Essa técnica de fazer um "device driver" genérico que só faz pegar do vetor e escrever no display pelo timer e específico para cada uC aliado a rotina de estrutura de display é ótima, pois a rotina de estrutura é completamente portável para qualquer compilador, basta reescrever o device driver...
"3 minutes of boring code review means 3 hours less fixing LSD (Little Stupid Detail)" Dr. Mike Smith
"Dê-me um ponto de apoio e uma alavanca e moverei o mundo" Arquimedes
"Quando vejo um Alfa Romeo passar eu tiro o meu chapéu" Henry FORD.
Avatar do usuário
phophollety
Dword
 
Mensagens: 1511
Registrado em: 15 Out 2006 13:00
Localização: Santo André São Paulo, Brasil


Voltar para PIC

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

cron

x