I/O Expander met I2C

Bedankt Arco,

Heb dit eraan toegevoegd maar mijn ledje brandt spijtig genoeg nog altijd niet :/
Ik heb in de bijlage mijn code geplaatst.
Alles van mijn code werkt en is getest buiten het I2C gedeelte werkt niet( het aan en uit zetten van led1)
In mijn programma is het de bedoeling dat als mijn PIC via zijn USB poort, LED1_ON ontvangt deze LED aangezet word.
Mijn LED1 is aangestoten op de IO EXPANDER. Namelijk op de eerst IO pin van mijn IO expander.

Kan je me verder helpen?

Arco

Special Member

In je code missen nog steeds registers 0x18...0x1C zo te zien... ;)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Op 15 maart 2017 13:01:23 schreef Arco:
In je code missen nog steeds registers 0x18...0x1C zo te zien... ;)

Bedankt Arco,

Aangezien ik al mijn poorten wens te gebruiken als output heb ik gebruik gemaakt van de registers 0x08h tot OxOch en dan deze dat ik hoog wens aan sturen met een 1.
Of is dit niet correct? Waarom moet ik de registers 0x18 tot 0x1C er nog aan toevoegen?

Arco

Special Member

Lees de datasheet eens, dat helpt... ;)
Die registers zijn voor het zetten van de pins als output; default is (zoals meestal gebruikelijk) een input.

[edit]: dat klopt...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Ik denk dat ik mee ben Arco.

Ik moet eerst de adhv de register 0x18 tot en met 0x1C aangeven dat ik mijn poorteb wens te gebruiken als outputs.
En dan met 0x08h tot OxOCh of ik ze hoog of laag wens te maken.

Correct?

c code:



#include<p18f4550.h>
#include "i2c.h"

...

void main(void) {

TRISBbits.RB1 = 1;
TRISBbits.RB0 = 1;

OpenI2C (MASTER, SLEW_OFF);
....
if(g_fromHostToDeviceBuffer[1] == LED1_ON) {
				IdleI2C();                         // Wait until the bus is idle
				StartI2C();                       // Send START condition

				IdleI2C();                         // Wait for the end of the START condition
				WriteI2C( 0x40 );  		// Send address from slave with R/W cleared for write (0100 0000)


				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x18 );            // Write adress from command register (0000 1000)
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x00 );            // Write data for the command register
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x19 );             // Write adress from command register (0000 1001)
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x00 );            // Write data for the command register
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x1A );             // Write adress from command register (0000 1010)
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x00 );            // Write data for the command register
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x1B );            // Write adress from command register (0000 1011)
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x00 );            // Write data for the command register
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x1C );             // Write adress from command register (0000 1100)
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x00 );            // Write data for the command register


				IdleI2C();                         	// Wait for ACK
				WriteI2C( 0x08 );               	// Write adress from command register (0000 1000)
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0xFF );               	// Write data for the command register
				IdleI2C();                         	// Wait for ACK
				WriteI2C( 0x09 );               	// Write adress from command register (0000 1001)
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x00 );               	// Write data for the command register
				IdleI2C();                         	// Wait for ACK
				WriteI2C( 0x0A );               	// Write adress from command register (0000 1010)
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x00 );               	// Write data for the command register
				IdleI2C();                         	// Wait for ACK
				WriteI2C( 0x0B );               	// Write adress from command register (0000 1011)
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x00 );               	// Write data for the command register
				IdleI2C();                         	// Wait for ACK
				WriteI2C( 0x0C );               	// Write adress from command register (0000 1100)
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x00 );               	// Write data for the command register
				IdleI2C();                         // Wait for ACK
				StopI2C();
		} else if(g_fromHostToDeviceBuffer[1] == LED1_OFF) {
				IdleI2C();                         // Wait until the bus is idle
				StartI2C();                       	// Send START condition

				IdleI2C();                         	// Wait for the end of the START condition
				WriteI2C( 0x40 );  				 	// Send address from slave with R/W cleared for write (0100 0000)


				IdleI2C();                         	// Wait for ACK
				WriteI2C( 0x18 );               	// Write adress from command register (0000 1000)
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x00 );               	// Write data for the command register
				IdleI2C();                         	// Wait for ACK
				WriteI2C( 0x19 );               	// Write adress from command register (0000 1001)
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x00 );               	// Write data for the command register
				IdleI2C();                         	// Wait for ACK
				WriteI2C( 0x1A );               	// Write adress from command register (0000 1010)
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x00 );               	// Write data for the command register
				IdleI2C();                         	// Wait for ACK
				WriteI2C( 0x1B );               	// Write adress from command register (0000 1011)
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x00 );               	// Write data for the command register
				IdleI2C();                         	// Wait for ACK
				WriteI2C( 0x1C );               	// Write adress from command register (0000 1100)
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x00 );               	// Write data for the command register


				IdleI2C();                         	// Wait for ACK
				WriteI2C( 0x08 );               	// Write adress from command register (0000 1000)
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x00 );               	// Write data for the command register
				IdleI2C();                         	// Wait for ACK
				WriteI2C( 0x09 );               	// Write adress from command register (0000 1001)
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x00 );               	// Write data for the command register
				IdleI2C();                         	// Wait for ACK
				WriteI2C( 0x0A );               	// Write adress from command register (0000 1010)
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x00 );               	// Write data for the command register
				IdleI2C();                         	// Wait for ACK
				WriteI2C( 0x0B );               	// Write adress from command register (0000 1011)
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x00 );               	// Write data for the command register
				IdleI2C();                         	// Wait for ACK
				WriteI2C( 0x0C );               	// Write adress from command register (0000 1100)
				IdleI2C();                         // Wait for ACK
				WriteI2C( 0x00 );               	// Write data for the command register
				IdleI2C();                         // Wait for ACK
				StopI2C();
		} else {
			// should never get here
		}
}

Dit is nu mijn code maar nog steeds geen werking.

Is mijn eerste maal met I2C daarmee dat het wat moeilijk is voor mij.

Eesr en vooral verstuur ik het slave adres.
Daarna zet ik al mijn IO's al output

Arco

Special Member

Dit kan zo ook niet werken. Je kunt niet:

code:

[addres] > [register] > [data] > [register] > [data] ...

versturen. Hoe moet de expander dan weten wat een registeradres en wat data is?
Na de eerste 0x40, 0x18 wordt de hele bups die daarna komt naar adres 0x18 gestuurd...

Je moet iedere keer het adres mee versturen.

code:

[0x40] > [0x18] > [data] > [restart] > [0x40] > [0x19] > [data] > [restart] ..... [stop]

Of autoincrement (bit 7 van registeradres) zetten.

code:

[start] > [0x40] > [0x98] > [data] > [data] > [data] ... [stop]
Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Bedankt ik begin het stilaan te snappen :D

Ik heb het nu op deze manier geprogrammeerd maar het werkt nog steeds niet. Mijn poorten van mijn iO expander staan volgens mij nog allemaal ingesteld op hun default stat als input.

Volgens mij vergeet ik toch ergens iets van initialisatie ofzo, maar geen idee wat.

if(g_fromHostToDeviceBuffer[1] == LED1_ON) {
IdleI2C(); // Wait until the bus is idle
StartI2C(); // Send START condition
IdleI2C(); // Wait for the end of the START condition
WriteI2C( 0x40 ); // Send address from slave with R/W cleared for write (0100 0000)
IdleI2C(); // Wait for ACK
WriteI2C( 0x98 ); // Write adress from command register (1001 1000)
IdleI2C(); // Wait for ACK
WriteI2C( 0x01 ); // Write data for the command register
IdleI2C(); // Wait for ACK
WriteI2C( 0x00 ); // Write data for the command register
IdleI2C(); // Wait for ACK
WriteI2C( 0x00 ); // Write data for the command register
IdleI2C(); // Wait for ACK
WriteI2C( 0x00 ); // Write data for the command register
IdleI2C(); // Wait for ACK
WriteI2C( 0x00 ); // Write data for the command register
IdleI2C(); // Wait for ACK
StopI2C();
} else if(g_fromHostToDeviceBuffer[1] == LED1_OFF) {
IdleI2C(); // Wait until the bus is idle
StartI2C(); // Send START condition
IdleI2C(); // Wait for the end of the START condition
WriteI2C( 0x40 ); // Send address from slave with R/W cleared for write (0100 0000)
IdleI2C(); // Wait for ACK
WriteI2C( 0x98 ); // Write adress from command register (1001 1000)
IdleI2C(); // Wait for ACK
WriteI2C( 0x00 ); // Write data for the command register
IdleI2C(); // Wait for ACK
WriteI2C( 0x00 ); // Write data for the command register
IdleI2C(); // Wait for ACK
WriteI2C( 0x00 ); // Write data for the command register
IdleI2C(); // Wait for ACK
WriteI2C( 0x00 ); // Write data for the command register
IdleI2C(); // Wait for ACK
WriteI2C( 0x00 ); // Write data for the command register
IdleI2C(); // Wait for ACK
StopI2C();
} else {
// should never get here
}

Arco

Special Member

Je stelt nu registers 08...0C niet in, dan blijven alle outputs in hun default state '0'...

[Bericht gewijzigd door Arco op woensdag 15 maart 2017 15:07:21 (31%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Ik heb toch gedaan wat je hier zei?

"[start] > [0x40] > [0x98] > [data] > [data] > [data] ... [stop]" of wat moet ik nog erbij doen?

Arco

Special Member

Dat is het instellen van in of output, je moet natuurlijk ook nog instellen of de pin hoog of laag moet worden (zie ook mijn eerste voorbeeld)

code:


[start] > [0x40] > [0x98] > [data] > [data] > [data] > [data] > [data] > [restart] > [0x40] > [0x88] > [data] > [data] > [data] > [data] > [data] > [stop] 

Als je alleen port 0 wilt instellen:

code:


[start] > [0x40] > [0x18] > [data] > [restart] > [0x40] > [0x08] > [data] > [stop]

Het instellen van in/output hoeft maar 1x te gebeuren. Daarna kun je met:

code:

 [start] > [0x40] > [0x08] > [data] > [stop]   

bits (in dit geval in port 0) aan en uit zetten.

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Bedankt Arco voor je hulp!

Maar werkt nog steeds niet...

if(g_fromHostToDeviceBuffer[1] == LED1_ON) {

IdleI2C(); // Wait until the bus is idle
StartI2C(); // Send START condition
IdleI2C(); // Wait for the end of the START condition
WriteI2C( 0x40 ); // Send address from slave with R/W cleared for write (0100 0000)
IdleI2C(); // Wait for ACK
WriteI2C( 0x98 ); // Write adress from command register (1001 1000)
IdleI2C(); // Wait for ACK
WriteI2C( 0x00 ); // Write data for the command register
IdleI2C(); // Wait for ACK
WriteI2C( 0x00 ); // Write data for the command register
IdleI2C(); // Wait for ACK
WriteI2C( 0x00 ); // Write data for the command register
IdleI2C(); // Wait for ACK
WriteI2C( 0x00 ); // Write data for the command register
IdleI2C(); // Wait for ACK
WriteI2C( 0x00 ); // Write data for the command register
IdleI2C(); // Wait for ACK
StopI2C();

IdleI2C(); // Wait until the bus is idle
StartI2C(); // Send START condition
IdleI2C(); // Wait for the end of the START condition
WriteI2C( 0x40 ); // Send address from slave with R/W cleared for write (0100 0000)
IdleI2C(); // Wait for ACK
WriteI2C( 0x88 ); // Write adress from command register (1001 1000)
IdleI2C(); // Wait for ACK
WriteI2C( 0xFF ); // Write data for the command register
IdleI2C(); // Wait for ACK
WriteI2C( 0x00 ); // Write data for the command register
IdleI2C(); // Wait for ACK
WriteI2C( 0x00 ); // Write data for the command register
IdleI2C(); // Wait for ACK
WriteI2C( 0x00 ); // Write data for the command register
IdleI2C(); // Wait for ACK
WriteI2C( 0x00 ); // Write data for the command register
IdleI2C(); // Wait for ACK
StopI2C();

}

Arco

Special Member

Klopt het adres 0x40 wel? (A0, A1, A2 aan Gnd?)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Jep liggen alle 3 aan GND.

Aan wat zou het kunnen liggen? Ik denk software maar ik weet niet goed wat...

Arco

Special Member

Pull-ups sda/scl aanwezig? (1...2k2 voor 400kHz, 2k2...10k voor 100kHz)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Op mij SCL en SDA? Deze zijn aanwezig, 4K7

Arco

Special Member

SDA en SCL ook niet omgekeerd? (je zou niet de eerste zijn die dat doet... :) )
En /OE pin laag, /RESET hoog?

[Bericht gewijzigd door Arco op woensdag 15 maart 2017 16:10:27 (16%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Juist gecontroleerd en is goed aangesloten.

Zou het zeker geen software fout zijn? In bijlage mijn code.

Ik bekijk nog eens de volledige aansluiting van mijn PCA9505 voor de zekerheid.

Arco

Special Member

Hangt de boel niet ergens in de i2c routines? (kun je controleren door een ledje op de micro zelf aan te steken na de i2c routine)
Dan weet je in ieder geval dat dat goed gaat. (veel libraries hangen als er wat mis gaat in de communicatie)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Het Ledje op de SDA van de PIC plaatsen?

Arco

Special Member

Nee, gewoon op een i/o pin van de processor met serieweerstand. En dan aandoen na verlaten i2c routines.

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Dag Arco,

Ik heb dit zojuist gedaan en de LED brandt, wel wat minder hard dan normaal...

Dag Arco,

Heb je zelf eigenlijk enige ervaring met het schrijven van I2C met PIC processoren, ik denk namelijk dat mijn code grondig verkeerd is en ik heel wat vergeet...
Maar ben er momenteel nog niet uit wat

Arco

Special Member

Ik gebruik I2C en SPI vaak, weinig problemen. (wel met Mikrobasic en Assembly, 'C' kan ik niet erg warm voor lopen... ;) )

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Persoonlijk denk ik dat mijn programma volledig verkeerd is.
Als ik op het internet voorbeelden zoek zie ik heel andere programma's en veel complexer.
Ben je zeker van je stuk van mijn programma?