Interfacing RTC 8583 with pic16F877A
Mikrobasic Pro Code
program SEVENSEGMENTRTC
structure TTime
dim year, months, day, hours, minutes, seconds as byte
end structure
dim TimeRead as TTime
byteRead as byte
dim TimeToWrite as TTime
dim i as longword
dim j as longword
dim ss as byte
dim por1 as byte
dim por2 as byte
dim por3 as byte
dim por4 as byte
dim por5 as byte
dim por6 as byte
sub function mask(dim num as longword) as byte
select case num
case 0 result = 0xc0
case 1 result = 0xf9
case 2 result = 0xa4
case 3 result = 0xb0
case 4 result = 0x99
case 5 result = 0x92
case 6 result = 0x82
case 7 result = 0xf8
case 8 result = 0x80
case 9 result = 0x90
end select
end sub
sub procedure interrupt
select case ss
case 0
PORTd = por1
PORTa = %11111
ss = 1
case 1
PORTd = por2
PORTa = %101111
ss = 2
case 2
PORTd = por3
PORTa = %110111
ss = 3
case 3
PORTd = por4
PORTa = %111011
ss = 4
case 4
PORTd = por5
PORTa = %111101
ss = 5
case 5
PORTd = por6
PORTa = %111110
ss = 0
end select
TMR0 = 0
INTCON = $20
T0IF_bit = 0 ' Clear Timer0 interrupt flag Vasiko na kathariseis to flag
end sub
sub procedure Display_Time()
POR4 = mask(TimeRead.minutes div 10)
POR3 = mask(TimeRead.minutes mod 10) or 0x80
POR2 = mask(TimeRead.seconds div 10)
POR1 = mask(TimeRead.seconds mod 10)
POR5 = mask(TimeRead.hours mod 10) or 0x80
POR6 = mask(TimeRead.hours div 10)
end sub
sub procedure ReadTime()
I2C1_start ' issue start signal
I2C1_Wr($A0) ' address PCF8583
I2C1_Wr(2) ' first word address
I2C1_Repeated_Start ' issue repeated start signal
I2C1_Wr($A1) ' address PCF8583 for reading R/W=1
byteRead = I2C1_Rd(1) ' read seconds byte
TimeRead.seconds = (byteRead >> 4)*10 + byteRead and 0x0F ' transform seconds
while I2C1_Is_Idle = 0 ' this lines are not neccessary in new versions
nop ' starting from mikroPascal 6.0.0.1
wend
byteRead = I2C1_Rd(1) ' read minutes byte
TimeRead.minutes = (byteRead >> 4)*10 + byteRead and 0x0F ' transform minutes
while I2C1_Is_Idle = 0
nop
wend
byteRead = I2C1_Rd(0) ' read hours byte
TimeRead.hours = (byteRead >> 4)*10 + byteRead and 0x0F ' transform hours
while I2C1_Is_Idle = 0
nop
wend
I2C1_Stop
end sub
sub procedure sethours
inc(TimeToWrite.hours)
if TimeToWrite.hours>23 then TimeToWrite.hours=0
end if
I2C1_Init(10000) ' initialize full master mode
I2C1_Start ' issue start signal
I2C1_Wr($A0) ' address PCF8583
I2C1_Wr(0) ' start from word at address 0 (configuration word)
I2C1_Wr($80) ' write $80 to config. (pause counter...)
I2C1_Wr(0) ' write 0 to cents word
I2C1_Wr((TimeToWrite.seconds div 10) << 4 + (TimeToWrite.seconds mod 10)) ' write seconds word
I2C1_Wr((TimeToWrite.minutes div 10) << 4 + (TimeToWrite.minutes mod 10)) ' write minutes word
I2C1_Wr((TimeToWrite.hours div 10) << 4 + (TimeToWrite.hours mod 10)) ' write hours word
I2C1_Wr((TimeToWrite.year mod 4) << 6 + (TimeToWrite.day div 10) << 4 +(TimeToWrite.day mod 10))
I2C1_Wr((TimeToWrite.months div 10) << 4 + (TimeToWrite.months mod 10)) ' write weekday/months
I2C1_Stop ' issue stop signal
I2C1_Start ' issue start signal
I2C1_Wr($A0) ' address PCF8530
I2C1_Wr($10) ' start from word at address 16
I2C1_Wr(TimeToWrite.year) ' write year to RAM
I2C1_Stop ' issue stop signal
I2C1_Start ' issue start signal
I2C1_Wr($A0) ' address PCF8530
I2C1_Wr(0) ' start from word at address 0
I2C1_Wr(0) ' write 0 to config word (enable counting)
I2C1_Stop ' issue stop signal
end sub
sub procedure setminutes
inc(TimeToWrite.minutes)
if TimeToWrite.minutes >59 then TimeToWrite.minutes=0
end if
I2C1_Init(10000) ' initialize full master mode
I2C1_Start ' issue start signal
I2C1_Wr($A0) ' address PCF8583
I2C1_Wr(0) ' start from word at address 0 (configuration word)
I2C1_Wr($80) ' write $80 to config. (pause counter...)
I2C1_Wr(0) ' write 0 to cents word
I2C1_Wr((TimeToWrite.seconds div 10) << 4 + (TimeToWrite.seconds mod 10)) ' write seconds word
I2C1_Wr((TimeToWrite.minutes div 10) << 4 + (TimeToWrite.minutes mod 10)) ' write minutes word
I2C1_Wr((TimeToWrite.hours div 10) << 4 + (TimeToWrite.hours mod 10)) ' write hours word
I2C1_Wr((TimeToWrite.year mod 4) << 6 + (TimeToWrite.day div 10) << 4 +(TimeToWrite.day mod 10))
I2C1_Wr((TimeToWrite.months div 10) << 4 + (TimeToWrite.months mod 10)) ' write weekday/months
I2C1_Stop ' issue stop signal
I2C1_Start ' issue start signal
I2C1_Wr($A0) ' address PCF8530
I2C1_Wr($10) ' start from word at address 16
I2C1_Wr(TimeToWrite.year) ' write year to RAM
I2C1_Stop ' issue stop signal
I2C1_Start ' issue start signal
I2C1_Wr($A0) ' address PCF8530
I2C1_Wr(0) ' start from word at address 0
I2C1_Wr(0) ' write 0 to config word (enable counting)
I2C1_Stop ' issue stop signal
end sub
sub procedure MainInit()
ADCON1 = 7
OPTION_REG = $80 'pull up
TMR0 = 0
INTCON = $A0 ' disable PEIE,INTE,RBIE... enable T0IE
TRISA = 0 ' designate porta pins as output
TRISD = 0 ' designate portb pins as output
PORTD = 0 ' make sure that nothing is displayed
PORTA = 0 ' make sure that all segments are off
I2C1_Init(100000) ' initialize I2C
end sub
main:
MainInit()
while true
ReadTime()
Display_Time()
if Button(PORTB, 0,200, 0) then sethours
end if
if Button(PORTB, 1, 200, 0) then setminutes
end if
wend
end.