Partage
  • Partager sur Facebook
  • Partager sur Twitter

ATtiny 45 - I²C

    2 février 2014 à 19:11:57

    Bonjour,

    Depuis ce matin je cherche un moyen d'utiliser l'I²C sur un ATtiny45, et la seule chose que j'ai réussi, c'est de faire foirer mon ATtiny (il marche encore mais ne répond plus...).

    Pourtant si j'ai bien compris la datasheet, il suffit de mettre nos données dans USIDR, et puis de pulser SCL.

    Mon code :

    #include <avr/io.h>
    #define F_CPU 8000000UL
    #include <util/delay.h>
    
    #define sdaPin PB0
    #define sclPin PB2
    
    const uint8_t maskUSICR =   ( 0<<USISIE ) |                 // (rw) disable USI Start Condition Interrupt Enable
    							( 0<<USIOIE ) |                 // (rw) disable USI Counter Overflow Interrupt Enable
    							( 1<<USIWM1 ) | ( 0<<USIWM0 ) | // (rw) Two wire mode, not using counter overflow
    							( 0<<USICS1 ) | ( 0<<USICS0 ) | // (rw) Clock select => software clock strobe (USICLK)
    							( 0<<USICLK ) |                 // (-w) Clock strobe
    							( 0<<USITC );                   // (-w) Toggle Port Pin
    
    int main( void ) 
    {
    	DDRB =  ( 1<<sdaPin ) |                                 // SDA output driver enable
    			( 1<<sclPin );                                  // SCL output driver enable
    	
    	USIDR = 0b10110011;
    
    	while ( 1 ) 
    	{
    		// 1. Start condition
    		PORTB |= ( 1<<sclPin ) |                // Set SCL high
    				 ( 1<<sdaPin );                 // Set SDA high
    
    		USIDR = ~USIDR;
    		for(int i = 0; i<8; i++) 
    		{
    			// Shift out next bit
    			USICR = maskUSICR |
    					( 1<<USICLK );                                  // Clock strobe, shift bit out
    			_delay_us( 10 );                                        // Maximum bit rate is 100kbps, 10 microseconds
    
    			// Toggle SCL
    			USICR = maskUSICR |
    					( 1<<USITC );                                   // Set SCL low, Toggle Clock Port Pin
    			_delay_us( 10 );
    		}
    			_delay_ms(100);
    	}
    }

    Je me suis trompé quelque part ?

    Merci d'avance.

    • Partager sur Facebook
    • Partager sur Twitter
    2b||!2b   sqrt(4b²)
      3 février 2014 à 1:22:10

      T'essaye de faire quoi ? de sampler tes bits à la main ? C'est pas le but. Normalement, t'initialise ton I2C, et tu viens juste mettre les octets à lire ou à écrire dans les bons registres, le reste se fait tout seul. Pour releaser la clock, en lisant en diagonal, j'ai vu : "Clearing the Start Condition Flag (USISIF) releases the line.". A priori c'est juste ça qu'il faut faire. Essaye de trouver un code d'exemple sur internet (genre l'impémentation de l'I2C sur arduino), tu comprendras mieux ce qu'il faut faire.

      • Partager sur Facebook
      • Partager sur Twitter
      64kB de mémoire, c'est tout ce dont j'ai besoin
        3 février 2014 à 21:25:42

        Au début c'est ce que je pensais, mais je n'arrive pas lancer la clock, le seul moyen que j'ai trouvé c'est de faire une boucle avec les 8 impulsions (code du haut), mais derrière SDA ne suit pas...

        Donc j'ai tenté comme tu m'a dit, mais il n'y a pas de changement apparent.

        #include <avr/io.h>
        #define F_CPU 8000000UL
        #include <util/delay.h>
        
        #define sdaPin PB0
        #define sclPin PB2
        
        const uint8_t maskUSICR =   ( 0<<USISIE ) |                 // (rw) disable USI Start Condition Interrupt Enable
        							( 0<<USIOIE ) |                 // (rw) disable USI Counter Overflow Interrupt Enable
        							( 1<<USIWM1 ) | ( 0<<USIWM0 ) | // (rw) Two wire mode, not using counter overflow
        							( 0<<USICS1 ) | ( 0<<USICS0 ) | // (rw) Clock select => software clock strobe (USICLK)
        							( 0<<USICLK ) |                 // (-w) Clock strobe
        							( 0<<USITC );                   // (-w) Toggle Port Pin
        
        int main( void )
        {
        	_delay_ms(1000);
        	
        	DDRB =  ( 1<<sdaPin ) |                                 // SDA output driver enable
        			( 1<<sclPin );                                  // SCL output driver enable
        
        	while ( 1 )
        	{
        		PORTB |= ( 1<<sclPin ) |						    // Set SCL high
        				 ( 1<<sdaPin );								// Set SDA high
        				 
        		USIDR = 0b10110011;
        		USISR = USISR & 0b00010000;
        		USICR = maskUSICR | ( 1<<USITC );
        		
        		_delay_us( 10 );
        		
        	}
        }

        ici, SDL reste HAUT et SDA envoie une pulse chaque 10µSec (ce qui à l'air normal).

        Et les codes d'exemples deviennent très rares avec l'arrivé d'arduino et de wire, pour l'instant j'ai trouvé ça et ça, mais je n'arrive pas à comprendre le code fournis par le deuxième...

        • Partager sur Facebook
        • Partager sur Twitter
        2b||!2b   sqrt(4b²)

        ATtiny 45 - I²C

        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
        • Editeur
        • Markdown