Le TM1637

L’aspect le plus important du MAX7219 est de pouvoir être contrôlé par un bus compatible SPI, QSPI et MICROWIRE.
Il n'utilise que trois fils pour la communication, pour un affichage sur de multiples leds.

Le TM1637


Le TM1637 permet de commander 8 digits

Transmission des données série du TM1637
Par défaut le délai entre chaque bit est de 20μs
Pour afficher les segments : TM1637.inc
.equ TM1637_CLK=PB0     ;PB0 TM1637 CLK
.equ TM1637_DIO=PB1     ;PB1 TM1637 DIO
.equ TM1637_Delay=20    ;20us
#define TM1637_COMM1    0x40
#define TM1637_COMM2    0xC0
#define TM1637_COMM3    0x80
;
;      A
;     ---
;  F |   | B
;     -G-
;  E |   | C
;     ---
;      D
;                 XGFEDCBA
#define SEG_A   0b00000001
#define SEG_B   0b00000010
#define SEG_C   0b00000100
#define SEG_D   0b00001000
#define SEG_E   0b00010000
#define SEG_F   0b00100000
#define SEG_G   0b01000000
#define SEG_DP  0b10000000
#define minus   0b01000000
#define deg     SEG_A|SEG_B|SEG_F|SEG_G
TM1637_parametre:
;digitToSegment: ;0123456789AbCdEF-° segments XGFEDCBA
.db 0b00111111,0b00000110,0b01011011,0b01001111,0b01100110,0b01101101,0b01111101,0b00000111
.db 0b01111111,0b01101111,0b01110111,0b01111100,0b00111001,0b01011110,0b01111001,0b01110001
;digits:
    .db 0,1,2,3
;segment:
    .db SEG_A|SEG_E|SEG_F|SEG_D,SEG_A|SEG_D,SEG_A|SEG_D,SEG_A|SEG_B|SEG_C|SEG_D
;brightness,pos:    
    .db     0x0f,0

TM1637_finparametre:

TM1637_Setup:
    ldi     XL,low(TM1637_paramRam)
    clr     XH
    ldi     ZL,low(TM1637_parametre<<1)
    ldi     ZH,high(TM1637_parametre<<1)
    rjmp    recup_param
bcl_recup:
    lpm     regA,Z+        ; [0x0060]=[param]
    st      X+,regA        ; 
recup_param:
    cpi     ZL,(TM1637_finparametre)<<1
    brne    bcl_recup
    ;Set the pin direction and default value.
    ;Both pins are set as inputs, allowing the pull-up resistors to pull them up
    cbi     DDRB,TM1637_CLK     ;INPUT
    cbi     DDRB,TM1637_DIO     ;INPUT
    cbi     PORTB,TM1637_CLK    ;LOW
    cbi     PORTB,TM1637_DIO    ;LOW
    ret

TM1637_start:
    sbi     DDRB,TM1637_DIO     ;OUTPUT
    rcall   delay
    ret

TM1637_stop:
    sbi     DDRB,TM1637_DIO     ;OUTPUT
    rcall   delay
    cbi     DDRB,TM1637_CLK     ;INPUT
    rcall   delay
    cbi     DDRB,TM1637_DIO     ;INPUT
    rcall   delay
    ret

TM1637_writeByte:
;Write byte in RegA
    push    regB
    ldi     regB,8      ;8 data bits, no parity
SendBits:
    sbi     DDRB,TM1637_CLK     ;OUTPUT CLK to zero
    rcall   delay
    lsr     regA
    brcc    SendBits0           ; si carry=0 I2CSendBits0
    cbi     DDRB,TM1637_DIO     ;INPUT to high
    rjmp    SendBits1
SendBits0:
    sbi     DDRB,TM1637_DIO     ;OUTPUT to low
SendBits1:
    rcall   delay
    cbi     DDRB,TM1637_CLK     ;INPUT CLK to high
    rcall   delay
    dec     regB
    brne    SendBits
;Wait for acknowledge
    sbi     DDRB,TM1637_CLK     ;OUTPUT CLK to zero
    cbi     DDRB,TM1637_DIO     ;INPUT
    rcall   delay
    cbi     DDRB,TM1637_CLK     ;INPUT CLK to high
    rcall   delay
    sbis    DDRB,TM1637_DIO     ;test ACK
    sbi     DDRB,TM1637_DIO     ;OUTPUT
    rcall   delay
    sbi     DDRB,TM1637_CLK     ;OUTPUT CLK to zero
    rcall   delay
    pop     regB
    ret

delay:
    ldi     XH, HIGH(C4PUS*TM1637_Delay)    
    ldi     XL, LOW(C4PUS*TM1637_Delay)
    rcall   Wait4xCycles    ;100us

    ret
;______________________________________________
;TM1637_encodeDigits
;Encode Digits dans Segments
;Input : None
;Output: Display
;______________________________________________
TM1637_encodeDigits:
    push    ZH
    push    ZL
    push    YH
    push    YL
    push    XH
    push    XL
    ;rcall  TM1637_Clear
    ldi     ZL,low(digits)
    ldi     ZH,high(digits)
    ldi     XL,low(segment)
    ldi     XH,high(segment)
    ldi     regB,4
    ldi     ZL,low(digits)
    ldi     ZH,high(digits)
blc_encode:
    ld      regA,Z+
    ldi     YL,low(digitToSegment)
    ldi     YH,high(digitToSegment)
    add     YL,regA
    ld      regA,Y
    st      X+,regA
    dec     regB
    brne    blc_encode
    pop     XL
    pop     XH
    pop     YL
    pop     YH
    pop     ZL
    pop     ZH
    ret
;______________________________________________
;TM1637_leading_zero:
;______________________________________________
TM1637_leading_zero:
    ldi     XL,low(segment)
    ldi     XH,high(segment)
leading_zero:
    ld      regA,X+
    cpi     regA,0b00111111 ;segment pour 0
    brne    fin_leading_zero
    dec     XL
    st      X,zero
    inc     XL
    rjmp    leading_zero

fin_leading_zero:
    ret
;______________________________________________
;TM1637_SetSegment
;Display all segment
;______________________________________________
TM1637_SetSegment:
    push    ZH
    push    ZL
    ;Write COMM1
    rcall   TM1637_start
    ldi     regA,TM1637_COMM1
    rcall   TM1637_writeByte
    rcall   TM1637_stop
    
    ;Write COMM2 + first digit address
    rcall   TM1637_start
    lds     regA,pos
    andi    regA,0x03
    ori     regA,TM1637_COMM2;
    rcall   TM1637_writeByte

    ldi     ZL,segment
    clr     ZH
    ldi     regB,4
fourchar:
    ld      regA,Z+
    rcall   TM1637_writeByte
    dec     regB
    brne    fourchar
    rcall   TM1637_stop

    ;Write COMM3 + brightness
    rcall   TM1637_start
    lds     regA,brightness
    ori     regA,TM1637_COMM3;
    rcall   TM1637_writeByte
    rcall   TM1637_stop
    pop     ZL
    pop     ZH
    ret
Programme de test : Test.asm
; Matériel :    ATtiny 85 20MHz 5V
;                        ATtiny85
;                         +-\/-+
;                    PB5 1|-  -|8  Vcc
;            dispo - PB3 2|-  -|7  PB2 - 
;            dispo - PB4 3|-  -|6  PB1 - TM1637_DIO
;                    GND 4|-  -|5  PB0 - TM1637_CLK
;                         +----+
; TM1637.asm
;
; Created: 13/02/2020 18:22:18
; Author : samuel.dupre
;
#define F_CPU 20000000 ;20MHz
.cseg   
.include "tn85def.inc"
.def zero   = r10
.def temp   =r9
.def regA   = R16       ; GENERAL PURPOSE ACCUMULATOR
.def DATA   = R18       ; Data pulseLengthInTicks

.def regB   = R21       ; GENERAL PURPOSE ACCUMULATOR
.def regC   = R20       ; GENERAL PURPOSE ACCUMULATOR
.def    VH      =r25    
.def    VL      =r24
.def    WH      =r23    ;min
.def    WL      =r22    ;sec

.org 0x0000

   rjmp  RESET_vect        ;  Reset Handler   
   reti        ;External Interrupt 0
   reti        ;Pin change Interrupt Request 0
   reti        ;Timer/Counter1 Compare Match 1A
   reti        ;Timer/Counter1 Overflow
   reti        ;Timer/Counter0 Overflow
   reti        ;EEPROM Ready
   reti        ; 
   reti        ;  
   reti        ; 
   reti        ;  
   reti        ;  
   reti        ;
   reti        ; 
   reti        ;

.include "wait.inc"
.include "TM1637.inc"
.include "hex2dec.inc"

RESET_vect:
    clr     zero
    ldi     regA, LOW(RAMEND)  ;Setup of stack pointer 0x15F t45/0x25F t85
    out     SPL, regA
    ldi     regA, HIGH(RAMEND)
    out     SPH, regA

    ldi     regA,0b10000000     ;Attention, ces 2 instructions sont importantes 
                                ;pour le changement de fréquence (sécurité AVR)
    out     CLKPR,regA
    ldi     regA,0b00000000     ;divise par 1 le clock RC de 20MHz, donc 20MHz
    out     CLKPR,regA
    
    ;Eteint le CAN
    cbi     ADCSRA, ADEN        ;switch Analog to Digitalconverter OFF
    rcall   TM1637_Setup
    rjmp    test
loop:
    rcall   TM1637_SetSegment       ;Affiche
    ldi     regA,2
    rcall   waitseconds

    clr     regA
    sts     digits,regA             ;0
    ldi     regA,4
    sts     digits+1,regA           ;4
    dec     regA
    sts     digits+2,regA           ;3
    dec     regA
    sts     digits+3,regA           ;2

    rcall   TM1637_encodeDigits     ;0432
    rcall   TM1637_leading_zero     ;_432
    rcall   TM1637_SetSegment       ;Affiche

    ldi     regA,2
    rcall   waitseconds
    ldi     regA,minus              ;-
    sts     segment,regA
    rcall   TM1637_SetSegment       ;Affiche -432

    ldi     regA,2
    rcall   waitseconds

    ldi     regA,1
    sts     digits,regA         ;1
    sts     digits+1,regA       ;1
    sts     digits+2,regA       ;3
    ldi     regA,8
    sts     digits+3,regA       ;8
    rcall   TM1637_encodeDigits ;1138
    lds     regA,segment+1
    ori     regA,SEG_DP
    sts     segment+1,regA
    rcall   TM1637_SetSegment   ;11:38

    ldi     regA,1
    rcall   waitseconds

    lds     regA,segment+1
    andi    regA,~SEG_DP
    sts     segment+1,regA
    rcall   TM1637_SetSegment   ;11:38

    ldi     regA,1
    rcall   waitseconds

    lds     regA,segment+1
    ori     regA,SEG_DP
    sts     segment+1,regA
    rcall   TM1637_SetSegment   ;11:38

    ldi     regA,1
    rcall   waitseconds

    lds     regA,segment+1
    andi    regA,~SEG_DP
    sts     segment+1,regA
    rcall   TM1637_SetSegment   ;11:38

    ldi     regA,1
    rcall   waitseconds

    lds     regA,segment+1
    ori     regA,SEG_DP
    sts     segment+1,regA
    rcall   TM1637_SetSegment   ;11:38

    ldi     regA,1
    rcall   waitseconds

    clr     regA
    sts     digits,regA         ;0
    ldi     regA,2
    sts     digits+1,regA       ;2
    ldi     regA,8
    sts     digits+2,regA       ;8
    sts     digits+3,regA       ;0

    rcall   TM1637_encodeDigits
    rcall   TM1637_leading_zero     ;_30°
    ldi     regA,deg
    sts     segment+3,regA
    rcall   TM1637_SetSegment       ;Affiche

    ldi     regA,2
    rcall   waitseconds

    clr     regA
    sts     digits,regA         ;0
    ldi     regA,1
    sts     digits+1,regA       ;1
    ldi     regA,4
    sts     digits+2,regA       ;4
    sts     digits+3,regA       ;0

    rcall   TM1637_encodeDigits
    ldi     regA,minus          ;-140
    sts     segment,regA
    ldi     regA,deg
    sts     segment+3,regA      ;-14°
    rcall   TM1637_SetSegment       ;Affiche
    ldi     regA,2
    rcall   waitseconds

    ldi     regA,0x0A
    sts     digits,regA         ;A
    ldi     regA,0x0B
    sts     digits+1,regA       ;B
    ldi     regA,0x0C
    sts     digits+2,regA       ;C
    ldi     regA,0x0F
    sts     digits+3,regA       ;F
    rcall   TM1637_encodeDigits
    rcall   TM1637_SetSegment       ;Affiche AbCF
    ldi     regA,2
    rcall   waitseconds

    ;Affiche rapidement de 9999 à 0
test:

    ldi     WH,high(9999)
    ldi     WL,low(9999)
bcl_9999:
    rcall   BIN2DCB16
    rcall   TM1637_encodeDigits
    rcall   TM1637_SetSegment       ;Affiche AbCF
    ldi     regA,20
    rcall   WaitMiliseconds
    subi    WL, 1
    sbc    WH, zero
    brne    bcl_9999
    rjmp    loop

.dseg
    .org 0x60
TM1637_paramRam:

digitToSegment:
    .byte 16
digits:
    .byte 4
segment:
    .byte 4
brightness: 
    .byte 1
pos:
    .byte 1

.eseg
.db "sammy76.free.fr TM1637 "
conversion hexa 16 bits (jusqu'a 9999) en décimal hex2dec.inc"
;16-bit unsigned binary integer to 8-bit BCD in AVR ASM for ATtiny
;9999-0
;Entrée : WH:WL
BIN2DCB16:
        push    WH
        push    WL
        ldi     ZL,low(digits)
        ldi     ZH,high(digits)
        ldi     regA, -1
_bib2:  inc     regA
        subi    WL, low(1000)
        sbci    WH, high(1000)
        brcc    _bib2
        st      Z+,regA
        ldi     regA, 10
_bib3:  dec     regA
        subi    WL, low(-100)
        sbci    WH, high(-100)
        brcs    _bib3
        st      Z+,regA
        ldi     regA, -1
_bib4:  inc     regA
        subi    WL, 10
        brcc    _bib4
        st      Z+,regA
        subi    WL, -10
        st      Z,WL
        pop     WL
        pop     WH
        ret