O display possui 8 dígitos de 7 segmentos (mais o ponto), 8 LEDs bi-colores e 8 botões. O que precisamos descobrir é como estes componentes estão ligados ao TM1638.
O display possui 2 conectores de 10 pinos, na própria placa estão indicados os sinais presentes. Além da alimentação, CLK e DIO, o conector da esquerda (para quem vê a placa de frente) possui 6 sinais de strobe (STB0 a STB5). O sinal STB0 é o sinal de strobe do TM1638 que está na placa. O conector da direita possui somente 5 sinais de strobe (STB1 a STB5) que são os sinais da entrada deslocados de uma posição do conector. Isto permite ligar em cadeia até 6 placas usando cabos do tipo 1:1 (isto é, que ligam o pino 1 ao pino 1, o 2 ao 2, etc).
Nos meus testes, eu liguei a alimentação do display aos pinos Gnd e +5 do Arduino e os sinais STB0, DIO e CLK aos sinais digitais 7, 8 e 9 (respectivamente). Você pode, é claro, ligar os sinais a outros sinais digitais, usei estes apenas porque são os usados nos exemplos da biblioteca TM-1638. Aliás, é desta biblioteca (de autoria do português Ricardo Batista), que extraí as rotinas básicas de comunicação com o TM-1638. Para simplificar o meu teste, converti a classe em rotinas e variáveis; aproveitei para colocar alguns comentários adicionais:
- // Pinos usados na conexão do display
- byte TM16XX_dataPin; // DIO
- byte TM16XX_clockPin; // CLK
- byte TM16XX_strobePin; // STB
- // Códigos dos comandos do TM1638
- #define TM1638_CMD_WRDISPA 0x40 // Escrita no display, auto incremento
- #define TM1638_CMD_WRDISPF 0x44 // Escrita no display, endereço fixo
- #define TM1638_CMD_RDKEYS 0x42 // Leitura das teclas
- #define TM1638_CMD_SETADDR 0xC0 // Programa endereço
- #define TM1638_CMD_DISPON 0x88 // Liga display e ajusta intensidade
- // Iniciação
- void TM16XX_setup(byte dataPin, byte clockPin, byte strobePin)
- {
- // salva a configuração
- TM16XX_dataPin = dataPin;
- TM16XX_clockPin = clockPin;
- TM16XX_strobePin = strobePin;
- // Configura os pinos
- pinMode(TM16XX_dataPin, OUTPUT);
- pinMode(TM16XX_clockPin, OUTPUT);
- pinMode(TM16XX_strobePin, OUTPUT);
- digitalWrite(TM16XX_strobePin, HIGH);
- digitalWrite(TM16XX_clockPin, HIGH);
- // Faz a configuração inicial
- TM16XX_sendCommand(TM1638_CMD_WRDISPA);
- TM16XX_sendCommand(TM1638_CMD_DISPON | 7);
- // Limpa a memória
- // Posiciona no endereço 0 e usa auto-incremento
- digitalWrite(TM16XX_strobePin, LOW);
- TM16XX_send(TM1638_CMD_SETADDR | 0);
- for (int i = 0; i < 16; i++)
- TM16XX_send(0x00);
- digitalWrite(TM16XX_strobePin, HIGH);
- }
- // Lê as teclas
- void TM16XX_readButtons(byte *keys)
- {
- digitalWrite(TM16XX_strobePin, LOW);
- TM16XX_send(TM1638_CMD_RDKEYS);
- for (int i = 0; i < 4; i++) {
- *keys++ = TM16XX_receive();
- }
- digitalWrite(TM16XX_strobePin, HIGH);
- }
- // Escreve um dado em um endereço da memória
- void TM16XX_sendData(byte address, byte data)
- {
- TM16XX_sendCommand(TM1638_CMD_WRDISPF);
- digitalWrite(TM16XX_strobePin, LOW);
- TM16XX_send(TM1638_CMD_SETADDR | address);
- TM16XX_send(data);
- digitalWrite(TM16XX_strobePin, HIGH);
- }
- // Envia um comando
- void TM16XX_sendCommand(byte cmd)
- {
- digitalWrite(TM16XX_strobePin, LOW);
- TM16XX_send(cmd);
- digitalWrite(TM16XX_strobePin, HIGH);
- }
- // Envia um byte
- void TM16XX_send(byte data)
- {
- for (int i = 0; i < 8; i++) {
- digitalWrite(TM16XX_clockPin, LOW);
- digitalWrite(TM16XX_dataPin, data & 1 ? HIGH : LOW);
- data >>= 1;
- digitalWrite(TM16XX_clockPin, HIGH);
- }
- }
- // Recebe um byte
- byte TM16XX_receive()
- {
- byte temp = 0;
- // Vira DIO para dentro e liga o pull-up
- pinMode(TM16XX_dataPin, INPUT);
- digitalWrite(TM16XX_dataPin, HIGH);
- // Le os bits
- for (int i = 0; i < 8; i++)
- {
- temp >>= 1;
- digitalWrite(TM16XX_clockPin, LOW);
- if (digitalRead(TM16XX_dataPin))
- temp |= 0x80;
- digitalWrite(TM16XX_clockPin, HIGH);
- }
- // Volta DIO para saida
- pinMode(TM16XX_dataPin, OUTPUT);
- digitalWrite(TM16XX_dataPin, LOW);
- return temp;
- }
O programa principal recebe pela serial comandos para escrever na memória, alterar a intensidade e ler as chaves:
- // Variáveis para tratamento dos comandos na serial
- byte cmd[10];
- int iCmd = 0;
- // Tabela para mostrar valores em hexadecimal
- char hexa[] = "0123456789ABCDEF";
- // Iniciacao do Arduino
- void setup ()
- {
- Serial.begin (9600);
- TM16XX_setup (8, 9, 7);
- }
- // Execução
- void loop ()
- {
- if (Serial.available())
- {
- // Monta o comando
- int car = Serial.read();
- if (car == ';')
- {
- // Completou um comando
- cmd [iCmd] = 0;
- trataCmd();
- iCmd = 0;
- }
- else if (iCmd < (sizeof(cmd)-2))
- {
- if ((car >= 'a') && (car <= 'z'))
- car -= 0x20; // converte para maiúscula
- cmd [iCmd++] = car;
- }
- }
- }
- // Trata comando
- // R -> lê chaves
- // Wadd -> escreve dd no endereço a (dado e endereços em hexa)
- // In -> intensidade (n de 0 a 7)
- void trataCmd (void)
- {
- if (cmd[0] == 'R')
- {
- byte chaves[4];
- TM16XX_readButtons (chaves);
- Serial.print ("Chaves = 0x");
- for (int i = 0; i < 4; i++)
- {
- Serial.print(hexa[chaves[i] >> 4]);
- Serial.print(hexa[chaves[i] & 0xF]);
- }
- Serial.println();
- }
- else if ((cmd[0] == 'I') && (iCmd == 2))
- {
- TM16XX_sendCommand(TM1638_CMD_DISPON + (cmd[1] & 0x7));
- }
- else if ((cmd[0] == 'W') && (iCmd == 4))
- {
- byte ender, dado;
- ender = htoi (cmd[1]);
- dado = (htoi (cmd[2]) << 4) + htoi (cmd[3]);
- TM16XX_sendData (ender, dado);
- Serial.print ("Mem[");
- Serial.print (ender, HEX);
- Serial.print ("] = 0x");
- Serial.print (dado, HEX);
- Serial.println ();
- }
- else
- Serial.println ("ERRO");
- }
- // Decodifica um dígito hexadecimal
- int htoi (char car)
- {
- if ((car >= '0') && (car <= '9'))
- return car - '0';
- if ((car >= 'A') && (car <= 'F'))
- return car - 'A' + 10;
- return 0;
- }
- Os segmentos dos dígitos são controlados pelas posições pares das memória. Partindo da esquerda para a direita do display, as posições correspondentes são 0, 2, 4, ... 14.
- Em cada posição par, o bit mais significativo (7) corresponde ao ponto decimal. Os bits 0 a 6 correspondem aos segmentos 'a' a 'g' (ver figura abaixo).
- As posições ímpares da memória controlam os LEDs bicolores. Partindo da esquerda para a direita, os LEDs são controlados pelas posições 1, 3, 5, ... 15.
- Lembrando, no TM1638 apenas os dois bits menos significativos estão disponíveis nas posições ímpares. O bit 0 acende o LED na cor vermelha vermelho e o bit 1 na cor verde. Se você ativar simultaneamente os dois bits o LED acenderá nas duas cores resultando em um laranja (muito parecido com o vermelho para o meu gosto).
- As primeiras quatro chaves correspondem ao bit menos significativos (bit 0) dos quatro bytes de leitura das chaves. As quatro últimas chaves correspondem ao bit 3 dos mesmos byte.
2 comentários:
Seria possivel implementar um relógio com um display desses?
Sou novo na area do arduino e gostaria de fazer um relógio com meu display. Voce não teria o codigo para essa finalidade?
Obrigado
Não é difícil implementar um relógio, mas eu prefiro usar o JY-MEGA3208 que já tem embutido o microcontrolador. Uma limitação dos dois é que não tem um relógio de tempo real propriamente dito, o ideal seria ter um com uma bateria para manter a data e hora, como fiz em outro projeto.
Postar um comentário