I2C - Problemen bij het zenden van data

Dit topic is gesloten


Voor een project stuur ik een aantal leds aan met behulp van een led driver (de PCA9552 van NXP). Deze ontvangt zijn commando's van een PIC 16F877A. De zendroutine van I2C werkt ook en de aanstuur codes (om de leds aan/af te zetten) zijn goed.

Het probleem zit bij het zenden. Telkens er voor de zesde keer iets verzonden wordt, krijg ik een foutmelding en ik vindt geen mogelijke oorzaak.

Dus stel ik mijn vraag hier: Wat zouden mogelijke oorzaken kunnen zijn voor deze, eerdere bizarre, fout?

Als er te weinig informatie staat: meldt dat gerust en ik zal zo snel mogelijk meer informatie geven.

Een foutmelding tijdens het runnen?
Ik neem dan aan dat je in een simulator ofzo draait?

Dus welke programmeertaal, welke simulator, welke foutmelding ?

In the beginning there was nothing.... and even that exploded...

Is je I2C routine af?
Daarmee bedoel ik dat je de mogelijke fouten afhandelt, als je geen ack krijgt dan de lijn eens reset (zie datasheet van je slave, kan vaak met enkele keren start-event en stop-event na elkaar te doen), time-outs voorzien, ...

AKA Naftebakje @Tweakers.net --- Zonder dwarsliggers geen spoor

wat is de foutmelding?

Mijn escuses, ik had de foutmelding moeten specifieren. De foutmelding treed op indien de ACK van de slave te lang op zich laat wachten.

Ik neem dan aan dat je in een simulator ofzo draait?

Nee, het is tijdens een test op een protobord.

Daarmee bedoel ik dat je de mogelijke fouten afhandelt

Ik zal de foutafhandeling uitbreiden en zien of de fout blijft optreden.

Ik heb de foutafhandeling uitgebreid (met een reset van de lijn, waarna opnieuw geprobeerd wordt te zenden - dit wordt een drietal keer geprobeerd) maar het probleem is er nog (alleen is er geen foutmelding meer).

Zoals eerder gezegd is het systeem als volgt: Aan een led driver (PCA9552) hangen 8 leds (Common andode en tweekleurig), de led driver wordt aangestuurd door een PIC 16F877A via I2C. Op basis van een schakelaar input bepaalt de PIC de kleur en welke led er moet aangestuurd worden.

Als er voor de zesde keer gestuurd moet worden verandert er niets (geen led die aangaat of een foutmelding). Dit gaat door tot het systeem ver genoeg is om terug te vertrekken vanuit de startpositie. Wat zou een mogelijke oorzaak van deze fout kunnen zijn?

Je krijgt dus geen ACK van de slave. Op welke byte is dat dan?

Zorg dat je NOOIT, NOOIT, NOOIT wat met Versatel Tele2 te maken krijgt!

Op 22 augustus 2007 14:43:11 schreef Marco69:
Je krijgt dus geen ACK van de slave. Op welke byte is dat dan?

Wat bedoel je juist? Het is mij niet echt duidelijk. Doel je op: welke boodschap ik stuur?

Nee, welke byte in je commando...
'Foutmelding' is ook zo lekker vaag... I2C zal zelf geen foutmelding geven hoor...

Zorg dat je NOOIT, NOOIT, NOOIT wat met Versatel Tele2 te maken krijgt!

Op 23 augustus 2007 11:37:58 schreef Marco69:
Nee, welke byte in je commando...
'Foutmelding' is ook zo lekker vaag... I2C zal zelf geen foutmelding geven hoor...

Ik verzend 3 bytes aan data naar de led driver met I2C: een adres (van de led driver), een register adres (welk ik ga aanpassen) en de data die in dat register moet terecht komen.

En de foutmelding die optreed in deze schakeling gebeurd wanneer een ACK uitblijft van de slave.

Met de aanpassingen: doe ik paar start stop condities en dan begint het zenden opnieuw. Dit geeft geen goed resultaat (de leds gaan niet aan) en na een tijd komt het programma terug in zijn startconditie terecht.

Heb je de interne adres grootte ook ingesteld?
Geef je ook aan of het een read of write is?
Doet je interface een automatische stop bit als je start hebt gedaan? Dus stop aan het einde van je transactie.

Ik gebruik I2C om met RTC te communiceren en er zijn 2 varianten waarbij je data verzendt. Da's per byte of een reeks bytes achter elkaar. Bij een reeks byte achter elkaar moet ik zelf een stop bit sturen als ik klaar ben (lijkt me ook logisch achteraf gezien). Per byte zet ik de start en stop register en dan doet de microcontroller de stop zelf.

Dus de eerste 5 keer lukt het wel en de zesde keer niet?

Kun je je stukje source hier laten zien, misschien zien we een programmeerfout.

"Een model dat niet werkt is erg. Veel erger echter is een model dat werkt, maar waarvan niemand weet waarom"

Op 23 augustus 2007 13:21:02 schreef Vraagteken:
[...]

Ik verzend 3 bytes aan data naar de led driver met I2C: een adres (van de led driver), een register adres (welk ik ga aanpassen) en de data die in dat register moet terecht komen.

En de foutmelding die optreed in deze schakeling gebeurd wanneer een ACK uitblijft van de slave.

Met de aanpassingen: doe ik paar start stop condities en dan begint het zenden opnieuw. Dit geeft geen goed resultaat (de leds gaan niet aan) en na een tijd komt het programma terug in zijn startconditie terecht.

Nog een keer... Op welke byte dan?

Zorg dat je NOOIT, NOOIT, NOOIT wat met Versatel Tele2 te maken krijgt!

Op 23 augustus 2007 13:55:26 schreef Nordin:
Heb je de interne adres grootte ook ingesteld?
Geef je ook aan of het een read of write is?

Het adres is 7 bit, altijd write.

Op 23 augustus 2007 13:55:26 schreef NordinDoet je interface een automatische stop bit als je start hebt gedaan? Dus stop aan het einde van je transactie.

Ik generereer een start conditie, 3 bytes zenden en genereer een stop conditie.

Op 23 augustus 2007 13:55:26 schreef NordinIk gebruik I2C om met RTC te communiceren en er zijn 2 varianten waarbij je data verzendt.

De routine is gebaseerd op de datasheet van de leddriver.

Op 23 augustus 2007 14:19:26 schreef Marco69:
[...]Nog een keer... Op welke byte dan?

Het fout lopen: bij de zesde keer zenden wordt enkel het adres gestuurd.

Op 23 augustus 2007 13:55:26 schreef NordinKun je je stukje source hier laten zien, misschien zien we een programmeerfout.

Specifieke voorkeuren of gewoon de hele file? De code is een dikke 440 lijnen (met extra commentaar erboven en eronder).

Gewoon de routine om via I2C de leddriver aan te sturen is genoeg, de rest is irrelevant. Trouwens, is dat in C geprogrammeerd? Want assembler ken ik niet. Maar desondanks kunnen anderen je wellicht helpen als het in assembler geschreven is. Het lijkt me in ieder geval beter om je stukje source hier te plaatsen, kunnen de jongens het voor je bestuderen.

Peace!

"Een model dat niet werkt is erg. Veel erger echter is een model dat werkt, maar waarvan niemand weet waarom"

Op 23 augustus 2007 17:30:37 schreef Nordin:
Gewoon de routine om via I2C de leddriver aan te sturen is genoeg, de rest is irrelevant.

Ok, het is wel in assembler (aangeleerde gewoontes). Ik heb geprobeerd om de code proper weer te geven, de vet aangegeven woorden zijn labels (en worden gebruikt om te springen naar bepaalde routines). Als er vragen zijn rond de code: stel ze gerust (andere opmerkingen rond het oplossen van het probleem zijn ook altijd welkom).

Write
movf Error_cnt, w ; error register herinitialiseren
movwf Error_reg

Writes
bsf STATUS, RP0 ; Naar BANK 1 gaan
bsf SSPCON2, SEN ; START Conditie genereren
call WaitI2C ; Subroutine om te wachten op succesvol aflopen van de I2C operatie

movf Loc_reg, w ; Module adres in W zetten
call SendI2C ; Zend routine oproepen
call WaitI2C ; Wachten
call WaitAck ; Subroutine om te wachten op Ack

movf Con_reg, w ; Control byte in W zetten
call SendI2C
call WaitI2C
call WaitAck

movf Dat_reg, w ; Data byte in W zetten
call SendI2C
call WaitI2C
call WaitAck

bsf STATUS, RP0 ; Naar BANK 1 gaan
bsf SSPCON2, PEN ; STOP Conditie genereren
call WaitI2C ; Wachten

return ; Terugkeren naar oorspronkelijke oproep

WaitAck
bcf STATUS, RP0
movf del16_reg, w ; delay van 16 us voor checken of Ack ontvangen is
movwf TMR0
call TMR
incf Bit_reg, f ; increase timeout counter each time ACK is not received
btfsc Bit_reg, 4
goto FailI2C
bsf STATUS, RP0 ; Naar BANK 1 gaan
btfsc SSPCON2, ACKSTAT ; Testen of de module een ACK heeft gegeven
goto WaitAck ; Blijvan Wachten -> tot max van 256us
bcf SSPCON2, ACKSTAT ; Ack clearen
bcf STATUS, RP0 ; Naar BANK 0 gaan
retlw 0

FailI2C
bsf STATUS, RP0 ; Naar BANK 1 gaan
bsf SSPCON2, PEN ; STOP Conditie genereren
call WaitI2C ; Wachten

bsf SSPCON2, SEN ; START Conditie genereren
call WaitI2C
bsf SSPCON2, PEN ; STOP Conditie genereren
call WaitI2C
bsf SSPCON2, SEN
call WaitI2C
bsf SSPCON2, PEN
call WaitI2C
decfsz Error_reg
goto Writes

bsf PORTC, 2 ; Fout Melden
loop goto loop ; Eternal loop

SendI2C
bcf STATUS, RP0 ; Naar BANK 0 gaan
movwf SSPBUF ; De te verzenden data in I2C buffer register laden
retlw 0 ; Terugkeren naar oproep

WaitI2C
bcf STATUS, RP0 ; Naar BANK 0 gaan
btfss PIR1, SSPIF ; Is deze interrupt gezet?
goto WaitI2C ; Nee, loop terug
bcf PIR1, SSPIF ; Ja, I2C operatie is met succes afgelopen
retlw 0 ; Terugkeren naar oproep

Uit een paar metingen is het voglende gebleken:

1. De data wordt de eerste 5 keer goed verzonden (volgens alle zaken van het protocol)

2. De zesde keer dat er gezend moet worden: het adres van de module komt door, er komt een ACK op en de rest van de data komt niet. Dit is verschillende keren hertest, het resultaat was steeds hetzelfde.

Enige tips?

ik heb ook dat probleem maar dan in flowcode 6

Hugo Welther

Moderator

@dieter159.
Open een eigen topic, nu haal je een bijna 10 jaar oude uit de sloot.

Ik zet hier een slotje op.

Neem het leven niet te serieus - je overleeft het toch niet. Elbert Hubbard (1856-1915)

Dit topic is gesloten