XV-TFT2428T am XMega128-A1

Gerri

Neues Mitglied
18. Apr. 2011
22
0
1
Sprachen
Hallo,

nachdem ich das neue Display XV-TFT2428T erhalten habe, möchte ich versuchen es an dem XMega128-A1 Modul zum laufen zu bringen. Dazu habe ich versucht den Beispielcode umzuschreiben.
Dabei ist mir aufgefallen, dass bei der Initialisierung per Software SPI, etwas fehlt. So wie der Code aktuell steht, wird immer das gleiche Bit übertragen.
Ich habe eine Zeile hinzugefügt und schiebe bei jedem Übertragungszyklus "output" jeweils ein Bit weiter.

Ich habe zum nachverfolgen den Code für den ATMega mit drin stehen lassen.


Der abgewandelte Code "Display_SPI.c" sieht wie folgt aus:
Code:
#include <avr/io.h> 
#include <util/delay.h> 
#include "Display_SPI.h"


/*********************************************************************************
 *  SPI Interface
 *********************************************************************************
 *  Microcontroller: AVR Xmega128
 *
 *  SCK   : PF7  (OUTPUT)
 *  MOSI  : PF5  (OUTPUT)
 *  MISO  : PF6  (INPUT)
 *  CS_   : PF4  (OUTPUT)
 *
 *  BUSY_ : PF2 (INPUT, Pullup Resistor activated)
 *  TINT_ : PF3 (INPUT, Pullup Resistor activated)
 *
 *********************************************************************************/
 

//#define SPI_MOSI_SET() PORTB |=  (1<<PB2);
#define SPI_MOSI_SET PORTF.OUTSET = PIN5_bm

//#define SPI_MOSI_CLR() PORTB &=  ~(1<<PB2);
#define SPI_MOSI_CLR PORTF.OUTCLR = PIN5_bm

// #define SPI_CLK_SET() PORTB |=  (1<<PB1)
#define SPI_CLK_SET PORTF.OUTSET = PIN7_bm

//#define SPI_CLK_CLR() PORTB &=  ~(1<<PB1)
#define SPI_CLK_CLR PORTF.OUTCLR = PIN7_bm

//#define SPI_MISO_IS_SET() PINB & (1<<PB3)
#define SPI_MISO_IS_SET PORTF.IN & 0x20			// ist EingangsPIN "PF6" auf high, dann ist die Bedingung erfüllt


//********************************************************************************
// Software SPI an PORTF
// fck max: 2MHz
//********************************************************************************

void SPI_Init(void)
{
  // Port und Direction

  PORTF.DIR &= ~(1<<PIN2);			/* DDRB &= ~(1<<PINB4);*/		// Busy Input Pullup
  PORTCFG.MPCMASK |= (1<<PIN2);		/* PORTB |= (1<<PB4);*/			// Maske setzen
	PORTF.PIN0CTRL = 0x18;			// mit der markierten Maske kann der PIN2 auf PullUP ( Handbuch Seite 142 ) gesetzt werden
	
  // SS\    PF4   OUTPUT
  // SCK    PF7   OUTPUT
  // MOSI   PF5   OUTPUT
  // MISO   PF6   INPUT

	PORTF.DIR |= (1<<PIN4)|(1<<PIN5)|(1<<PIN7);		// PORTB |= (1<<PB2) | (1<<PB1) | (1<<PB0);  // High
	PORTF.OUTSET |= (1<<PIN4) | (1<<PIN7);	// DDRB  |= (1<<PB2) | (1<<PB1) | (1<<PB0);  // Direction Output // hier habe ich MOSI auf low gelassen
	PORTF.DIR &= ~(1<<PIN6);					// DDRB &= ~(1<<PB3);   // MISO Input 

  // TOUCH_
  PORTCFG.MPCMASK |= (1<<PIN3);		// PORTB |= (1<<PB5);  // PINB5 Input mit Pullup  
	PORTF.PIN0CTRL = 0x18;
	
  PORTF.DIR &= ~(1<<PIN3);			//DDRB &= ~(1<<PB5);
  
  _delay_ms(1000);

}



uint8_t SPI_RW (uint8_t output)
{
  uint8_t input;
  uint8_t i;
  uint8_t c_data;
	
	c_data = output;
	
  for (i=0; i<8; i++)
  {

    SPI_CLK_CLR;
		_delay_ms(100);
    if (c_data & 0x80)    // Output MOSI
	{
	  SPI_MOSI_SET;
    } else {
	  SPI_MOSI_CLR;
    }

	c_data = c_data <<1;	// hier Bit schieben, da sonst immer das gleiche Bit gesendet wird
	
	_delay_ms(100);
	
	SPI_CLK_SET;
	_delay_ms(100);
		
    input <<= 1;          // Input MISO
	if (SPI_MISO_IS_SET)
	{
	  input |= 1;
    } else {
	  input &= ~1;
    }

  }
	
	SPI_MOSI_CLR;   // Mosi auf Null, falls das letzte übertragende Bit 1 war
  
  return input;							//return the byte clocked in from SPI slave
}		








uint8_t WaitWhileDisplayBusy_Timeout500ms(void)
{
  uint16_t time;

  time = 50000;					// timeout 500ms
  while (DISPLAY_BUSY)
  {
    time--;
	if (0 == time)
	{
      // Timeout, deselect display spi
	  SPI_SS_HIGH						// timeout
      _delay_us(1);
	  return 0x00;
    }
    _delay_us(10);
  }

  return 0xFF;
}



uint8_t WaitWhileDisplayBusy(void)
{
  uint16_t time;

  time = 10000;					// timeout 50ms

  time = 50000;
  while (DISPLAY_BUSY)
  {
    time--;
	if (0 == time)
	{
      // Timeout, deselect display spi
	  SPI_SS_HIGH						// timeout
      _delay_us(1);
	  return 0x00;
    }
    _delay_us(5);
  }

  return 0xFF;
}


uint8_t WaitUntilDisplayBusy(void)
{
  uint16_t time;

  time = 10000;					// timeout 50ms

  time = 50000;
  while (DISPLAY_NOTBUSY)
  {
    time--;
	if (0 == time)
	{
      // Timeout, deselect display spi
	  SPI_SS_HIGH						// timeout
      _delay_us(1);
	  return 0x00;
    }
    _delay_us(5);
  }

  return 0xFF;
}

uint8_t WaitWhileTouch(void)
{
  uint16_t time;

  time = 10000;					// timeout 10ms

  while (TOUCHPANEL_EVENT)
  {
    time--;
	if (0 == time)
	{
      // Timeout, deselect display spi
	  SPI_SS_HIGH						// timeout
      _delay_us(1);
	  return 0x00;
    }
    _delay_us(1);
  }

  return 0xFF;
}



uint8_t SendCommand(uint16_t command)
{

 /**************************************
  Wait for display ready
  **************************************/

 if (!WaitWhileDisplayBusy()) return 0;  // timeout

 /**************************************
  Select display spi
  **************************************/
  SPI_SS_LOW;
  _delay_us(2);

 /**************************************
  Send command to display
  **************************************/
  SPI_RW((uint8_t)(command>>8));  // MSB
  SPI_RW((uint8_t)command);      // LSB

 /**************************************
  Wait until display signals busy
  **************************************/
 if (!WaitUntilDisplayBusy()) return 0; // timeout
 

  return 0xFF;

}


Die Headerdatei "Display_SPI.h" sieht wie folgt aus:

Code:
#define SPI_HARDWARESPI

//#define SPI_SOFTWARESPI



/*********************************************************************************
 *  SPI Interface
 *********************************************************************************
 *  Microcontroller: AVR Xmega128
 *
 *  SCK   : PF7  (OUTPUT)
 *  MOSI  : PF5  (OUTPUT)
 *  MISO  : PF6  (INPUT)
 *  CS_   : PF4  (OUTPUT)
 *
 *  BUSY_ : PF2 (INPUT, Pullup Resistor activated)
 *  TINT_ : PF3 (INPUT, Pullup Resistor activated)
 *
 *********************************************************************************/

#define SPI_SS_HIGH          _delay_us(1); /*PORTB |= (1<<PB0);*/		PORTF.OUTSET = PIN4_bm;
// Note: Deassert SS_ (CS_) not until the SPI-Transfer is really finished
//       otherwise it is possible the display module does not receive the last data byte
//       completely. We use an small delay of 1us to take account of this.

#define SPI_SS_LOW           /* PORTB &= ~(1<<PB0);*/		PORTF.OUTCLR = PIN4_bm

#define DISPLAY_BUSY         /*!(PINB & (1<<PB4));*/		!(PORTF.IN & 0x02)		// Bedingung PIN3 PORTF low
#define DISPLAY_NOTBUSY      /*PINB & (1<<PB4);*/			(PORTF.IN & 0x02)			// Bedingung PIN3 PORTF high

#define TOUCHPANEL_EVENT     /*!(PINB & (1<<PB5));*/		!(PORTF.IN & 0x04)





void SPI_Init (void);
unsigned char SPI_RW (unsigned char output);

uint8_t WaitWhileDisplayBusy_Timeout500ms(void);
uint8_t WaitWhileDisplayBusy(void);
uint8_t WaitUntilDisplayBusy(void);
uint8_t WaitWhileTouch(void);
uint8_t SendCommand(uint16_t command);


Die Maindatei sieht zum Test wie folgt aus:

Code:
#include <asf.h>
#include <util/delay.h>
#include <Display_SPI.h>
#include <Display_System.h>
#include <Display_Graphics.h>
#include <Display_Text.h>

int main (void)
{
	board_init();

	SPI_Init();
	
	_delay_ms(1000);
	
		
	while(1){
		
	SetBacklightIntensity(85);
	}	

	// Insert application code here, after the board has been initialized.
}

Leider bleibt das Display schwarz und rührt sich nicht, wenn ich es initialisiere und Befehle sende.
Zumindest meine Leuchtdiode zeigt ein Clock, ein SS/ und ein MOSI Signal an wie es sein sollte, wenn ich sie an dem jeweiligen Pin anschließe.

Die Spannung am Display messe ich mit 3,4 V. Auch wenn ich das Display nur an die Spannung hänge mit einer MicroSD-Karte( ist eine 2GB-Karte zu groß ? ) und der "flash.xvc" Datei darauf, welche ich mit FAT32 formatiert habe, bleibt das Display schwarz. In der Anleitung steht, hier sollte ein Status der übertragenden Datei angezeigt werden, ist das richtig?

Ich bin für Hinweise oder Ideen zum Code oder Display dankbar :)

Gruß Gerald
 
Hallo Gerald,

ich habe mir dein C-Programm angesehen. Du hast recht, die Zeile mit dem Shift fehlt, keine Ahnung warum das verlorengegangen ist :rolleyes: Ich werde das Beispiel auf der Webseite verbessern.

Falls du das Mikrocontrollermodul nutzt:
Achtung, mir ist aufgefallen dass du wieder PF2 (für BUSY\) und PF3 (für TINT\) nutzt. Das sind die Pins für den USARTF0 der über den Leveltranslator an die USB-UART-Bridge angeschlossen ist. Diese Pins darfst du also nicht für externe aktive Hardware nutzen! Im Moment arbeiten die Signale BUSY\ und RXD0 sowie TINT\ und TXD0 gegeneinander. Nutze also hierfür andere Pins.

Warum nutzt du eigentlich nicht Hardware SPI, der Xmega hat davon ja mehrere Module, du kannst sogar einen USART als Master SPI konfigurieren.

Für den XmegaA1 habe ich für dich eine Lösung mit Software SPI und Hardware SPI. Es werden jeweils die selben Pins genutzt, diese liegen auf PORTD (hier als Beispiel):

PD2: TINT\ (IN Pullup)
PD3: BUSY\ (IN Pullup)
PD4: CS\ (OUT)
PD5: MOSI (OUT)
PD6: MISO (IN)
PD7: SCK (OUT)

Du musst natürlich nicht SPI auf PORTD verwenden. Du kannst mit SPI auch auf PORTF bleiben, du musst nur eben andere Pins für BUSY\ und TINT\ verwenden.

Die SoftwareSPI-Routine ist etwas anders, als im Beispiel, hier wird nur einmal Shift ausgeführt, dies finde ich noch etwas eleganter. Bei einem Systemtakt von 32MHz läuft HardwareSPI mit einer SPI-Frequenz von 2,0MHz und SoftwareSPI mit ziemlich genau 1,5MHz (Optimierung bei GCC auf Os).

Bezüglich der MicroSD Karte, wir haben viele Karten getestet (1GB bis 16GB, FAT32), eine Liste der getesteten Karten, werde ich noch auf die Webseite stellen. Welche Karte nutzt du denn?
Man geht so vor: (1) Spannung aus (2) Karte einstecken (3) Spannung einschalten.

Du hattest ja geschrieben, dass du die Spannung am Display gemessen hast. Also hast du das ZIF-Flachbandkabel richtig herum reingesteckt. Die Stecker sind Top-Contact, wenn du das Display von der Bauteilseite siehst und das Flachbandkabel steckst, dann siehst du die Pins des Flachbandkabels, diese zeigen nach oben. Im anderen Fall bekommt das Display keine Betriebsspannung. Falls du den Adapter FPC-ADAP10 nutzt, betrifft dies den Adapter auch.


Hier mal der Sourcecode für XmegaA1:

DisplaySPI.h
Code:
#define SPI_SS_HIGH          _delay_us(1);PORTD.OUTSET = 1<<PIN4; 
#define SPI_SS_LOW           PORTD.OUTCLR = 1<<PIN4;

#define DISPLAY_BUSY         !(PORTD.IN & (1<<PIN3))
#define DISPLAY_NOTBUSY      PORTD.IN & (1<<PIN3)

#define TOUCHPANEL_EVENT     !(PORTD.IN & (1<<PIN2))

Display_SPI.C
(Du schaltest mit "#define SOFTWARESPI" zwischen Hardware- und Software-SPI um.)
Code:
/*********************************************************************************
 *  SPI Interface
 *********************************************************************************
 *  Microcontroller: ATxmega128A1
 *
 *  PD2: TINT\     (IN Pullup)
 *  PD3: BUSY\     (IN Pullup)
 *
 *  PD4: CS\       (OUT)
 *  PD5: MOSI      (OUT)
 *  PD6: MISO      (IN)
 *  PD7: SCK       (OUT)
 *
 *  Harware SPI:  fck = 2,0MHz
 *  Software SPI: fck = 1,5MHz
 *
 *  Data Direction: MSB first
 *  SPI Mode: 3
 *********************************************************************************/


//#define SOFTWARESPI

#ifdef SOFTWARESPI

/******************************************************
 Software SPI
 ******************************************************/
void SPI_Init(void)
{

  /*

  PD2: TINT\     (IN Pullup)
  PD3: BUSY\     (IN Pullup)
  PD4: CS\       (OUT)
  PD5: MOSI      (OUT)
  PD6: MISO      (IN)
  PD7: SCK       (OUT)

  */

  // CS_, MOSI, CLK
  PORTD.OUTSET = (1<<PIN5) | (1<<PIN4);              // 1: CS, MOSI
  PORTD.OUTSET = (1<<PIN7);                          // 1: CLK
  PORTD.DIRSET = (1<<PIN7) | (1<<PIN5) | (1<<PIN4);  // OUTPUT: CS, MOSI, CLK

  // MOSI, BUSY_, TINT_
  PORTD.OUTCLR = (1<<PIN6) | (1<<PIN3) | (1<<PIN2);  // MOSO, BUSY\, TINT\: INPUT
  PORTD.DIRCLR = (1<<PIN6) | (1<<PIN3) | (1<<PIN2);
  PORTD.PIN3CTRL = ( 0b011 << 3 );                   // BUSY\ Pullup
  PORTD.PIN2CTRL = ( 0b011 << 3 );                   // TINT\ Pullup

  SPI_SS_HIGH


}

#define SPI_MOSI_SET() PORTD.OUTSET = (1<<PIN5)
#define SPI_MOSI_CLR() PORTD.OUTCLR = (1<<PIN5)

#define SPI_CLK_SET() PORTD.OUTSET  = (1<<PIN7)
#define SPI_CLK_CLR() PORTD.OUTCLR  = (1<<PIN7)

#define SPI_MISO_IS_SET() PORTD.IN & (1<<PIN6)

// SPI Frequenz bei ATxmegaA @ 32MHz ist ca. 1,5MHz
uint8_t SPI_RW (uint8_t output)
{

  uint8_t data_in;
  uint8_t msk;
  uint8_t len; 
    
  msk = 0b10000000;
  len = 8; 
  data_in = 0; 

  while(len)   
  {   

   /*******************************************
    * Daten ausgeben
    *******************************************/
    SPI_CLK_CLR();

    if (output & msk)
    {
      SPI_MOSI_SET();
    } else {
      SPI_MOSI_CLR();
    }

    nop();

    SPI_CLK_SET();

    nop();

   /*******************************************
    * Daten einlesen
    *******************************************/    
    if(SPI_MISO_IS_SET())   
      data_in |= msk;       
        
              
    msk >>= 1;
    len--;   

  }  
   
  return data_in;   

}        


#else

/******************************************************
 Hardware SPI
 ******************************************************/

void SPI_Init(void)
{

  uint8_t data;

  /*

  PD2: TINT\     (IN Pullup)
  PD3: BUSY\     (IN Pullup)
  PD4: CS\       (OUT)
  PD5: MOSI      (OUT)
  PD6: MISO      (IN)
  PD7: SCK       (OUT)

  */

  // CS\, MOSI, CLK
  PORTD.OUTSET = (1<<PIN5) | (1<<PIN4);              // 1: CS, MOSI
  PORTD.OUTSET = (1<<PIN7);                          // 1: CLK
  PORTD.DIRSET = (1<<PIN7) | (1<<PIN5) | (1<<PIN4);  // OUTPUT: CS, MOSI, CLK

  // MISO, BUSY_, TINT_
  PORTD.OUTCLR = (1<<PIN6) | (1<<PIN3) | (1<<PIN2);  // MOSO, BUSY\, TINT\: INPUT
  PORTD.DIRCLR = (1<<PIN6) | (1<<PIN3) | (1<<PIN2);
  PORTD.PIN3CTRL = ( 0b011 << 3 );                   // BUSY\ Pullup
  PORTD.PIN2CTRL = ( 0b011 << 3 );                   // TINT\ Pullup

  SPID.CTRL = SPI_ENABLE_bm | SPI_MODE_3_gc | SPI_MASTER_bm;        // SPI Enable, Slave, SPI Mode 3 

  SPID.CTRL |= 0b01;  // 2Mbps  (CLKper/16)

  data = SPIE.STATUS;  // Flush buffer
  data = SPIE.DATA; 

  SPI_SS_HIGH

}

uint8_t SPI_RW (uint8_t output)
{

  SPID.DATA = output;

  while(!(SPID.STATUS & SPI_IF_bm)) { }

  return SPID.DATA;


}        

#endif

Ich hoffe, dies hilft dir weiter.

Grüße,
Dirk
 
Hallo Dirk,
danke für die schnelle Antwort. Ich habe mir den Code angeschaut und habe nur etwas Probleme was

data = SPIE.STATUS; // Flush buffer
data = SPIE.DATA;

genau macht, den Rest kann ich gut nachvollziehen.

Ich habe jetzt das Display an PORTD angeschlossen, die Hardware-SPI-Initialisierung benutzt, leider bleibt immernoch alles dunkel.
Ich habe nochmals alle Kabel überprüft, die Spannung an den beiden etwas größeren Plättchen auf dem Displaymodul gemessen mit 3,4V

Ich benutze eine MicroSD-Karte von SanDisk mit 2GB. Ich habe auch noch mal eine MicroSD-Karte von Hama mit 4GB ausprobiert, mit dem gleichen Ergebnis...Strom aus, Karte rein, Strom an, schwarzer Bildschirm...

Gruß Gerald
 
Hallo Gerald,

die SanDisk MicroSD-Karte 1GB, 2GB, 4GB und 8GB haben wir validiert. Ab 4GB sind die Karten i.d.R. bereits mit FAT32 formatiert, bei den kleineren Karten formatiert man selber FAT32.
Du kannst ein Image-File von mir downloaden (es sind die Bilder der Demonstration im Video enthalten), dieses kannst du einmal auf eine Karte kopieren und nochmal austesten. Wichtig ist, dass der File-Namen komplett klein geschrieben wird und dass sich das File im Root-Verzeichnis befindet!

Das angehängte Bild zeigt die Betriebsspannung an den größeren Pads (VCC: 6,7 und GND:9,10), bitte nochmal Polung kontrollieren.

Bezüglich der Beispielsoftware für das Xmega128A1 Modul habe ich ein Bild angehängt, dass die Signalanordnung auf dem 10poligen Adapter zeigt auch wird da der Anschluss der Signale
an den PORTD des XmegaA1 dargestellt. Es wird das SPI-Modul von PORTD genutzt. Bitte den Anschluss nochmals kontrollieren.

IMG_3616.jpgADAP10.jpg



data = SPIE.STATUS; // Flush buffer
data = SPIE.DATA;

Dies löscht das SPIF Bit im Status-Register, falls es gesetzt war.

"The SPIF bit can be cleared by first reading the STATUS register
with IF set, and then access the DATA register"


Grüße,
Dirk
 
Hallo Dirk,

müßte man nicht SPID.STATUS nehmen, es ist ja der PORT D und nicht E, oder hängt das zusammen?

Auch mit dem Image bleibt das Display bei eingesteckter Karte dunkel.

Folgendes kann ich an den PINs messen:
Der BUSY-PIN fängt an nach ca 45 Sekunden auf High zu kriechen, nach ca 70Sekunden, ist die Spannung so groß, dass CS/ auf Low geht und der MOSI PIN seine Spannung wechselt, d.h. anfängt zu senden.

Könnte es sein, dass ich durch meine PORTF-Aktion den BUSY-Ausgang kaputt bekommen habe? Ich hatte es ja einmal Testweise angeschlossen...und einfach nicht mehr dran gedacht, dass da noch was anderes dran hängt :(

Gruß Gerald

EDIT Dirk:
Wir haben das Displaymodul sicherheitshalber ausgetauscht. Die Parameterübergabe der Touchpanelkoordinaten wurde in der Demosoftware über Pointer realisiert. Im AVR Studio 4 funktioniert es, im Studio 5 nicht (Y-Koordinate wird nicht richtig übergeben). Einfachheitshalber haben wir die Koordinaten global definiert, dann läuft es auch unter Studio 5.
 
Nachtrag:
Das Display läuft jetzt schon seit über einem Jahr tadellos! Vielen Dank nochmal für die schnelle und unkomplizierte Hilfe!
 
Hi Gerald,
Nachtrag:
Das Display läuft jetzt schon seit über einem Jahr tadellos! Vielen Dank nochmal für die schnelle und unkomplizierte Hilfe!

super, das freut mich. Danke für die Rückmeldung :)

Dirk :ciao:
 
Hallo Dirk,

es freut mich auch zu sehen, dass die "Font Package"-Funktion dazugekommen ist, so muss ich größere/andere Zahlen/Buchstaben nicht mehr als Grafiken ausgeben :). Eine echt tolle Erweiterung, ich freue mich schon drauf diese in meinem nächsten Projekt zu benutzen.

Viele Grüße
Gerald
 
Hallo Gerald,
... Eine echt tolle Erweiterung, ich freue mich schon drauf diese in meinem nächsten Projekt zu benutzen.

eigentlich wollte ich schon viel mehr neue Features integrieren :eek: ich bin aber leider ziemlich ausgelastet :( Aber da werde ich bestimmt noch einiges "nachschieben", meine Todo-Liste ist jedenfalls voll, also Ideen sind da :D

Dirk :ciao:
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)