Teade

Collapse

Foorumi reeglid.

Foorumi reeglistik on uuendatud. Palume tutvuda ja arvesse võtta.
See more
See less

I2C mure: ATmega8 ja TC1321

Collapse
X
 
  • Filter
  • Kellaaeg
  • Show
Clear All
new posts

    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.

    #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


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

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

      Comment


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

        Comment


          #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


            #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


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