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
zeig doch mal bitte die konkrete Ansteuerung des Displays ( nicht die TWI-Standart-Implementation sondern wie du die Daten dahin schickst)! VG Marc
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?
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 | }
|
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.
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.
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 | }
|
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.