www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik SPI- Schnittstelle Byte senden


Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo liebes Forum,

da ich mich erst mit dem Thema Mikrocontroller am einarbeiten bin, bitte 
ich schon mal um Nachsicht wegen evtl "einfacher" Fragen.

Ich haben einen Atmega 8515L (auf dem STK500), welchen ich nutzen will 
um einen IC ltc6802-2 zu konfigurieren und später auch auszulesen.

Zunächst will ich einige Bytes vom Master (Atmega) zum Slave senden. 
Gleichzeitig will ich die gesendeten Bytes auf dem UART am Rechner zur 
Kontrolle (über uart_puts(comData);) ausgeben.

Die Initialisierung des Uart sollte stimmen, da ich einen "Hello World" 
String normal ausgeben kann.

Die LED on/off dienen lediglich zur eigenen Kontrolle, wo ich mich 
gerade befinde.

Momentan werden die Bytes nicht sauber gesendet. Auch an der Uart 
Schnittstelle sehe ich ein anderes Ergebnis als erwartet.
Wäre toll, wenn mir jemand weiterhelfen könnte.

Hier ist mein verwendeter Code:


#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>


#ifndef F_CPU

#define F_CPU 1000000L // Systemtakt in Hz
#endif
#define BAUD 4800L // Baudrate
// Berechnungen
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000) // Fehler in Promille
#if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))
#error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
#endif

#include <util/delay.h> /* in der aktuellen Version in util/ */



// UART Interface

void uart_init(void)      //Init Uart
{
  //UCSRB |= (1<<RXEN) | (1<<TXEN); // UART TX einschalten
  UCSRB |= (1<<TXEN); // UART TX einschalten
  UCSRC = (1<<URSEL)| (1<<UCSZ1) | (1<<UCSZ0);  // 8 Datenb , 1Stb
  UBRRH = UBRR_VAL >> 8;
  UBRRL = UBRR_VAL & 0xFF;
}

void uart_putch(char c) {
   while(!(UCSRA & (1<<UDRE)));
   UDR = c;
}

void uart_puts(char * str) {
   while (*str) {
      uart_putch(*str++);
   }
}


//////////// Test LED 3 on off ////////////

void led3_on(void)
{
DDRB  |= (1 << PB3);     //Port 3 Out
PORTB |= (1 << PB3);     //LED on
_delay_ms(1000);
}

void led3_off(void)
{
DDRB  |= (1 << PB3);     //Port 3 Out
PORTB &= ~(1 << PB3);    //LED off
_delay_ms(1000);
}


// SPI Interface
void spi_init (void)          //Init SPI
{
  DDRB |= (1<<PB4)|(1<<PB5)|(1<<PB7);   // MOSI,SCK,SS als Output
  PORTB |= (1<<PB4);           //SS auf High
  SPCR |= (1<<SPE)|(1<<MSTR);       // SPI enable, Master Mode
}

void spi_senden (unsigned comData, unsigned CFGR0, unsigned CFGR1, 
unsigned CFGR2, unsigned CFGR3, unsigned CFGR4, unsigned CFGR5)
{

  PORTB &= ~(1 << PB4);         //START SENDEN SS auf Low

  SPDR = comData;              //Command Byte
  while (!(SPSR & (1 << SPIF)));     //warten bis gesendet


  while (!(UCSRA & (1<<UDRE)))  //ist die Sendestufe bereit?
      {
    }
  uart_puts(comData);
    led3_on();

  SPDR = CFGR0;
  while (!(SPSR & (1 << SPIF)));     //warten bis gesendet
  SPDR = CFGR1;
  while (!(SPSR & (1 << SPIF)));     //warten bis gesendet
  SPDR = CFGR2;
  while (!(SPSR & (1 << SPIF)));     //warten bis gesendet
  SPDR = CFGR3;
  while (!(SPSR & (1 << SPIF)));     //warten bis gesendet
  SPDR = CFGR4;
  while (!(SPSR & (1 << SPIF)));     //warten bis gesendet
  SPDR = CFGR5;
  while (!(SPSR & (1 << SPIF)));     //warten bis gesendet


while (!(UCSRA & (1<<UDRE)))  //ist die Sendestufe bereit?
      {
    }
   uart_puts(CFGR5);
  //led3_off();

  PORTB |= (1 << PB4);           //ENDE SS auf high

}



int main(void)
{
     uart_init();

    spi_init();


  spi_senden(0x01, 0xE1, 0x04, 0x00, 0xFF, 0x73, 0xAF); // Write Config



  while(1)
   {

  led3_off();


   }

return 0;
}

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Momentan werden die Bytes nicht sauber gesendet.

Woher weisst du das? Auf dem Osci nachgesehen?
Dann liegt es an deiner Schaltung.

> Auch an der Uart
>Schnittstelle sehe ich ein anderes Ergebnis als erwartet.

Das ist so weil du nicht weisst was ein String ist.
Ich rate dir dringend zu einem C-Buch oder Lehrgang.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
uart_puts(comData);
Das ist Unsinn und sendet daher auch Unsinn. comData ist nun mal kein 
Pointer auf einen String.

Du solltest dir gleich von Anfang an angewöhnen, alle Warnungen des 
Compilers ernst zu nehmen.

PS: Für "uart_puts(CFGR5);" gilt natürlich das gleiche. ;-)

PPS: Und verwende bitte beim nächsten Mal die vom Forum angebotene 
Möglichkeit der Source-Code-Formatierung.

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke ,
mit
 uart_putch[comData); 
stimmt auch die Ausgabe im Terminal.

Die Daten werden laut Oszi verschickt.
Aber eigentlich will ich den Befehl nur einmal senden. Momentan habe ich 
bei SPI_Senden() eine Endlos-Schleife und ich sehe nicht warum?
In die While(1) Schleife komme ich gar nicht hinein.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Watchdog Fuse aus? Richtigen uC eingestellt?

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
WDTON Haken ist nicht gesetzt und Atmega8515 ist eingestellt.

Wenn ich die Funktion innerhalb von main() aufrufe, dann wird die 
Schleife genau einmal durchlaufen und geht weiter zur while(1).

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>Aber eigentlich will ich den Befehl nur einmal senden. Momentan habe ich
>>bei SPI_Senden() eine Endlos-Schleife und ich sehe nicht warum?
>>In die While(1) Schleife komme ich gar nicht hinein.

>Wenn ich die Funktion innerhalb von main() aufrufe, dann wird die
>Schleife genau einmal durchlaufen und geht weiter zur while(1).

Fällt dir auf das sich deine Aussagen widersprechen?

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm vielleicht habe ich mich ja falsch ausgedrückt.

Ich will die Byte-folge einmal senden. Wenn ich die Funktion zum senden 
der Bytes spi_senden() außerhalb von main verwende, dann wiederholt sich 
diese Funktion immer wieder. Wenn ich die Funktion innerhalb von main() 
setze und überhalb der while(1) Schleife, dann wird die Byte-Folge genau 
einmal gesendet.

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gibt es eigentlich eine fertige Funktion,um per SPI Strings zu senden? 
oder müsste man sich die aus der Bytesenden-Routine selber zaubern und 
die Routine mehrmals aufrufen, solange das zeichen != '\0' ist?

Danke und Gruß
jo

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich kenne keine fertige Funktion, da ja auch jede SPI Kommunikation von 
Datenblatt abhängt.

Autor: Elektrolyt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey Micha,

was genau machst du denn mit dem Balancer ?
Laden und samplen und balancen? oder nur als ADC benutzen?
ich hab das teil auch mal eingesetzt, allerdings habe ich keine Ahnung 
wo der Quellcode ist...


gruß Elko

Autor: Tobias T. (thelaughingman)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
füg mal ein
#include <avr/wdt.h>
ein und ruf direkt als erstes in der main
wdt_disable();
auf.

Der 8515L hat keine Fuse für den WatchDogTimer (aus), da du ihn nicht 
deaktiviert startet der Mikrocontroller permanent neu.
WDTON mach ihn nur permanent an. Ausschalten muss du den WDT trotzdem.

Für später um die Initialisierungen immer ein
cli();
//Initialisierungen ...
sei();
packen.

Die DDRX Register für die Pins muss du auch nur einmal einstellen. 
Braucht nicht vor jeden ändern der LED nochmal stehen.

Autor: Tobias T. (thelaughingman)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zu deiner Frage (String per SPI senden):
Schau dir doch den Code zu senden von String über UART, an der greift 
auch auf das Senden einzelner Zeichen zurück. Dasselbe muss du mit SPI 
machen (-> Copy&Paste).

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Micha schrieb:

> Ich will die Byte-folge einmal senden. Wenn ich die Funktion zum senden
> der Bytes spi_senden() außerhalb von main verwende, dann wiederholt sich
> diese Funktion immer wieder.

Dann zeige uns den Code zu diesem "außerhalb von main verwende", denn in 
dem Code oben wird die Funktion in main aufgerufen. Wie sollen wir dir 
sagen, was dort schief läuft, wenn wir den Code dazu nicht kennen?

Autor: Micha (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Dieser Code macht zumindest das, was ich will.
Einmalig eine Bytefolge aussenden und dauern eine kürzere Byte-folge 
aussenden.
Der Quellcode ist als Anhang beigefügt

@Elko
ich will zunächst die Spannung über ADC auslesen und ausgeben.
Wäre toll, wenn Du den Quellcode nochmal findest (?) und mal posten 
kannst.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.