ATMEGA 1280 USART0 in SPI MODE

Gast #1703458
Lesenswert?

Hallo Leute,

habe folgendes Problem, will mein Display EA DOGM and die USART0 in SPI 
Mode anschließen. Ich verwende einen ATmega 1280 TQFP100

Das Display war bisher direkt an der SPI Schnittstelle dran, da ich aber 
diese nun für eine SDCard Ansteuerung brauche, muss ich nun die USART0 
in SPI Mode verwenden.

Wie gesagt das Display funktionierte bisher tatellos an SPI, das einzige 
was nun geändert wurde, ist MOSI und SCK vom Display an USART 
angeschlossen
die restlichen PINs blieben unberührt.

DISPLAY MOSI -> TXD
DISPLAY SCK -> XCK0

Init Funktion
1
#define XCK0_DDR  DDRE
2
#define XCK0  PD2
3

4
// Initialize the SPI as master
5
void uart_spi_init()
6
{
7
  // DDRB = 0xFF;
8
  // SPI max. speed
9
  // the DOGM128 lcd controller can work at 20 MHz
10
        // SPIMODE 3
11
  //SPCR = (1 << SPE) | (1 << MSTR) | (1 << CPHA) | (1 << CPOL);
12
  //SPSR = (1 << SPI2X);
13

14

15
DDRB = 0xFF;
16
DDRE = 0xFF;
17

18
UBRR0 = 0;
19

20
// Set the XCK0 port pin as an output, enables master mode
21
XCK0_DDR |= (1 << XCK0);
22

23
// Set MSPI mode of operation and SPI mode 3
24
UCSR0C = (1 << UMSEL01) | (1 << UMSEL00) | (1 << UCSZ00)| (0 << UCSZ01) | (1 << UCPOL0);
25

26
// Enable the receiver and transmitter
27
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
28

29
UBRR0 = 7;
30
}


und Sende Funktion
1
void send_byte (uint8_t data)
2
{
3
  clr_cs ();
4

5
  //SPI SENDBYTE
6
  //SPDR = data;
7
  //while (!(SPSR & (1<<SPIF)));
8

9
  while (!(UCSR0A & (1 << UDRE0))); //USART in SPIMODE
10
  UDR0 = data; //USART in SPIMODE
11

12
  set_cs ();
13
}

Aber mit diesen Änderungen Funktioniert mein Display nicht mehr!
Display funktioniert noch, habe noch eine zwei Platine mit der SPI 
Ansteuerung!

Habe ich irgendetwas übersehen? Es muss an der Initialisierung oder am 
Senden liegen!!

Danke für eure Hilfe

Gruß
Jochen
Gast #1703466
Lesenswert?

Hi

>while (!(UCSR0A & (1 << UDRE0))); //USART in SPIMODE

Im Gegensatz zum SPI ist das Datenregister der UART gepuffert. UDRE gibt 
nur an, das ein Byte an UDR übergeben werden kann, nicht , das das 
Byte fertig gesendet wurde. Bevor du den Status der Steuerleitungen 
(CS,A0..) änderst, must du mit TXC prüfen, ob das letzte Byte komplett 
gesendet wurde.

MfG Spess
Gast #1703483
Lesenswert?

Hi,

vielen Dank für die Info, habs entsprechend geändert!
1
void send_byte (uint8_t data)
2
{
3
  clr_cs ();
4

5
  while (!(UCSR0A & (1 << UDRE0)));
6
  UDR0 = data;
7
  while (!(UCSR0A & (1 << TXC0)));
8

9
  set_cs ();
10
}

Leider hat das auch nicht geholfen. Hast du noch eine Idee?
#1703537
Lesenswert?

Salut ...

ich benutze den USART0 auf einen Atmega2561, ich denke mal von den 
Register sollte das das selbe sein in etwa. Hier mein Code zum Init und 
senden/empfangen.
1
void SPI_init( void )
2
{
3
    UBRR0 = 0;
4
    /* Setting the XCKn port pin as output, enables master mode. */
5
    SPI_DDR |= ( 1 << XCK1 );
6
    /* Set MSPI mode of operation and SPI data mode 0. */
7
    UCSR0C = (1<<UMSEL01)|(1<<UMSEL00);
8
    /* Enable receiver and transmitter. */
9
    UCSR0B = (1<<RXEN0)|(1<<TXEN0);
10
    /* Set baud rate. */
11
    /* IMPORTANT: The Baud Rate must be set after the transmitter is enabled */
12
    UBRR0 = 0;
13
}
14

15
char SPI_ReadWrite( char Data )
16
{
17
  /* Wait for empty transmit buffer */
18
  while ( !( UCSR0A & (1<<UDRE0)) );
19
  /* Put data into buffer, sends the data */
20
  UDR0 = Data;
21
  /* Wait for data to be received */
22
  while ( !(UCSR0A & (1<<RXC0)) );
23
  /* Get and return received data from buffer */
24
  return UDR0;
25
}

Bei tut dieser Code mit einem ENC28j60. Evtl. musst du noch den Mode und 
Speed ändern auf deine Bedürfnisse.

CA Dirk
Gast #1703667
Lesenswert?

Hallo Dirk,


SPI_DDR ist DDRE???

und

XCK1 ist PE2???

Sonst habe ich alles identisch, nur SPIMODE 3 das ich mit

(1 << UCSZ00)| (0 << UCSZ01) | (1 << UCPOL0)

eingestellt habe.


Ich denke die Speed, bzw Baudrate dürfte keine Rolle spielen!

Oder doch?

Gruß
Jochen
#1703766
Lesenswert?

Salut ...

so weit ich das noch in Erinnerung habe war die Baudrate bei den 
Displays nicht so dolle.

SPI_DDR = DDRE

und XCK0 liegt auf PE2, da ist ein kleiner Fehler in meinem Listing, 
dort steht XCK1 :-). Aber interessant dürfte für dich eigentlich nur das 
abholen der Daten sein.

N8 Dirk
#1703807
Lesenswert?

Hallo,

versuche mal ein NOP oder ein kleine Pause nach dem Senden, also
1
void send_byte (uint8_t data)
2
{
3
  clr_cs ();
4

5
  //SPI SENDBYTE
6
  //SPDR = data;
7
  //while (!(SPSR & (1<<SPIF)));
8

9
  while (!(UCSR0A & (1 << UDRE0)));
10
  UDR0 = data; 
11

12
  _delay_ms (0.001); // ODER NOP;
13

14
  while (!(UCSR0A & (1 << TXC0)));
15
  set_cs ();
16
}

Die Displays brauchen eine kurze Pause bis Sie wieder den nächsten 
Befehl annehmen können. Wenn es zu schnell geht, dann reagiert das 
Display nicht mehr.

Gruß
Marcus Parentis
Gast #1703885
Lesenswert?

Hallo,

wo ist der /CS des SPI-Displays angeschlossen? Er sollte einen eigenen 
Pin bekommen; der /SS von der SPI-Schnittstelle wird ja wohl für die 
SDCard verwendet ...

> Ich denke die Speed, bzw Baudrate dürfte keine Rolle spielen! Oder doch?

Darüber sollte das Datenblatt des Displays Auskunft geben (max. SPI 
clock); zu schneller Takt kann Probleme geben.
Da das Display an der (richtigen) SPI-Schnittstelle gelaufen hat, kannst 
du diese Takteinstellungen doch für den SPI-USART übernehmen.
#1721528
Lesenswert?

Hallo Jochen,
im Datenblatt vom ATmega128x/644x/256x steht, nur die mega 
1281/6441/2561
haben den UART0 di/do Modus. Bei den anderen gehen die PINs nach 
MISO/MOSI

• PDO/TXD0 – Port E, Bit 1
PDO, SPI Serial Programming Data Output. During Serial Program 
Downloading, this pin is
used as data output line for the ATmega1281/2561. For 
ATmega640/1280/2560 this function is
placed on MISO.
TXD0, USART0 Transmit pin.
• PDI/RXD0/PCINT8 – Port E, Bit 0
PDI, SPI Serial Programming Data Input. During Serial Program 
Downloading, this pin is used
as data input line for the ATmega1281/2561. For ATmega640/1280/2560 this 
function is placed
on MOSI.
RXD0, USART0 Receive Pin. Receive Data (Data input pin for the USART0). 
When the
USART0 receiver is enabled this pin is configured as an input regardless 
of the value of DDRE0.
When the USART0 forces this pin to be an input, a logical one in PORTE0 
will turn on the internal
pull-up


Gruß Karl-Heinz
#1721810
Lesenswert?

Danke für die Info,
 Ich baue mir gerade ein Bord mit 2560 , externes Ram, Ethernet 
Controller, usart to usb chip, serial eeprom ,Micro-SD, jtag , ISP . Die 
freien Ports werde ich auf Wannenstecker ausführen.  Für den Ethernet 
Chip werde ich exklusive ein SPI port  z.b. PortE verwenden.
Der TCP/IP Stack wird eine Mischung von U.Radig Stack  und dem openMPC 
Stack.
Beide Stacks laufen auf meine Demo Boards mega644p und mega2560.
Mal sehen wie weit ich mit meinem Projekt komme.
Im Endausbau werde ich auch einen Ethernet Bootloader dazu packen.
Gruß KH
#1725435
Lesenswert?

ich habe mein Problem gelöst, im Datenblatt steht man muss nach dem 
Senden das UDRx lesen. deshalb sieht man bei vielen Implementierungen 
SPI_ReadWrite an einem Stück.

Wenn man mit SPI_Put oder SPI_Get arbeitet, muss im SPI_Put ein warten 
und lesen vom UDRx erfolgen. Diese Daten gebe ich mit einem Flag und 
einer Variable an die SPI_Get Prozedur weiter.

mit dieser kleinen Änderung läuft der Stack von U.Radig auch auf USART 
im SPI Mode,  könnte für manche Leute hilfreich sein.

Gilt für USART0:

static inline void spi_put( unsigned char value )
{

              /* Wait for empty transmit buffer */
              while ( !( UCSR0A & (1<<UDRE0)) );

              /* Put data into buffer, sends the data */
              UDR0 = value;
              while ( !(UCSR0A & (1<<RXC0)) );
              SendReceive=UDR0; //read data and flag read done to 
spi_get
              SendReceiveFlag=true;
}


static inline unsigned char spi_get(void)
{
              if (SendReceiveFlag==true)
              {
                SendReceiveFlag=false;
                return SendReceive;
              }

              while ( !(UCSR0A & (1<<RXC0)) );
              return UDR0;
}
#1725447
Lesenswert?

ich habe mein Problem gelöst, im Datenblatt steht man muss nach dem 
Senden das UDRx lesen. deshalb sieht man bei vielen Implementierungen 
SPI_ReadWrite an einem Stück.
Wenn man mit SPI_Put oder SPI_Get arbeitet, muss im SPI_Put ein warten 
und lesen vom UDRx erfolgen. Diese Daten gebe ich mit einem Flag und 
einer Variable an die SPI_Get Prozedur weiter.

mit dieser kleinen Änderung läuft der Stack von U.Radig auch auf USART 
SPI Mode,  könnte für manche Leute hilfreich sein.
static inline void spi_put( unsigned char value )
{

              /* Wait for empty transmit buffer */
              while ( !( UCSR0A & (1<<UDRE0)) );

              /* Put data into buffer, sends the data */
              UDR0 = value;
              while ( !(UCSR0A & (1<<RXC0)) );
              SendReceive=UDR0; //read data and flag read done to 
spi_get
              SendReceiveFlag=true;
}


static inline unsigned char spi_get(void)
{
              if (SendReceiveFlag==true)
             {
                 SendReceiveFlag=false;
                return SendReceive;
             }

              while ( !(UCSR0A & (1<<RXC0)) );
              return UDR0;
}
Gast #1759466
Lesenswert?

Hallo Leute,

ich möchte eine atmega1281 durch USART1 als SPI_Master verwenden. Das 
ist die C Code aus Datasheet:

// Initialisierung SPI_Master (ATMEGA1281)
void USART_Init( unsigned int baud )
{
  UBRR1L = 0;
  /* Setting the XCKn port pin as output, enables master mode. */
  XCK1_DDR |= (1<<XCK1);
  /* Set MSPI mode of operation and SPI data mode 0. */
  UCSR1C = (1<<UMSEL11)|(1<<UMSEL10)|(0<<UCPHA1)|(0<<UCPOL1);
  /* Enable receiver and transmitter. */
  UCSR1B = (1<<RXEN1)|(1<<TXEN1);
  /* Set baud rate. */
  /* IMPORTANT: The Baud Rate must be set after the transmitter is 
enabled*/
  UBRR1L = baud;
}

// Senden der Daten von Master

unsigned char USART_Receive(void)
{
  unsigned char data;
  /* Wait for empty transmit buffer */
  while ( !( UCSR1A & (1<<UDRE1)) );
  /* Put data into buffer, sends the data */
  UDR1 = data;
  /* Wait for data to be received */
  while ( !(UCSR1A & (1<<RXC1)) );
  /* Get and return received data from buffer */
  return UDR1;
}

aber bei der Übersetzung meldet die folgenden Bits als undeclared:
UBRR1L
XCK1_DDR
XCK1
UCSR1C
UMSEL11
UMSEL10
UCPHA1
UCPOL1
UCSR1B
RXEN1
TXEN1
UCSR1A
UDRE1
UDR1
RXC1

Habt ihr sie extra definiert oder gibt eine Header(Include) File, welche 
diese Bits erkennen kann?

Grüße
David
Gast #1759588
Lesenswert?

Ich habe schon definiert:
#define UBRR1  _SFR_MEM16   (0xCC)
#define UBRR1L  _SFR_MEM8  (0xCC)
#define UBRR1H  _SFR_MEM8  (0xCD)
#define XCK1_DDR  DDRD
#define XCK1    PD5
#define UCSR1A  _SFR_MEM8  (0xC8)
#define RXC1  7
#define UDRE1  5
#define UCSR1B  _SFR_MEM8  (0xC9)
#define RXEN1  4
#define TXEN1  3
#define UCSR1C  _SFR_MEM8  (0xCA)
#define UMSEL11  7
#define UMSEL10  6
#define UCPOL1  0
#define UDR1   _SFR_MEM8  (0xCE)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren