Forum: Compiler & IDEs TWI I2C DOGXL160-7 sehr langsam


von Micha (Gast)


Lesenswert?

Hallo,
Ich habe einen AT90USB1287 mit 8Mhz.
Dazu über I2C ein DOGXL160-7.

Die I2C ist so eingestellt:
TWBR = 0
TWPS = 1

Damit errechnet sich mit

 8000000
----------- = 500000 HZ
16+2*0*4*1

Das Display verträgt bis zu 4000000.
Selbst wen ich denn Quarz gegen 16000000 austausche komme ich mit dieser 
Rechnung nur auf 1Mhz.

Wenn ich jedes Pixel beschreibe, dauert dies ungefähr 7 sek. Bei 
500000Hz.

Ist das normal? oder mache ich was falsch?

Ist der 4Wire SPI Mode schneller ?

Wenn das alles so langsam ist, hat das Display eine Möglichkeit,
komplette seiten in diesem zu speichern? Und dann nurnoch aufzurufen. So 
das man nicht jedesmal alle bits einzeln übertragen muss?

P.S.: Code wie im Forum unter TWI beschrieben.

Vielen Dank

von Marc S. (Gast)


Lesenswert?

zeig doch mal bitte die konkrete Ansteuerung des Displays ( nicht die 
TWI-Standart-Implementation sondern wie du die Daten dahin schickst)!

VG Marc

von Micha (Gast)


Lesenswert?

Danke für die schnelle Antwort.

Wie im Beispielprogramm von der EA Homepage.

1
void LCD(uint8* DATA, uint8 i)
2
{
3
  while(i)
4
  {
5
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);                        //TWSTA = TWI START Condition Bit  
6
while  (!(TWCR & (1<<TWINT)));
7
8
if ((TWSR & 0xF8) != TW_START)
9
  Led0_on();                                                                //Fehlerbehandlung
10
11
TWDR = 0x78;//SLA_W;
12
TWCR = (1<<TWINT) | (1<<TWEN);
13
14
while (!(TWCR & (1<<TWINT)));
15
16
if ((TWSR & 0xF8) != TW_MT_SLA_ACK)
17
  Led0_on();
18
  
19
TWDR = *DATA;
20
TWCR = (1<<TWINT) | (1<<TWEN);
21
22
while (!(TWCR & (1<<TWINT)));
23
24
if ((TWSR & 0xF8) != TW_MT_DATA_ACK)
25
  Led0_on();
26
  
27
  
28
TWCR = (1<<TWINT)|(1<<TWEN)|
29
(1<<TWSTO);
30
31
    DATA++;                         /* Increment the pointer on the array  */
32
    i--;                            /* Decrement the Byte counter  */
33
  }
34
35
return;
36
}

Allso müsste es schneller möglich sein?

von Micha (Gast)


Lesenswert?

Dieser Teil Alle Pixel aus dauert 7 sek!
Erhöhe ich TWBR, dauert das ganze noch länger!
Also ist die Bitrate mit den obrigen einstellung schon auf Maximun. 
richtig?
1
/**************************************************************************************************
2
 * @fn      HalLcd_Clean
3
 *
4
 * @brief   Sets All pixels Off
5
 *
6
 * @param   None
7
 *
8
 * @return  None
9
 **************************************************************************************************/
10
void HalLcd_Clean(void)
11
{
12
  uint8 LcdData[] = {0x00};
13
 
14
  for(uint8 p=0; p<26; p++){                  /* 25  Pages */
15
    for(uint8 c=0; c<160; c++){               /* 160 Columns */
16
      HalLCD_SetPageAddress(0x00 + p);
17
      HalLCD_SetColumnAdress(0x00 + c);       
18
      HalLcd_SendData(LcdData, 1);
19
    }
20
  }
21
}
22
23
24
25
/**************************************************************************************************
26
 * @fn      HalLcd_SendData
27
 *
28
 * @brief   Sends  Data to LCD via 3 wire SPI
29
 *
30
 * @param   uint8* SData - Pointer to the Data to be written to the LCD
31
 *          uint i       - Number of the  Datas  to be written to the LCD
32
 *
33
 * @return  None
34
 **************************************************************************************************/
35
36
void HalLcd_SendData(uint8* SData, uint8 i)
37
38
{
39
  LCD_Data(SData,i);
40
  //P3OUT |=  CD;                                 /* CD High */
41
  //SPI_A0_Send_Data(SData , i);
42
}
43
44
void LCD_Data(uint8* DATA, uint8 i)
45
{
46
  while(i)
47
  {
48
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);                        //TWSTA = TWI START Condition Bit  
49
while  (!(TWCR & (1<<TWINT)));
50
51
if ((TWSR & 0xF8) != TW_START) // Passcaller 00 == 1
52
  Led0_on();                                                                //Fehlerbehandlung
53
54
TWDR = 0x7A;//SLA_W;
55
TWCR = (1<<TWINT) | (1<<TWEN);
56
57
while (!(TWCR & (1<<TWINT)));
58
59
if ((TWSR & 0xF8) != TW_MT_SLA_ACK)
60
  Led0_on();
61
  
62
TWDR = *DATA;
63
TWCR = (1<<TWINT) | (1<<TWEN);
64
65
while (!(TWCR & (1<<TWINT)));
66
67
if ((TWSR & 0xF8) != TW_MT_DATA_ACK)
68
  Led0_on();
69
  
70
  
71
TWCR = (1<<TWINT)|(1<<TWEN)|
72
(1<<TWSTO);
73
74
    DATA++;                         /* Increment the pointer on the array  */
75
    i--;                            /* Decrement the Byte counter  */
76
  }
77
78
return;
79
}

von Peter D. (peda)


Lesenswert?

Micha schrieb:
> Wenn ich jedes Pixel beschreibe, dauert dies ungefähr 7 sek.

I2C ist bis max 400kHz spezifiziert.
Bei 400kHz komme ich auf:
1
160 * 104 * 9/8 / 400kHz = 0,05s pro Bild.
Die 7s gehen also woanders drauf.


Peter

P.S.:
Ich hab mir den Controller nicht angesehen, aber ich gehe mal davon aus, 
daß immer 8 Pixel je Datenbyte gesetzt werden können und die Adresse 
automatisch erhöht wird.

von Marc S. (Gast)


Lesenswert?

Das Problem ist recht simpel:

Anstelle einfach bei 0 Anzufangen und das komplette Display in einem 
Rutsch zu beschreiben adressierst du jedes Byte einzeln und schreibst es 
danach hinein. Richtig schnell wirds nach dem Prinzip, wobei hier SPI 
verwendet wird (lässt sich aber auch auf I²C übertragen):
1
void   LCD_Sende_Kommando(uint8_t Kommando)
2
{
3
  PORT_ClearOutputBit(&PORTB, 3);  // Kommando-Modus
4
  SPIC.DATA = Kommando;      // Kommando senden
5
  while(!SPIC.STATUS){}      // Auf Sendeschluss warten
6
}
7
8
void   LCD_Sende_Daten(uint8_t Daten)
9
{
10
  PORT_SetOutputBit(&PORTB, 3);  // Daten-Modus
11
  SPIC.DATA = Daten;        //Datum senden
12
  while(!SPIC.STATUS){}      //Auf Sendeschluss warten
13
}
14
15
void  LCD_Auffrischen(void)
16
{
17
  PORT_ClearOutputBit(&PORTB, 1);    // Chipselect aktivieren
18
  for(uint8_t Zeile = 0; Zeile < 8; Zeile++)
19
  {
20
    LCD_Sende_Kommando(0xB0 + Zeile);    // Zeile Senden
21
    LCD_Sende_Kommando(0x04);
22
    LCD_Sende_Kommando(0x10);
23
    for(uint8_t Spalte = 0; Spalte < 128; Spalte++)
24
    {
25
      LCD_Sende_Daten(LCD_Ramspiegel[Zeile][Spalte]);
26
    }
27
  }
28
  PORT_SetOutputBit(&PORTB, 1);    // Chipselect deaktivieren
29
}

Dafür brauchst du aber ein Abbild des Displays im RAM !

Ansonnsten ersetz einfach den Verweis auf das Array in der inneren 
For-schleife durch ne Zahl dann siehst du schonmal das prinzip.

von Micha (Gast)


Lesenswert?

Viele Dank.

Man muss nicht nach jeder übertragung ein Stopp senden. Sondern kann 
sofort weitermachen mit dem nächsten Datensatz.

Jetzt werde ich das noch mit einem Abbild erweitern. Dann kann ich die 
ganze Seite mit einmal senden!

Wie ist das jetzt mit diesem Takt?
Wie ihr oben seht beschreibe ich das Taktregister nicht!
Initalisiert wird es mit 0.

Kann man das so lassen? Oder geht da noch mehr?

Habe mich aktuell auf 0,8 sek verbessert.
Die Adresse erhöht das display automatisch.


1
LCD_clean(4160);
2
3
void LCD_clean(uint16 i)
4
{
5
6
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);                        //TWSTA = TWI START Condition Bit  
7
while  (!(TWCR & (1<<TWINT)));
8
9
if ((TWSR & 0xF8) != TW_START) // Passcaller 00 == 1
10
  Led0_on();                                                                //Fehlerbehandlung
11
12
TWDR = 0x7A;//SLA_W;
13
TWCR = (1<<TWINT) | (1<<TWEN);
14
15
while (!(TWCR & (1<<TWINT)));
16
17
if ((TWSR & 0xF8) != TW_MT_SLA_ACK)
18
  Led0_on();
19
   
20
  while(i)
21
  {
22
  
23
TWDR = 0x00;
24
TWCR = (1<<TWINT) | (1<<TWEN);
25
26
while (!(TWCR & (1<<TWINT)));
27
28
if ((TWSR & 0xF8) != TW_MT_DATA_ACK)
29
  Led0_on();
30
    i--;                            /* Decrement the Byte counter  */
31
  }
32
  
33
  
34
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
35
36
37
38
return;
39
}

von Gerhard G. (g_g)


Lesenswert?

Hallo,

schau dir mal den Code (I2C) an, das Display ist in wenigen 
Millisekunden beschrieben!

http://www.basteln-mit-avr.de/atxmega32a4.html#dogxl160

Gruß G.G.

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.