kaporalu Postat Februarie 9, 2011 Partajează Postat Februarie 9, 2011 Un simplu ceas facut pe EasyPIC5 de la http://www.mikroe.com Scris in mikroBasic Pro. Nu a vrut sa mearga cu pull-up de 10K pe busul I2C Cu 2.2K nu se mai pierde comunicatia (placa are multe trasee lungi, inclusiv PORTC). program clock1 '************************************************ ' Digital clock with PCF8583 on EasyPIC5 board (http://www.mikroe.com) ' ' by KapoRalu, feb.2011 ' ' MCU: PIC16F877A, quartz 8 MHz ' Osc=HS, only Brown Out Detect is ON '************************************************ ' Buttons connected on RB0 and RB1 to GND, pull-up resistors to +5V ' Button RB0: switch berween normal clock display (HH.MM) and seconds display (like "SS) ' * in clock adjust mode, increment hour/min, reset seconds to zero (synchronise) ' Button RB1: Time adjust mode. Each pressing change the next item: ' - first press = adjust hours ' - second press = adjust minutes ' - third = reset seconds to zero (hours/minutes are not affected!) ' - fourth = back to normal clock '*********************************************** ' Date not yet implemented ' No alarms yet ' 24 hours format ' ' Real Time Clock board with PCF8583, connected at PortC. ' I2C lines connected to +5V, with pull up rsistors, 2.2Kohm '***was necessary to use 2K2 to compensate hi-capacitance of lines of EasyPIC5 board '*** with 10Kohm, I2C bus is not working as supposed. ' ' Address pin A0 of PCF8583 (pin3) connected to 0V. ' I2C lines: SCL (pin6 PCF8583) connected to RC3 ' SDA (pin5 PCF8583) connected to RC4 ' Pin7 (INT) of PCF8583 connected to RC2 and pull-up resistor 10Kohm on +5V, RTC board ' Pin7 = 1Hz pulses 50% duty factor (not used here!) ' PCF8583 registers: ' Addr $00: D7 D6 D5 D4 D3 D2 D1 D0 = CONTROL/STATUS ' | | | | | | | | ' | | | | | | | \= Timer Flag (seconds pulses 50% duty factor if ALARM bit is 0) ' | | | | | | \---= Alarm Flag (minutes pulses 50% duty factor if Alarm bit is 0) ' | | | | | \------= Alarm enable bit (0 = disable alarm , 1= enable alarm control) ' | | | | \---------= Mask Flag (0=read locations x05-x06 unmasked, 1=read date/month count directly) ' | | | | ' | | \--+------------= function mode: 00=clock 32768Hz (used in RTC card) ' | | 01=clock 50Hz ' | | 10=event counter mode ' | | 11=test modes ' | \------------------= hold last count flag (0=count, 1=store and hold last count in latches) ' \---------------------= stop counting flag (0=count, 1=stop, reset driver) ' IMPORTANT: D7 need to be 1 (clock stopped) before writing time in registers ' and 0 again to start the clock ' ' Addr $01: D7 D6 D5 D4 D3 D2 D1 D0 = hundredth of seconds ' | | | | | | | | ' | | | | \--+--+--+-= 1/100 seconds, BCD format (0...9) ' \--+--+--+-------------= 1/10 seconds, BCD format (0...9) ' ' Addr $02: D7 D6 D5 D4 D3 D2 D1 D0 = seconds ' | | | | | | | | ' | | | | \--+--+--+-= seconds (units), BCD format (0...9) ' \--+--+--+-------------= seconds (ten's), BCD format (0...9) ' ' Addr $03: D7 D6 D5 D4 D3 D2 D1 D0 = minutes ' | | | | | | | | ' | | | | \--+--+--+-= minutes (units), BCD format (0...9) ' \--+--+--+-------------= minutes (ten's), BCD format (0...9) ' ' Addr $04: D7 D6 D5 D4 D3 D2 D1 D0 = hours ' | | | | | | | | ' | | | | \--+--+--+-= hours (units), BCD format (0...9) ' | | \--+-------------= hour (ten's) , BCD format (0,1 or 2) ' | \-------------------= AM/PM Flag (0=AM, 1=PM) ' \----------------------= hour format (0= 24H format, bit D6 not changed; ' 1= 12H format, bit D6 updated) ' Addr $05: D7 D6 D5 D4 D3 D2 D1 D0 = year/date (day of month) ' | | | | | | | | ' | | | | \--+--+--+-= date (units), BCD format (0...9) ' | | \--+-------------= date (ten's) , BCD format (0...3) ' \--+-------------------= year, BCD format (0...3). Read as "0" if mask flag is 1 (bit D3, Addr x00) ' PCF8583 use only 4 year calendar, 0 is "leap year" (with 29 Feb date) ' years 1,2,3 are "common years" (last day of Feb: 28 ' ' Addr $06: D7 D6 D5 D4 D3 D2 D1 D0 = weekday/month ' | | | | | | | | ' | | | | \--+--+--+-= month (units), BCD format (0...9) ' | | | \-------------= month (ten's), 0 or 1 ' \--+--+----------------= day of week, BCD format (0...6).Read as "0" if mask flag is 1 (bit D3, Addr x00) ' ' To adress the RTC via I2C bus need to use the slave access byte: ' D7 D6 D5 D4 D3 D2 D1 D0 ' 1 0 1 0 0 0 x x ' | | ' | \-= R/nW bit, 1= read command, 0=write command ' \----= A0 (pin3 PCF8583) 0=GND,1=Vcc (to select 1 of 2 slaves present on I2C bus) ' ' How to read data from RTC: ' a) send START signal ' b) write slave address (here is $A0 = %10100000, for pin3-A0 connected to GND) ' c) write register address from where start reading (ex. to start read seconds, address is $02) ' d) send START signal (repeat) ' e) write slave address, bit D0=1 (R/nW 1 = request to READ) ' f1) read seconds (first address = $02) and acknowledge ' f2) read minutes (next address = $03) and acknowledge *** Address is auto-incremented by RTC ' f3) read hours (next address = $04) and acknowledge ' f4) read year/date (next address = $05) and acknowledge ' g) read weekday/month (next address = $06) and ***NOT*** acknowledge (Not ack = end of reading) ' h) send STOP signal ' ' How to write data to RTC: ' a) send START signal ' b) write slave address (here is $A0 = %10100000, for pin3-A0 connected to GND) ' c) write $00 (CONTROL register address) ' d) write $80 (%10000000) = STOP THE CLOCK !!!!! **************************************************** ' e1) write next address ($01 =1/100 of seconds) *** also here, registers are auto-incremented ' e2) write next address ($02 =seconds) ' e3) write next address ($03 =minutes) ' e4) write next address ($04 =hours) ' e5) write next address ($05 =year/date) ' e6) write next address ($06 =week day/month) ' f) send STOP signal ' g) send START signal ' h) write slave address ($A0) ' i) write $00 (CONTROL register address) ' j) write $00 (to reset bit D7) = START THE CLOCK !!! ******************* ' k) send STOP signal (now I2C bus is free, RTC is updated and running) '************************************************************************** ' Here, hardware I2C is used (PIC16F877A) ' For other MCUs without I2C port, use mikroBasic commands: Soft_I2C_... '************************************************************************* ' dim dr, sr, mr, hr as byte 'decimal, sec, min, hrs as read from RTC dim tens, sec, min, hrs as byte 'decimal, sec, min, hrs transformed dim menu as byte 'menu selection 1=clock, 2=seconds dim x, zz, v as byte dim blink as byte 'status of seconds dots 1=on,0=off dim d3, d2, d1, d0 as byte 'digits to be displayed hh:mm dim led as byte[4] 'led is the 7-LED code for each 7-seg display '------------------------------ sub function num2RTC(dim number as byte) as byte 'calc the BCD number to be 'written in RTC result=Dec2BCD(number/10) 'HI digit (tens) result = result << 4 '4 times to left =0000 1010 became 1010 0000 x=Dec2BCD(number mod 10) 'LO digit (units) result=result or x 'the final BCD to be written end sub '--------------------- Reads time and date information from RTC (PCF8583) sub procedure Read_Time() I2C1_Start() 'Issue start signal I2C1_Wr($A0) 'Address PCF8583, see PCF8583 datasheet I2C1_Wr(1) 'Address the config Register I2C1_Repeated_Start() 'Issue repeated start signal I2C1_Wr($A1) 'Address PCF8583 for reading R/W=1 dr=I2C1_Rd(1) 'Read 1/10 seconds byte (1 = reception acknowledged) sr=I2C1_Rd(1) 'Read seconds byte mr=I2C1_Rd(1) 'Read min byte hr=I2C1_Rd(0) 'Read hrs byte (0= finish reading) I2C1_Stop() end sub '--------------------- '---------------------Write time to RTC sub procedure Write_Time() hr = num2RTC(hrs) 'calc. the BCD (to be written) of hours mr = num2RTC(min) 'calc. the BCD of minutes sr = num2RTC(sec) 'calc. the BCD of seconds I2C1_Start() 'Issue start signal I2C1_Wr($A0) 'Address PCF8583, see PCF8583 datasheet I2C1_Wr(0) 'Start from address 0 (configuration memory location) I2C1_Wr(0x80) 'Write 0x80 to configuration memory location (stop counter...) I2C1_Wr(dr) 'Write to cents memory location (as read before, unchanged!) I2C1_Wr(sr) 'Write to seconds memory location I2C1_Wr(mr) 'Write to minutes memory location I2C1_Wr(hr) 'Write to hours memory location I2C1_Stop() 'Issue stop signal I2C1_Start() 'Issue start signal I2C1_Wr($A0) 'Address PCF8530 I2C1_Wr(0) 'Start from address 0 I2C1_Wr(0) 'Write 0 to configuration memory location (enable counting) I2C1_Stop() 'Issue stop signal end sub '------------------------------ '------- Formats date and time (was read as BCD digits from RTC) sub procedure Transform_Time() tens = ((dr and $F0) >> 4) 'tens will be 0...9, used as blink signal sec = ((sr and 0xF0) >> 4)*10 + (sr and 0x0F) ' Transform seconds min = ((mr and 0xF0) >> 4)*10 + (mr and 0x0F) ' Transform mins hrs = ((hr and 0x30) >> 4)*10 + (hr and 0x0F) ' Transform hours blink = ($01 and (not(tens/5))) 'blink signal 1 or 0 end sub '--------------------------------- '--------------------------------- sub function Mask(dim num as byte) as byte ' this function returns masks select case num ' for common cathode 7-seg. display case 0 result = $3F case 1 result = $06 case 2 result = $5B case 3 result = $4F case 4 result = $66 case 5 result = $6D case 6 result = $7D case 7 result = $07 case 8 result = $7F case 9 result = $6F end select end sub '--------------------------- sub procedure Selectmenu() 'choose by key what to display if Button(PORTB,0,100,0) then Delay_ms(100) inc (menu) if menu = 3 then menu = 1 else end if end if select case menu case 1 'normal clock hh:mm d3=hrs/10 led[3]=Mask(d3) if d3 = 0 then 'blank leading zero hours led[3]=0 end if d2=hrs mod 10 led[2]=Mask(d2) d1=min/10 led[1]=Mask(d1) d0=min mod 10 led[0]=Mask(d0) if blink=1 then led[2] = led[2] or $80 'turn ON also decimal point end if case 2 ' display seconds, "ss d1=sec/10 d0=sec mod 10 led[3] = $00 led[2] = $22 led[1]=Mask(d1) led[0]=Mask(d0) end select end sub '--------------------------------------- '------------------ Display on 7-segments sub procedure Display7seg() zz=1 for v = 0 to 3 PORTA = zz 'select the digit PORTD = led[v] 'turn ON LEDs Delay_ms(1) 'how much time digit is ON 'at 1ms, refresh rate is approx 180Hz 'duty factor is approx 20% zz = zz << 1 'select next digit if zz > 8 then 'is the leftmost digit? (RA3) zz = 1 'if yes, go to rightmost (RA0) end if PORTA = 0 PORTD = 0 next v end sub '-------------------------------------- '-------------------------------------- sub procedure Adjust_time() dim adjuster as byte adjuster = 1 'adjuster = 1, adj hours 'adjuster = 2, adj minutes 'adjuster = 3, reset seconds to zero while (adjuster < 4) 'adjuster = 4, back to normal clock Read_Time() ' Read time from RTC(PCF8583) Transform_Time() ' Format date and time' if Button(PORTB,1,100,0) then delay_ms(500) inc (adjuster) end if select case adjuster case 1 'display and adjust hours d3=hrs/10 d2=hrs mod 10 d1=min/10 d0=min mod 10 led[3]=Mask(d3) if d3 = 0 then 'blank leading zero led[3]=0 end if led[2]=Mask(d2) or $80 led[1]=Mask(d1) led[0]=Mask(d0) if (tens.0) then 'fast blinking of hours led[3]=0 led[2]=$80 end if Display7seg() if Button(PORTB,0,50,0) then inc (hrs) if hrs > 23 then hrs=0 end if Write_Time() delay_ms(200) end if case 2 'display and adjust minutes d3=hrs/10 d2=hrs mod 10 d1=min/10 d0=min mod 10 led[3]=Mask(d3) if d3 = 0 then 'blank leading zero led[3]=0 end if led[2]=Mask(d2) or $80 led[1]=Mask(d1) led[0]=Mask(d0) if (tens.0) then 'fast blink of minutes led[1]=0 led[0]=0 end if Display7seg() if Button(PORTB,0,50,0) then inc (min) if min > 59 then min=0 end if Write_Time() delay_ms(200) end if case 3 'display and reset seconds to "0" d1=sec/10 d0=sec mod 10 led[3]=0 led[2]=$22 'display seconds symbol ( " ) led[1]=Mask(d1) led[0]=Mask(d0) if (tens.0) then 'fast blink of sec. symbol led[2]=0 end if Display7seg() if Button(PORTB,0,50,0) then sec = 0 Write_Time() 'write time to RTC immediately delay_ms(500) end if end select wend menu=1 ' back to normal clock display end sub '---------------------------------------------- '------------------ Performs project-wide init sub procedure Init_Main() 'PORTA = digital (here, PIC16F877A MCU!!!!) CMCON = CMCON or $07 ' turn off comparators ADCON1 = ADCON1 or $07 ' turn off analog inputs ADCON1.3 = 0 PORTA = 0 TRISA = 0 TRISB = 255 ' PortB for buttons PORTB = 255 TRISC = $FF PORTC = $FF TRISD = 0 '7-digit LED connected on PortD PORTD = 0 I2C1_Init(100000) 'Init I2C, 100KHz menu = 1 blink=0 zz=1 v=0 tens=0 sec=0 min=0 hrs=0 d3=0 d2=0 d1=0 d0=0 end sub '--------------------- main: Delay_ms(100) Init_Main() ' Perform initialization delay_ms(300) Read_Time() while TRUE ' Endless loop Read_Time() ' Read time from RTC(PCF8583) Transform_Time() ' calc. the time' Selectmenu() ' if PORTB.0 keypress, change display hh:mm or "ss Display7seg() if Button(PORTB,1,100,0) then 'PORTB.1 pressed? delay_ms(500) Adjust_time() end if wend end. Link spre comentariu
picolo Postat Februarie 9, 2011 Partajează Postat Februarie 9, 2011 Salut,In primul rand , cine a scris harababura asta de cod?Este necesara o minima decenta chiar in relatia cu un compilator care accepta la compilare indiferent de modul de prezentare.Inteleg ca lucrezi in basic, dar nici chiar asa.Nu prea cred ca-si vor pierde multi timpul cu ceva prezentat in modul asta.Incearca o indentarea a codului sa inteleaga ceva si niste oameni obisnuiti. Link spre comentariu
kaporalu Postat Februarie 10, 2011 Autor Partajează Postat Februarie 10, 2011 Imi pare rau ca a iesit asa "varza". Este rezultatul lui copy/paste.Atasez si fisierele *.mbas si *.hex Link spre comentariu
Postări Recomandate
Creează un cont sau autentifică-te pentru a adăuga comentariu
Trebuie să fi un membru pentru a putea lăsa un comentariu.
Creează un cont
Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!
Înregistrează un nou contAutentificare
Ai deja un cont? Autentifică-te aici.
Autentifică-te acum