Forum: Mikrocontroller und Digitale Elektronik AT91SAM7 I2C multiple write


von Thorsten (Gast)


Lesenswert?

Hallo,

ich implementiere gerade das TWI I2C Interface
1
int I2C_WriteBytes(const AT91PS_TWI pTwi,
2
                   unsigned int     uiSlaveAddr,
3
                   char             *data,
4
                   unsigned int     uiNumOfBytes)
5
{
6
  unsigned int end = 0, status, error=0, Count;
7
  unsigned int iBusy = 0;
8
9
  /* Enable Master Mode */
10
  pTwi->TWI_CR = AT91C_TWI_MSEN;
11
12
  /* Wait until TXRDY is high to transmit */
13
  status = AT91C_BASE_TWI->TWI_SR;
14
  while (!(status & AT91C_TWI_TXRDY))
15
    status = AT91C_BASE_TWI->TWI_SR;
16
17
  /* Set the TWI Master Mode Register */
18
  pTwi->TWI_MMR =  (uiSlaveAddr << 16) & ~AT91C_TWI_MREAD;
19
20
  /* Send the data */
21
  for ( Count=0; Count < uiNumOfBytes ;Count++ )
22
  {
23
    end = 0;
24
    iBusy = 0;
25
    /* Write the data to send into THR. Start conditionn DADDR and R/W bit
26
       are sent automatically */
27
    AT91C_BASE_TWI->TWI_THR = *data++;
28
29
    /* NACK errata handling */
30
    /* Do not poll the TWI_SR */
31
    /* Wait 3 x 9 TWCK pulse (max) before reading TWI_SR */
32
    /* From 400Khz down to 1Khz, the time to wait will be in µs range.*/
33
    I2C_WaitMicroSecond (40) ;
34
35
    while (!end)
36
    {
37
      iBusy++;
38
      status = AT91C_BASE_TWI->TWI_SR;
39
      if ((status & AT91C_TWI_NACK) == AT91C_TWI_NACK)
40
      {
41
        error++;
42
        end=1;
43
      }
44
      /*  Wait for the Transmit ready is set */
45
      if ((status & AT91C_TWI_TXRDY) == AT91C_TWI_TXRDY)
46
        end=1;
47
          
48
      if (iBusy > 100000)
49
        return 9;
50
    }
51
  }
52
53
  /* Wait for the Transmit complete is set */
54
  status = AT91C_BASE_TWI->TWI_SR;
55
  while (!(status & AT91C_TWI_TXCOMP))
56
    status = AT91C_BASE_TWI->TWI_SR;
57
58
  return error;
59
}

Ich möchte jetzt den multiple write mode nutzen. Also START condition, 
Addressbyte, und n-Datenbytes und abschließend die Stop condition. Mein 
Problem ist jetzt, dass jedes einzelne Datenbyte mit der START- und STOP 
condition übertragen wird.
Habe ich noch einen Fehler im Code???

Danke

von gerhard (Gast)


Lesenswert?

hallo,
anbei das examples von atmel, vielleicht hilft das mal.

p.s.: das twi interface des at91sam7s ist etwas "buggy", unbedingt das 
errate im datenblatt ansehen.

gruss
gerhard

von Thorsten (Gast)


Lesenswert?

Hallo Gerhard,

danke, jetzt funzt es.

Gruss

von Thorsten (Gast)


Lesenswert?

Hallo,

ich nutze den oben verlinkten Workaround für das I2C TWI-Interface.
Der Schreibvorgang funktioniert ohne Probleme. Jetzt habe ich aber das 
Problem, dass ich vom I2C Slave lesen möchte. Das funktioniert leider 
nicht. Am Oszi erkennt man, dass das I2C Interface in einer Endlosloop 
ist und permant versucht(I2C-Takt clockt dauerhaft) vom Slave zu lesen.

Anbei male mein Quellcode.
Ist da noch ein Fehler???
1
void I2C_Init(void)
2
{
3
  // Configure TWI PIOs
4
  AT91F_TWI_CfgPIO ();
5
  
6
  // Configure PMC by enabling TWI clock
7
  AT91F_TWI_CfgPMC ();
8
 
9
  // Configure TWI in master mode
10
  AT91F_TWI_Configure (AT91C_BASE_TWI);
11
 
12
  // Set TWI Clock Waveform Generator Register
13
  I2C_SetClock();
14
  
15
  //TWI NACK Bug workaround
16
  AT91F_AIC_ConfigureIt (     AT91C_BASE_AIC,
17
                              AT91C_ID_TWI,
18
                              7,
19
                              AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE,
20
                              dummy_irq);
21
  *AT91C_TWI_IER = (1<<0);
22
  
23
  *AT91C_TWI_CR = AT91C_TWI_MSEN;
24
}
25
26
unsigned char I2C_read(unsigned char dev_adr,                                   // slave address
27
                       unsigned char mem_adr,                                   // internal memory address
28
                       unsigned char *data,                                     // datapointer for the return data
29
                       unsigned int n_byte){                                   // count of bytes to read
30
  unsigned int timeout = 0;
31
  unsigned char counter;
32
  unsigned int  uiByteCounter = 0;
33
  timeout = 0;
34
  
35
  *AT91C_TWI_CR = AT91C_TWI_MSEN;                                                 //Enable the TWI Master Mode
36
  *AT91C_TWI_IADR = mem_adr;                                                    //Set the TWI Slave memory address
37
  *AT91C_TWI_MMR = ((dev_adr<<16)                                               //Slave address
38
                    | AT91C_TWI_MREAD);                                           //Master read mode
39
                    //| AT91C_TWI_IADRSZ_1_BYTE);                                 //Slave internal addtess site 1 byte
40
  *AT91C_TWI_CR = AT91C_TWI_START;                                              //Send the start condition slave address and set read mode
41
  while(!(*AT91C_AIC_IPR & (1<<AT91C_ID_TWI)))                                  //TX Complete TWI irq polling
42
  {                                 
43
    timeout++;
44
    if(timeout >= 10000000){
45
      I2C_stop();
46
      return TWI_TXTIMEOUT;                                                     //Exit on TXCOMP timeout
47
    }
48
  }
49
  I2C_nack_wait();
50
  if(*AT91C_TWI_SR & AT91C_TWI_NACK){                                           //Slave exist and send ACK?
51
    I2C_stop();
52
    return TWI_NACK;                                                            //Exit on NACK
53
  }
54
  counter = 0;
55
  
56
  while(uiByteCounter != n_byte)
57
  {                                                               //Recive
58
    timeout = 0;
59
    while((!(*AT91C_TWI_SR & AT91C_TWI_RXRDY))){                                //Wait for data redady
60
      timeout++;
61
      if(timeout>=1000000){
62
        I2C_stop();
63
        return TWI_TXTIMEOUT_READ;                                              //Exit on RXRDY timeout
64
      }
65
    }
66
    data[uiByteCounter++] = AT91C_BASE_TWI->TWI_RHR;//(unsigned char) *AT91C_TWI_RHR;                                       //Read data
67
    uiByteCounter++;
68
  }
69
  
70
  I2C_stop();
71
  
72
  return 0;
73
}
74
75
static void dummy_irq(void)
76
{
77
  volatile unsigned int uiStatus     = 0;
78
  volatile unsigned int uiDelay      = 0;
79
80
  // signal start of Interrupt Service Routine
81
  uiStatus = AT91C_BASE_AIC->AIC_IVR;
82
  uiStatus = uiStatus;
83
84
  
85
  
86
  // signal end of Interrupt Service Routine
87
  uiStatus = AT91C_BASE_AIC->AIC_EOICR;
88
  uiStatus = uiStatus;
89
}
90
91
Danke und Gruss

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.