MM2(+): TM1637 7-segment clock display


Author Message
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 3210
Posted: 08:54am 13 Feb 2016      

If you want a cheap and cheerful clock display you can't get cheaper than this






These displays use the TM1637 controller which has a i2c-like interface (pullups required on the clock and data leads)

The attached code drives this display using simple bit-banging from Basic (not a CFunction in sight)


option explicit
option default none
dim digittosegment%(15)=(&H3F,&H06,&H5B,&H4F,&H66,&H6D,&H7D,&H07,&H7F,&H6F,&H77,&H7C,&H39,&H47,&H79,&H71)
dim integer m_brightness 'holds the brightness value for the display 0-15 are valid
DIM INTEGER displaydata(3)=(0,0,0,0) 'holds the bit values of the segments to be lit, ordered left to right
const colon=1
const nocolon=0
const noleadingzeros=1
const leadingzeros=0
const TM1637_I2C_COMM1 = &H40
const TM1637_I2C_COMM2 = &HC0
const TM1637_I2C_COMM3 = &H80
'*************************************************************************************************
'
' Test / demo program
'
dim mytime$ length 8
DIM integer j
TM1637Init(44,1)' initialise the display using pin 44 for the clock and pin 1 for the data
setbrightness(12)' load the brightness into the global variable
setsegments(displaydata()) 'displaydata is set to zeroes so clear the display
mytime$=time$
pause 1000
timer=0
do
if mytime$<>time$ then 'the clock seconds have changed
if val(right$(time$,1)) mod 2 then 'flash the colon each second
converttime(displaydata(),colon,noleadingzeros) 'set the time into the display array including the colon but no leading zeroes
else
converttime(displaydata(),nocolon,noleadingzeros)'set the time into the display array without the colon or leading zeroes
endif
setsegments(displaydata()) 'update the display
mytime$=time$
endif
loop while timer <60000 'update the time over a minute
'
for j=-999 to 1999 step 17 'demo positive and negative numbers without leading zeroes
convertnumber(displaydata(),j,noleadingzeros)
setsegments(displaydata())
next j
for j=-999 to 1999 step 17 'demo positive and negative numbers with leading zeroes
convertnumber(displaydata(),j,leadingzeros)
setsegments(displaydata())
next j
end

'************************************************************************************************

sub TM1637Init(pinClk as integer, pinDIO as integer)
dim integer m_pinClk,m_pinDIO
' Copy the pin numbers
m_pinClk = pinClk
m_pinDIO = pinDIO

' Set the pin direction and default value.
' Both pins are set as inputs, allowing the pull-up resistors to pull them up
pin(m_pinDIO)=0
pin(m_pinClk)=0
setpin m_pinDIO,DIN
setpin m_pinClk,DIN
end sub

sub setBrightness(brightness as integer)
m_brightness = brightness
end sub

sub setSegments(segments() as integer)
local integer k
' Write COMM1
start
writeByte(TM1637_I2C_COMM1)
stop

' Write COMM2 + first digit address
start
writeByte(TM1637_I2C_COMM2)

' Write the data bytes
for k=0 to 3
writeByte(segments(k))
next k
stop

' Write COMM3 + brightness
start
writeByte(TM1637_I2C_COMM3 + (m_brightness AND &H0f))
stop
end sub

sub start
setpin m_pinDIO, DOUT
' bitDelay
end sub

sub stop

setpin m_pinDIO, dout
setpin m_pinClk, DIN
setpin m_pinDIO, DIN
end sub

sub writeByte(b as integer) as integer
local integer i,ack,data = b
' 8 Data Bits
for i=0 to 7
' CLK low
setpin m_pinClk,dout
' Set data bit
if (data and 1) then
setpin m_pinDIO,DIN
else
setpin m_pinDIO,DOUT
endif
' CLK high
setpin m_pinClk, DIN
data = data >> 1
next i

' Wait for acknowledge
' CLK to zero
setpin m_pinClk, dout
setpin m_pinDIO, DIN
' CLK to high
setpin m_pinClk, din
ack = pin(m_pinDIO)
if (ack = 0) then
setpin m_pinDIO, dout
endif
setpin m_pinClk, dout
end sub

function encodeDigit(digit as integer) as integer
encodeDigit=digitToSegment%(digit and &H0f)
end function

sub convertnumber(dd() as integer, n as integer, nolead as integer)
local integer d(2),m
m=abs(n mod 10000)
if n<0 then m=abs(n mod 1000)
d(0)=(m - (m mod 1000))
d(1)=(m - d(0) - (m MOD 100))
d(2)=(m - d(0) - d(1) - (m mod 10))
dd(3)=encodeDigit(m - d(0) -d(1)- d(2))
dd(0)=encodeDigit(d(0)\1000)
dd(1)=encodeDigit(d(1)\100)
dd(2)=encodeDigit(d(2)\10)
if nolead then
if d(0)=0 then
dd(0)=0
if d(1)=0 then
dd(1)=0
if d(2)=0 then
dd(2)=0
endif
endif
endif
if n<0 then
if dd(2)=0 then
dd(2)=64
else
if(dd(1)=0) then
dd(1)=64
else
dd(0)=64
endif
endif
endif
else
IF n<0 then dd(0)= 64
endif
end sub

sub converttime(dd() as integer, displaycolon as integer, nolead as integer) as integer
local integer i=val(left$(time$,2))*100+val(mid$(time$,4,2))
convertnumber(dd(),i,nolead)
if displaycolon then dd(1)=dd(1) OR &H80
end sub




Edited by matherp 2016-02-14