TM1638

Using TM1638

TM1638

How works a TM1638:

The TM1638 is a small board with a range of Leds, a range of digits and a range of buttons.
It takes 3 pins to receive instructions ( plus on for vcc and one for ground).

This 3 pins are :
STROBE, used to start an instruction.
CLCK used to inform that a bit is readable.
DATA used to send bit.

It has 16 addresses used to control Leds and Digits.
Even adresses are for digits and odd one for leds.

You have a set of 4 instructions that you can send over:
ACTIVATE (0x8F) = activate the board, make it ready to receive other instructions.
WRITE_SINGLE (0x44)  = write byte to single address
WRITE_CONSECUTIVE (0x40) = write byte consecutively starting at a specific address
READ (0x42)  = read incoming byte.

At the beginning all your Pins linked to the board must be in Output mode.
STROBE pin must be set (to HIGH).
All the other must be clear (to LOW).

How to send DATA

Data are sent bit by bit over the DATA pin.
You first set your bit and then pulse (HIGH then LOW) CLCK Pin to inform the board a data is available.
And so on, until the last bit.

How to send command

To send a command you have to put STROBE to CLEAR (LOW).
When your command number is sent (see How to send data), you SET STROBE (HIGH).
If you command has parameters like an adress and a value, again you CLEAR STROBE before sending them, and SET STROBE when it’s done.

Activate the board

To activate the board you must first send the activate command.
The command is 0x8 + the brightness.
In our library we set the maximum brightness so we gonna send :
0x8F to the board.
There is no parameters to this function.
So typically we ‘ll send 1001111 bits.

In pseudo code:
STROBE:CLEAR
DATA:SET
CLCK:PULSE_HIGH
DATA:SET
CLCK:PULSE_HIGH
DATA:SET
CLCK:PULSE_HIGH
DATA:SET
CLCK:PULSE_HIGH
DATA:CLEAR
CLCK:PULSE_HIGH
DATA:CLEAR
CLCK:PULSE_HIGH
DATA:SET
CLCK:PULSE_HIGH
STROBE:SET

LEDs

You control led over even addresses.
The simplest way to switch on the led is to send the WRITE_SINGLE command.
This command take two parameters (two bytes): the address and the byte to write.
If you want to switch on you send 1.
To switch off you send 0.
To send the address the form is 1100xxxx where xxxx represent the address.
This command is 0x44.
So if you want to switch on led2 you have to:

STROBE:CLEAR
Send 0x44
SROBE:SET
STROBE:CLEAR
Send 0xC4
Send 0x01
SROBE:SET

Buttons

To read the input value of button, you first have to send the read command.
Read command is 0x42.
Then you set your DATA pin in input mode.
To read you first set CLK.
Then you read on DATA pin.
And clear CLK, and again… to read 4 bytes of data.
When the byte is read, you can set STROBE.

Returned bytes give you which buttons are pressed (bit to 1 if pressed).
On the first one you have information about button One and Five (S1 and S5) on bit 1 and 5.
On the second one you have information about button Two and Six (S2 and S6) on bit 2 and 6.
On third one it’s Three and Seven (S3,S7) on bit 3 and 7.
And for the last one , information on button four and Eight (S4,S8) on bit 4 and 8.

 

Digits

To control digits you will use the same command as to display Leds: WRITE_SINGLE. But you have to write on odd addresses this time.
The digit is divided in 7 segments + the point.

Here is the bit number which represent a segment. If the position is set to 1, then the segment is light on.

Digits
So to print number 2 on the last digit, you can send:

STROBE:CLEAR
Send 0x44
SROBE:SET
STROBE:CLEAR
Send 0xCE
Send 0x5B (01011011)
STROBE:SET

TM1638 with etl library

Supported MCU

This code has been tested on ESP8266.

Build the driver with etl library

Issue a command

enum class Commands:uint8_t {
    READ = 0x42,
    WRITE_SINGLE = 0x44,
    WRITE_CONSECUTIVE = 0X40,
    ACTIVATE = 0x8f
};

static void issueCommand(Commands cmd) {
    STROBE::clear();
    write(static_cast<uint8_t>(cmd));
    STROBE::set();
}

static void write(uint8_t data) {
    for (auto bitIndex = 0; bitIndex < 8; ++bitIndex) {
        DATA::set((data & (1 << bitIndex)) != 0);
        CLK::pulseHigh();
    }
}

Init method

static void init() {
    STROBE::setOutput();
    CLK::setOutput();
    DATA::setOutput();
    STROBE::set();
    issueCommand(Commands::ACTIVATE);
    reset();
}

Leds

static void setLed(uint8_t ledNumber, uint8_t value) {
    issueCommand(Commands::WRITE_SINGLE);
    STROBE::clear();
    write(0xC1 + (ledNumber << 1));
    write(value);
    STROBE::set();
}

static void setLeds(uint8_t value) {
    for (auto i = 0; i < 8; i++) {
      setLed(i, (value & (1 << i)) != 0);
    }
}

Digits

static void display(uint8_t position, char character) {
    issueCommand(Commands::WRITE_SINGLE);
    STROBE::clear();
    write(0xC0 + (position << 1));
    write(font[character - 32]);
    STROBE::set();
}

 

Buttons

//For esp for the moment
static void setInputHandler(voidFuncPtrTM1638 handler) {
    static os_timer_t timer;
    inputHandler = handler;
    os_timer_setfn(&timer, refresh, NULL);
    os_timer_arm(&timer, 1, 1);
}

static void refresh(void* arg) {
    uint8_t key;
    inputHandler(readKey());
}

static uint8_t readKey() {
    STROBE::clear();
    write(static_cast<uint8_t>(Commands::READ));
    DATA::setInput();
    uint8_t buttons = 0;
    for (auto bitIndex = 0; bitIndex < 4; ++bitIndex) {
        auto byteRead = read();
        buttons |= (byteRead << bitIndex);
    }
    DATA::setOutput();
    STROBE::set();
    return buttons;
}

static uint8_t read() {
    uint8_t value = 0;
    for (auto bitIndex = 0; bitIndex < 8; ++bitIndex) {
      CLK::set();
      value |= DATA::read() << bitIndex;
      CLK::clear();
    }
    return value;
}

Using the driver

Setup

etl::TM1638<etl::Pin0, etl::Pin4, etl::Pin5> tm1638;
tm1638.init();

 

Using LEDs

To switch on led 1,2,5 and 8:

tm1638.setLeds(0b10010011);

 

Using digits

Simply use:

 

tm1638.display(0, '0');
tm1638.display(1, '1');
tm1638.display(2, '2');
tm1638.display(3, '3');
tm1638.display(4, '4');

 

Using Buttons

First create an Handler to receive input:

// This one print 1 on digit corresponding to the buttons pressed.
void handler(uint8_t key) {
    if (lastKey != key) {
        etl::TM1638<etl::Pin0, etl::Pin4, etl::Pin5>::resetDisplay();
        for (uint8_t i = 0; i < 8; i++) {
            etl::TM1638<etl::Pin0, etl::Pin4, etl::Pin5>::display(i, (key & (1 << i)) != 0);
        }
        etl::TM1638<etl::Pin0, etl::Pin4, etl::Pin5>::setLeds(key);
        lastKey = key;
    }
}

 

Then set the handler to the TM1638:

tm1638.SetInputHandler((voidFuncPtrTM1638) handler);

 

References

Etl library:

Etl library

An other article on TM1638 but with arduino:

Article Arduino

 

 

 

Publicités

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion /  Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion /  Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion /  Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion /  Changer )

Connexion à %s