PIC16F1826 met HD44780 en PicBasic

In register 2 en 5 zitten bits die niets met de tijd te maken hebben, die moeten worden verwijderd... (century bit, 12/24h bit)

Arco - "Simplicity is a prerequisite for reliability" - www.arcovox.com

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 instructie

pic 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)

Just find out what you like and let it kill you

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.

Just find out what you like and let it kill you

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...

Arco - "Simplicity is a prerequisite for reliability" - www.arcovox.com

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.

De delay hoeft alleen aan het eind, dus na de HBSTOP... (en daar staat 'ie nu juist niet... ;) )

[Bericht gewijzigd door Arco op 11 oktober 2019 00:10:00 (27%)]

Arco - "Simplicity is a prerequisite for reliability" - www.arcovox.com

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.

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.

Just find out what you like and let it kill you

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.

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... ;)

Arco - "Simplicity is a prerequisite for reliability" - www.arcovox.com

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.

Wow, wel een uitdaging voor iemand die net begint...
Nou maar eens kijken hoe ik dat SSPxCON2 register kan uitlezen... :?

Met HBUSIN heb je er sowieso niks aan. (als de boel 'hangt' vallen er geen registers meer uit te lezen...)

Arco - "Simplicity is a prerequisite for reliability" - www.arcovox.com

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?

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

Arco - "Simplicity is a prerequisite for reliability" - www.arcovox.com

Ja, dat werkt, Arco.
Geweldig, bedankt!

Nu kan ik per register gaan bekijken wat er allemaal is vastgelegd!

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?

Klopt, je moet de waarde als hex wegschrijven. (zolang je alleen cijfers gebruikt, wordt dat vanzelf bcd)
In MikroBasic kun je ook dec2bcd() gebruiken...

Arco - "Simplicity is a prerequisite for reliability" - www.arcovox.com

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

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)

Arco - "Simplicity is a prerequisite for reliability" - www.arcovox.com

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.

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 12 oktober 2019 02:55:39 (26%)]

Arco - "Simplicity is a prerequisite for reliability" - www.arcovox.com