I2C mure: ATmega8 ja TC1321

Collapse
X
 
  • Kellaaeg
  • Show
Clear All
new posts
  • andreie
    Liige
    • 08/2003
    • 1860

    #1

    I2C mure: ATmega8 ja TC1321

    Mure selline, et TC1321 kuulab ainult softis tehtud I2C implementatsiooni, rauas tehtu peale kirtsutab nina ja ütleb NAK.

    Timing'ute pealt ei oska midagi valet välja lugeda.

    Ideid?

    Softis:


    Rauas, 1:


    Rauas, 2:
    If you think education is expensive, try ignorance.
  • raivo
    Liige
    • 01/2002
    • 1005

    #2
    häda ilmselt selles lühikeses SDA pulsis, mis tekib peale 9.takti, sest master ei kasuta siis SDA-d ja slave jõudis ACK pulsi juba lõpetada.
    kas siis M8 TWI on "kiiksuga" ( ma olen kah sellega maadelnud nii et vähe pole) või tõlgendab üks osapool toimuvat REPEATED START'ina. mingit rohtu, kuidas selle lühikese pulsi aegu SDA "0"-s hoida ei oska pakkuda. proovi kasvõi paarsada pF kondet SDA peal, RESTARDI sarnasus peaks kaduma.

    Comment

    • andreie
      Liige
      • 08/2003
      • 1860

      #3
      Uups, olingi probleemist valesti aru saanud. Tänud parandamast.

      Proovin, mis saab.
      If you think education is expensive, try ignorance.

      Comment

      • andreie
        Liige
        • 08/2003
        • 1860

        #4
        Tegin taimeri peale ringi. Kirjutamisel valmistatakse ette bitijada, mida katkestuses on imelihtne siinile paisata.
        If you think education is expensive, try ignorance.

        Comment

        • raivo
          Liige
          • 01/2002
          • 1005

          #5
          vöib ka nii. prosel jöudlust enamasti piisavalt. TWI probleemid on ka
          www.avrfreaks.net foorumis sagedane aruteluteema. ehk leiad sealt miskit seletust. näiteks siin:
          http://www.avrfreaks.net/index.php?name=PN...ewtopic&t=30370

          mulle aga oleks vaja softi, millega mega8 käituks nagu näiteks 24c64 EEPROM, et mingis aadressvahemikus on RAM, teises EEPROM, kolmandas registrid. imelihtne oleks paindlikke I2C seadmeid konfigureerida. vöiks olla C-s, et ka väiksemale/suuremale prosele vöi PICile saaks ymber tösta.

          Comment

          • andreie
            Liige
            • 08/2003
            • 1860

            #6
            Ei ole mul sellist softi...

            avrfreak'ide foorumit kammisin ka, seal oli inimestel TWI probleeme parasjagu, kuigi mitte sellist, mis mul oli. Jäigi kripeldama võimalus, et viga võib olla laua ja tooli vahel...

            Panen enda oma üles, äkki läheb teistelgi tarvis.

            Kood:
            typedef unsigned char u08;
            
            #define	I2C_PORT PORTC
            #define	I2C_DDR 	DDRC
            #define	I2C_PIN 	PINC
            #define	I2C_SCL_PIN 5
            #define	I2C_SDA_PIN 4
            
            /*****************************************************************************/
            /*****************************************************************************/
            /* Maximum number of patterns: 1 start, 2*4*(8+1) data, 3 stop.
             * Total: 76.
             */
            #define	I2C_MAXPATTERNS 76
            static volatile u08	i2c_countdown = 0;
            static volatile u08	i2c_pattern[I2C_MAXPATTERNS]; // number of patterns to play :)
            
            /*****************************************************************************/
            static void
            fill_i2c_pattern(	u08 data,
             	u08** ptrptr)
            {
            	u08	i;
            	u08*	ptr = *ptrptr;
            
            	// Generate ACK bit.
            	*(ptr++) = _BV(I2C_SCL_PIN);
            	*(ptr++) = 0;
            
            	// Generate data bits.
            	for (i=0; i<8; ++i) {
             if (data & 0x01) {
             	*(ptr++) = _BV(I2C_SDA_PIN) | _BV(I2C_SCL_PIN);
             	*(ptr++) = _BV(I2C_SDA_PIN);
             } else {
             	*(ptr++) = _BV(I2C_SCL_PIN);
             	*(ptr++) = 0;
             }
             data >>= 1;
            	}
            
            	*ptrptr = ptr;
            }
            
            /*****************************************************************************/
            static void
            i2c_write(	const u08	addr,
             const u08*	data,
             const u08	size)
            {
            	u08	i;
            	u08*	ptr = i2c_pattern;
            
            	if (i2c_countdown == 0) {
             // 1. stop.
             *(ptr++) = _BV(I2C_SDA_PIN) | _BV(I2C_SCL_PIN);
             *(ptr++) = _BV(I2C_SCL_PIN);
             *(ptr++) = 0;
             // 2. data in reverse.
             for (i=0; i<size; ++i)
             	fill_i2c_pattern(data[size-i-1], &ptr);
             // 3. address
             fill_i2c_pattern(addr << 1, &ptr);
             // 4. start.
             *(ptr++) = _BV(I2C_SCL_PIN);
             i2c_countdown = ptr - i2c_pattern;
            	}
            }
            
            /* and later, somewhere in the timer interrupt (or in my case, ADC interrupt): */
            	/* Next bit of the I2C bitstream, if needed. */
            	if (i2c_countdown > 0) {
             const u08	p = i2c_pattern[--i2c_countdown];
             // Avoid clock ambiguity - SCL first, SDA second.
             I2C_PORT = (I2C_PORT & ~_BV(I2C_SCL_PIN)) | (p & _BV(I2C_SCL_PIN));
             I2C_PORT = (I2C_PORT & ~_BV(I2C_SDA_PIN)) | (p & _BV(I2C_SDA_PIN));
            	}
            If you think education is expensive, try ignorance.

            Comment

            • andreie
              Liige
              • 08/2003
              • 1860

              #7
              Tegin veel ühe, milles tehakse veidi vähem tööd funktsioonis i2c_write ja natukene rohkem tööd katkestuses. Saadab ainult 3 baiti korraga, ei rohkem, ei vähem
              Kood:
              typedef unsigned char u08;
              #define	I2C_PORT PORTC
              #define	I2C_DDR 	DDRC
              #define	I2C_PIN 	PINC
              #define	I2C_SCL_PIN 5
              #define	I2C_SDA_PIN 4
              
              /*****************************************************************************/
              /*****************************************************************************/
              static volatile u08	i2c_countdown = 0;
              static volatile u08	i2c_countdown2 = 0;
              static volatile u08	i2c_bytes[4];
              
              static const u08	bitmasks[8]	PROGMEM	= {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
              
              // Avoid clock ambiguity - SCL first, SDA second.
              #define	i2c_outp(p)	\
              	do { \
               I2C_PORT = (I2C_PORT & ~_BV(I2C_SCL_PIN)) | ((p) & _BV(I2C_SCL_PIN));	\
               I2C_PORT = (I2C_PORT & ~_BV(I2C_SDA_PIN)) | ((p) & _BV(I2C_SDA_PIN));	\
              	} while (0)
              
              /*****************************************************************************/
              /* NOTE NOTE NOTE: this is actually hard-coded to size==3.
               */
              static void
              i2c_write(	const u08	addr,
               const u08*	data,
               const u08	size)
              {
              	u08	i;
              	if (i2c_countdown == 0) {
               i2c_bytes[3] = addr << 1;
               for (i=0; i<3; ++i)
               	i2c_bytes[i] = data[size-i-1];
               i2c_countdown = 76; // 1 start, 2*4*(8+1) data, 3 stop ==> 76 total.
              	}
              }
              
              /* The following code goes somewhere into the timer interrupt. */
              	/* Next bit of the I2C bitstream, if needed. */
              	if (i2c_countdown > 0) {
               u08	byteidx = 0;
               u08	bitidx;
               u08	countdown;
               switch (--i2c_countdown) {
               case 75: /* Start */
               	i2c_outp(_BV(I2C_SCL_PIN));
               	break;
               default: /* Data byte :) */
               	countdown = i2c_countdown - 3;
               	byteidx = countdown / 18;
               	bitidx = countdown - byteidx*18;
               	switch (bitidx) {
               	default: /* Data bit :) */
                if (i2c_bytes[byteidx] & pgm_read_byte(bitmasks + ((bitidx-2) >> 1))) {
                	if (bitidx & 0x01) {
                 i2c_outp(_BV(I2C_SDA_PIN));
                	} else {
                 i2c_outp(_BV(I2C_SDA_PIN) | _BV(I2C_SCL_PIN));
                	}
                } else {
                	if (bitidx & 0x01) {
                 i2c_outp(0x00);
                	} else {
                 i2c_outp(_BV(I2C_SCL_PIN));
                	}
                }
                break;
               	case 1: /* ACK bit 1 */
                i2c_outp(0x00);
                break;
               	case 0: /* ACK bit 0 */
                i2c_outp(_BV(I2C_SCL_PIN));
                break;
               	}
               	break;
               case 2: /* Stop */
               	i2c_outp(0x00);
               	break;
               case 1: /* Stop */
               	i2c_outp(_BV(I2C_SCL_PIN));
               	break;
               case 0: /* Stop */
               	i2c_outp(_BV(I2C_SDA_PIN) | _BV(I2C_SCL_PIN));
               	break;
               }
              	}
              If you think education is expensive, try ignorance.

              Comment

              Working...