In register 2 en 5 zitten bits die niets met de tijd te maken hebben, die moeten worden verwijderd... (century bit, 12/24h bit)
Special Member
Golden Member
Ook met het programmavoorbeeld van Hadv krijg ik met PicBasic hetzelfde verschijnsel:
Wanneer ik daar een LCD (SSD1306, 1602A, 16*2) bij in zet, dan is het effect van de HBUSIN en HBUSOUT dat de display 'op hol slaat'.
Zelfs het commando CLS werkt dan niet meer als je dat tussen de commando's plaatst.
Het enige dat dan helpt is power off en opnieuw starten.
Er moet toch iets zijn met de combinatie PicBasic-16F1826-LCD-DS3231.
Met MikroBasic werkt het allemaal netjes.
Op 8 oktober 2019 16:13:47 schreef Bavelt:
Ik neem aan dat de instructiepic basic code:
SYMBOL cSec = 0
moet worden aangepast in :
pic basic code:
SYMBOL cSec = dsdata[0]
.
(En alle anderen ook t/m 18)
Anders zou dsdata niet zijn gevuld.
Toch?[...]
Maar welke areg waarden horen nu bij de WriteAreg en ReadAreg?.
In het voorbeeld zijn deze nl ook niet gevuld.
Nee, cSec enzo wordt gebruikt als index voor de tabel dsdata.
Dus als je schrijft DSDATA(cSec) = 7 dan krijgt deze entry de waarde 7.
Dat moet je voor elk register doen. Die registers staan in de datasheet. Je moet in ieder geval éénmalig de datum/tijdregisters schrijven.
Als je een waarde uit een register wil lezen doe je
variabele = ReadAReg(cSec)
Golden Member
Op 9 oktober 2019 13:00:06 schreef hadv:
[...]
Nee, cSec enzo wordt gebruikt als index voor de tabel dsdata.
Dus als je schrijft DSDATA(cSec) = 7 dan krijgt deze entry de waarde 7.
Dat moet je voor elk register doen. Die registers staan in de datasheet. Je moet in ieder geval éénmalig de datum/tijdregisters schrijven.
Als je een waarde uit een register wil lezen doe je
variabele = ReadAReg(cSec)
Maar voor de index gebruik je toch areg?
Het programma crasht na het commando
pic basic code:
dsdata[areg] = HBUSIN
Dat kan ik controleren door de ingebakken display voor en na dit commando.
Die van Na komt niet meer.
pic basic code:
DEVICE = 16F1826
CONFIG1 FOSC_INTOSC, WDTE_OFF, PWRTE_ON, MCLRE_OFF, CP_ON, CPD_OFF, BOREN_OFF, CLKOUTEN_OFF, IESO_ON, FCMEN_ON
CONFIG2 WRT_OFF, PLLEN_OFF, STVREN_ON, BORV_19, LVP_OFF
DECLARE XTAL 32
ALL_DIGITAL true
OSCCON = %11110000 'Oscillator goed zetten voor 32Mhz
SYMBOL rst LATB.3
SYMBOL dta LATB.1
SYMBOL clk LATB.4
'-------------------------------
DECLARE LCD_TYPE 0
DECLARE LCD_DTPIN LATA.0
DECLARE LCD_ENPIN LATB.2
DECLARE LCD_RSPIN LATB.3
DECLARE LCD_LINES 2
DECLARE LCD_INTERFACE 4
SYMBOL DSWrite = %11010000
SYMBOL DSRead = %11010001
SYMBOL cSec = 0
SYMBOL cMin = 1
SYMBOL cHou = 2
SYMBOL cDayNum = 3
SYMBOL cDay = 4
SYMBOL cMon = 5
SYMBOL cYea = 6
SYMBOL cA1M1 = 7
SYMBOL cA1M2 = 8
SYMBOL cA1M3 = 9
SYMBOL cA1M4 = 10
SYMBOL cA2M2 = 11
SYMBOL cA2M3 = 12
SYMBOL cA2M4 = 13
SYMBOL cControl= 14
SYMBOL cStatus = 15
SYMBOL cAge = 16
SYMBOL cTempH = 17
SYMBOL cTempL = 18
DIM areg AS BYTE
DIM dsdata[19] AS BYTE
CLEAR
areg = cSec
GOSUB WriteAreg
areg = cSec
GOSUB ReadAreg
GOTO Einde
WriteAreg:
HBSTART
HBUSOUT DSWrite
HBUSOUT areg
HBUSOUT dsdata[areg]
HBSTOP
RETURN
ReadAreg:
HBSTART
HBUSOUT DSWrite
HBUSOUT areg
HBSTOP
DELAYMS 20
HBSTART
HBUSOUT DSRead
CLS
PRINT AT 1,1, "Voor Dsread"
DELAYMS 1000
dsdata[areg] = HBUSIN
CLS
PRINT AT 1,1, "Na Dsread"
DELAYMS 1000
HBUSNACK
HBSTOP
RETURN
Einde:
END
Zou je misschien je voorbeeld willen aanpassen, voor bijvoorbeeld alleen de seconden? Ik krijg het niet werkend.
pic basic code:
; initieel de tijd en datum vullen
aReg = cMin
DSData[aReg] = 0x12
GoSub WriteAreg
; wat jij doet klopt niet omdat je niet eerst iets in DSDATA[cSec] hebt staan, dat is dus nu 0 en dat is wellicht niet wat je wilt
areg = cSec
GOSUB WriteAreg
; dan, tijdens het programma, de actuele waarde uit de DS3231 lezen
; iMin, iTemp1 en iTmep2 zijn bytes
aReg = cMin
GoSub ReadAreg
iTemp1 = DSData[cMin] & %01110000
iTemp1 = iTemp1 >> 4
iTemp2 = DSData[cMin] & %00001111
iMin = iTemp2 + (10 * iTemp1)
HRSOutLn "min ", Dec2 iMin
Dat HBUSIN niet werkt kan meerdere oorzaken hebben, heb je wel pull-ups op de SDA en SCL lijnen hangen? Het kan ook zijn dat CLS en print de timing verstoren.
Special Member
Als je niet precies weet hoe de i2c library intern precies werkt, is het altijd raadzaam om na een bus read/write een delay van ongeveer 5mS in te lassen.
Dat lost vaak veel problemen op...
Golden Member
heb je wel pull-ups op de SDA en SCL lijnen hangen? Het kan ook zijn dat CLS en print de timing verstoren.
Ja, beide 4K7.
De Hardware is overigens wel Ok, want met het MikroBasic Prorammaatje werkt het allemaal goed.
Met PicBasic helaas nog geen resultaat.
De volledige code:
pic basic code:
DEVICE = 16F1826
CONFIG1 FOSC_INTOSC, WDTE_OFF, PWRTE_ON, MCLRE_OFF, CP_ON, CPD_OFF, BOREN_OFF, CLKOUTEN_OFF, IESO_ON, FCMEN_ON
CONFIG2 WRT_OFF, PLLEN_OFF, STVREN_ON, BORV_19, LVP_OFF
DECLARE XTAL 32
ALL_DIGITAL true
OSCCON = %11110000 'Oscillator goed zetten voor 32Mhz
SYMBOL rst LATB.3
SYMBOL dta LATB.1
SYMBOL clk LATB.4
'-------------------------------
DECLARE LCD_TYPE 0
DECLARE LCD_DTPIN LATA.0
DECLARE LCD_ENPIN LATB.2
DECLARE LCD_RSPIN LATB.3
DECLARE LCD_LINES 2
DECLARE LCD_INTERFACE 4
SYMBOL DSWrite = %11010000
SYMBOL DSRead = %11010001
SYMBOL cSec = 0
SYMBOL cMin = 1
SYMBOL cHou = 2
SYMBOL cDayNum = 3
SYMBOL cDay = 4
SYMBOL cMon = 5
SYMBOL cYea = 6
SYMBOL cA1M1 = 7
SYMBOL cA1M2 = 8
SYMBOL cA1M3 = 9
SYMBOL cA1M4 = 10
SYMBOL cA2M2 = 11
SYMBOL cA2M3 = 12
SYMBOL cA2M4 = 13
SYMBOL cControl= 14
SYMBOL cStatus = 15
SYMBOL cAge = 16
SYMBOL cTempH = 17
SYMBOL cTempL = 18
DIM areg AS BYTE
DIM dsdata[19] AS BYTE
DIM Itemp1 AS BYTE
DIM Itemp2 AS BYTE
DIM IMIN AS BYTE
CLEAR
areg = cMin
dsdata[areg] = $12
GOSUB WriteAreg
areg = cMin
GOSUB ReadAreg
Itemp1 = dsdata[cMin] & %01110000
Itemp1 = Itemp1 >> 4
Itemp2 = dsdata[cMin] & %00001111
IMIN = Itemp2 + (10 * Itemp1)
CLS
PRINT AT 1,1, "Min: ", DEC2 IMIN
;HRSOutLn "min ", Dec2 iMin
GOTO Einde
WriteAreg:
HBSTART
HBUSOUT DSWrite
HBUSOUT areg
HBUSOUT dsdata[areg]
HBSTOP
DELAYMS 5
RETURN
ReadAreg:
HBSTART
HBUSOUT DSWrite
HBUSOUT areg
HBSTOP
DELAYMS 5
HBSTART
HBUSOUT DSRead
dsdata[areg] = HBUSIN
HBUSNACK
HBSTOP
DELAYMS 5
RETURN
Einde:
END
Het commando HRSOutLn geeft geen resultaat op de LCD.
Met het commando "Print" zie je dat de minuten op 00 blijven staan, m.a.w. die worden blijkbaar niet gelezen. Daarbij wat vreemde tekens op willekeurige plekken op de LCD.
Zie foto.
Special Member
De delay hoeft alleen aan het eind, dus na de HBSTOP... (en daar staat 'ie nu juist niet... )
[Bericht gewijzigd door Arco op vrijdag 11 oktober 2019 00:10:00 (27%)
Golden Member
Het kan ook zijn dat CLS en print de timing verstoren
Dat zou betekenen dat het met PicBasic niet mogelijk zou zijn om met een PIC 16F1826 een RTC in te lezen en het resultaat te tonen op een LCD HD44780.
Dan wel dat PICbasic een incorrecte assembler / hex oplevert waar deze PC niet goed mee overweg kan.
Golden Member
De delay hoeft alleen aan het eind, dus na de HBSTOP... (en daar staat 'ie nu juist niet...
Heb ik inmiddels aangepast..Geen effect
Op 11 oktober 2019 00:09:10 schreef Bavelt:
[...]Dat zou betekenen dat het met PicBasic niet mogelijk zou zijn om met een PIC 16F1826 een RTC in te lezen en het resultaat te tonen op een LCD HD44780.
Dan wel dat PICbasic een incorrecte assembler / hex oplevert waar deze PC niet goed mee overweg kan.
Dit is allemaal wel heeeel erg kort door de bocht. Je kunt de gelezen waarden altijd op het display zetten NADAT je de lees transactie hebt voltooid.
Dus...Gosub ReadAReg...print at x,y. In plaats van de print ergens in de subroutine te plakken.
Golden Member
Ik heb de PRINT AT x, y uit de sub gehaald.
Dit is nu het programma
pic basic code:
DEVICE = 16F1826
CONFIG1 FOSC_INTOSC, WDTE_OFF, PWRTE_ON, MCLRE_OFF, CP_ON, CPD_OFF, BOREN_OFF, CLKOUTEN_OFF, IESO_ON, FCMEN_ON
CONFIG2 WRT_OFF, PLLEN_OFF, STVREN_ON, BORV_19, LVP_OFF
DECLARE XTAL 32
ALL_DIGITAL true
OSCCON = %11110000 'Oscillator goed zetten voor 32Mhz
ANSELB = 0 'Alle output/digital
ANSELA = 0
TRISA = 0
TRISB = 0
SYMBOL rst LATB.3
SYMBOL dta LATB.1
SYMBOL clk LATB.4
'-------------------------------
DECLARE LCD_TYPE 0
DECLARE LCD_DTPIN LATA.0
DECLARE LCD_ENPIN LATB.2
DECLARE LCD_RSPIN LATB.3
DECLARE LCD_LINES 2
DECLARE LCD_INTERFACE 4
SYMBOL DSWrite = %11010000
SYMBOL DSRead = %11010001
SYMBOL cSec = 0
SYMBOL cMin = 1
SYMBOL cHou = 2
SYMBOL cDayNum = 3
SYMBOL cDay = 4
SYMBOL cMon = 5
SYMBOL cYea = 6
SYMBOL cA1M1 = 7
SYMBOL cA1M2 = 8
SYMBOL cA1M3 = 9
SYMBOL cA1M4 = 10
SYMBOL cA2M2 = 11
SYMBOL cA2M3 = 12
SYMBOL cA2M4 = 13
SYMBOL cControl= 14
SYMBOL cStatus = 15
SYMBOL cAge = 16
SYMBOL cTempH = 17
SYMBOL cTempL = 18
DIM areg AS BYTE
DIM dsdata[19] AS BYTE
DIM Itemp1 AS BYTE = 0
DIM Itemp2 AS BYTE = 0
DIM IMIN AS BYTE = 0
CLEAR ; Wis RAM geheugen
CLS
PRINT AT 1,1, "Test RTC"
DELAYMS 1000
areg = cSec
dsdata[areg] = %00101000 ; Schrijven seconden in RTC
GOSUB WriteAreg
WHILE 1=1 ; Voordurend lezen van de seconden
areg = cSec
GOSUB ReadAreg
Itemp1 = dsdata[areg] & %01110000
Itemp1 = Itemp1 >> 4
Itemp2 = dsdata[areg] & %00001111
IMIN = Itemp2 + (10 * Itemp1)
;Tonen Resultaat op de LCD (SSD1306 met HD44780)
PRINT AT 2,1, "Sec: ", DEC2 IMIN
;HRSOutLn "min ", Dec2 iMin ; Dit commando geeft geen resultaat op de LCD
DELAYMS 1000
WEND
WriteAreg:
HBSTART ; Schrijven RTC
HBUSOUT DSWrite
HBUSOUT areg
HBUSOUT dsdata[areg]
HBSTOP
DELAYMS 5
RETURN
ReadAreg: ; Lezen RTC
HBSTART
HBUSOUT DSWrite
HBUSOUT areg
HBSTOP
DELAYMS 5
HBSTART
HBUSOUT DSRead
dsdata[areg] = HBUSIN
HBUSNACK
HBSTOP
DELAYMS 5
RETURN
Einde:
END
Maar na het lezen van de RTC gaat het mis.
Zelfs het woordje "SEC" komt niet meer op de Display.
Het commando
pic basic code:
dsdata[areg] = HBUSIN
lijkt nog steeds de boosdoener die de zaak laat crashen.
Special Member
HBUSIN is 'blocking'
Het wacht op een antwoord van de slave. Als dat om een of andere reden niet komt, hangt de boel voor eeuwig vast...
(ze zijn schijnbaar niet zo vriendelijk geweest een errorcheck en/of time-out in te bouwen)
Het zal wel komen door wat er naar de slave gestuurd wordt niet helemaal klopt. Die begrijpt 't niet en geeft geen antwoord...
Er crasht dus niets, de processor staat geduldig op antwoord te wachten...
Om in te haken bij Arco, misschien even controleren of je wel een ACK krijgt van de slave als je het adres hebt geschreven.
In de datasheet staat: "The result of an ACK is placed in the ACKSTAT bit of
the SSPxCON2 register" en op blz 281 (in mijn versie) staat:
"bit 6 ACKSTAT: Acknowledge Status bit (in I2C mode only)
1 = Acknowledge was not received
0 = Acknowledge was received"
Dus als je zeker wilt weten of er wel communicatie is zou ik nu eerst even het ACKSTAT bit controleren nadat je het adres geschreven hebt. Is dit nul dan weet je tenminste dat je met de slave kunt praten.
Golden Member
Wow, wel een uitdaging voor iemand die net begint...
Nou maar eens kijken hoe ik dat SSPxCON2 register kan uitlezen...
Special Member
Met HBUSIN heb je er sowieso niks aan. (als de boel 'hangt' vallen er geen registers meer uit te lezen...)
Golden Member
Om fouten te kunnen opsporen en om de registers goed te begrijpen,
wilde ik per register de binaire waarden weergeven.
In PicBAsic is dat simpel met
pic basic code:
PRINT AT 2, 3, BIN Teller
.
Maar iets gelijkwaardigs heb ik in MikroBasic niet kunnen vinden
Hoe kan ik een byte binair weergeven?
Special Member
Volgens mij is dat er niet standaard, ik heb het nooit nodig gehad. (debuggen doe altijd serieel -> pc)
Maar 't is makkelijk zelf te maken:
pic basic code:
Sub Procedure ByteToBinStr(Dim pByte As Byte, Dim ByRef pStr As String)
Dim lCnt As Byte
For lCnt = 7 To 0 step -1
If pByte.lCnt Then pStr[7-lCnt] = "1" Else pStr[7-lCnt] = "0" End If
Next lCnt
pStr[8] = 0
End Sub
pStr wijst naar een string die minimaal 9 char. lang is
Golden Member
Ja, dat werkt, Arco.
Geweldig, bedankt!
Nu kan ik per register gaan bekijken wat er allemaal is vastgelegd!
Golden Member
Meteen maar weer even vraagje (sorry).
In de Datasheet van de DS3231 lees ik dat het formaat van de seconden/uren etc in BCD is.
Als ik de seconden op 59 wegschrijf dan zie ik dat na uitlezen (en de conversie naar Binair) in het register (00h) staat:
0011 1011 Dit is inderdaad 48 + 11 = 59
Maar als het in BCD zou zijn, dan had er toch moeten staan:
0101 1001
5 9
Waar zit mijn denkfout?
Special Member
Klopt, je moet de waarde als hex wegschrijven. (zolang je alleen cijfers gebruikt, wordt dat vanzelf bcd)
In MikroBasic kun je ook dec2bcd() gebruiken...
Golden Member
zolang je alleen cijfers gebruikt, wordt dat vanzelf bcd)
?
Maar 0011 1011 is toch wat anders dan 0101 1001?
Ik had gedacht bit 7 t/m 4 is de tientallen seconden. dus 5*10 = 0101
Bit 3 t/m 0 is seconden, Dus 9 * 1 = 1001
Samen 0101 1001
Maar in het register staat het binair (0011 1011).
Vat ik even niet
Special Member
Bit 7 doet niet mee. Bit[6:4] zijn tientallen, bit[3:0] eenheden in BCD.
Als je 59 decimaal door dec2bcd() haalt, komt er vanzelf 01011001 uit. (BCD is eigenlijk een WYSIWYG versie van decimaal... )
Wat in eigenlijk bedoelde is dat als je 59 decimaal in BCD wilt, je het ook als 0x59 (hex) kunt schrijven. (is hetzelfde als BCD)
Golden Member
Bit 7 doet niet mee
Klopt, zie ik nu ook.
Je uitleg over Hex/BCD snap ik ook (dank).
Wat ik alleen niet snap, is dat in mijn testprogrammaatje met jouw routine
ByteToBinStr, waarmee ik de waarde in het register binair (dus per bitje) wilde tonen, ik %0011 1011 krijg.
Daar waar ik 0101 1001 had verwacht.
Special Member
Als er 0x3B uit komt, zul je dat er echt ook wel ingestopt hebben...
(je hebt er waarschijnlijk 59 decimaal ingestopt)
[Bericht gewijzigd door Arco op zaterdag 12 oktober 2019 02:55:39 (26%)