kramann.info
© Guido Kramann

Login: Passwort:










Mikrocontroller
1 Einfuehrung
..1.1 Entwicklungsgeschichtliches
..1.2 Maschinensprache
..1.3 Assemblerbeispiel
..1.4 Sprachwahl
..1.5 Praxis
....1.5.1 Digital_IO
....1.5.2 Byteoperationen
....1.5.3 AVR_Studio
....1.5.4 Testboard
....1.5.5 Aufgaben
....1.5.6 Do_it_yourself
......1.5.6.1 Ampel
......1.5.6.2 Programmierer
..1.6 Literatur
..1.7 Programmierer
....1.7.1 Bauverlauf
....1.7.2 KurzreferenzLow
....1.7.2 Kurzreferenz_16PU
..1.8 Uebung1
..1.9 BoardAtHome
....1.9.1 Software
....1.9.2 Hardware
....1.9.3 Knoppix
....1.9.4 Aufbau
....1.9.5 LED
2 Oszillator
..2.1 Assembler
..2.2 Interner_RC
..2.3 Quarz
..2.4 Taktgenerator
3 DigitalIO
..3.1 Elektrische_Eigenschaften
..3.2 Pullup_Widerstaende
..3.3 Bitmasken_Eingang
..3.4 Bitmasken_Ausgang
..3.5 Tic_Tac_Toe
....3.5.1 DuoLEDs
....3.5.2 Schaltplan
....3.5.3 Spielfeld
....3.5.4 Anwahl
....3.5.5 Kontrolle
..3.6 Laboruebung2
..3.7 Laboruebung2_alt
4 PWM
..4.1 Prinzip
..4.2 Nutzen
..4.3 Generierung
..4.4 Programmierung
..4.5 Servos
..4.7 Laboruebung3
..4.8 LoesungUE3
..4.9 Uebung6
5 LichtKlangKugeln
..5.1 LED
..5.2 RGB
..5.3 Sensoren
..5.4 lautsprecher
..5.5 tonerzeugung
6 UART
..6.1 Bussysteme
..6.2 UART
..6.3 RS232
..6.4 Hardware
..6.5 Senden
..6.6 Hyperterminal
..6.7 Empfangen
..6.8 Broadcast
..6.9 Uebung4
7 Infrarot
..7.1 schalten
..7.2 seriell
..7.3 Uebung
8 OOP
..8.1 Probleme
..8.2 Konzept
..8.3 Statisch
..8.4 Datentypen
..8.5 RS232
....8.5.1 Prozedural
....8.5.2 Analyse
....8.5.3 Umsetzung
....8.5.4 Vererbung
....8.5.5 Statisch
....8.5.6 Performance
..8.6 Fahrzeug
9 ADW
..9.1 ADW
..9.2 Zaehler
10 Peripherie
..10.1 RS232Menue
..10.2 ASCIIDisplay
..10.3 Tastenmatrix
..10.4 Schrittmotor
..10.5 Zaehler
..10.6 Uebung7
11 SPI
..11.1 Testanordnung
..11.2 Register
..11.3 Test1
..11.4 Test2_Interrupt
..11.5 Test3_2Slaves
..11.6 Laboruebung
12 EEPROM
13 I2C
..13.1 MasterSendByte
..13.2 MasterSend2Bytes
..13.3 MasterReceiveByte
..13.4 MasterReceive2Bytes
14 Anwendungen
..14.1 Mechatroniklabor
....14.1.1 Biegelinie
....14.1.2 Ausbruchsicherung
....14.1.3 Einachser
....14.1.4 AV
....14.1.5 Vierradlenkung
....14.1.6 Kommunikation
..14.2 Sinuserzeugung
....14.2.1 Variante1
....14.2.2 Variante2
....14.2.3 Variante3
....14.2.4 Variante4
..14.3 Laboruebung8
..14.4 Loesung_Ue8
..14.5 SPI_Nachtrag
20 Xubuntu

11.5 Testprogramm 3 - Verwendung beider Slaves

  1. Der Master wählt Slave 1 an, d.h. PA1 ändert den Pegel von High nach Low.
  2. Da PA1 des Masters mit dem SS Eingang des Slaves 1 verbunden ist, führt die Pegeländerung von High auf Low bei Slave 1 dazu, dass ein Interrupt ausgelöst wird und das Hauptprogramm unterbrochen wird, um in den SPI-Modus zu gehen.
  3. Es wird dann ein Byte vom Master an den Slave gesendet, dort empfangen und angezeigt. Gleichzeitig wird ein Byte durch den Master von Slave 1 empfangen und beim Master angezeigt.
  4. Im Anschluß wird beim Master PA1 wieder auf High gesetzt, aber dafür PA2 auf Low, um Slave 2 anzuwählen.
  5. Der von Slave 1 empfangene Wert wird dann an Slave 2 gesendet.
  6. Wieder sendet der Master stets die Zahl 15 an Slave 1 und bekommt einen mit jedem durch den Taster ausgelösten Sende-Empfangszyklus inkrementierten Zahlenwert von Slave 1, der dann an Slave 2 vom Master weiter gegeben wird.
  • Um ein anschauliches Beispiel zu bekommen, sind aufgrund der Hauptprogramme zunächst alle Anzeigen auf Null gestellt.
  • Der Master sendet als Byte immer dezimal 15 an Slave 1, welcher diese Zahl nach einem Sende-Empfangszyklus dann anzeigt.
  • Slave 1 sendet an den Master zuerst eine 1 und zählt dann nach jedem Sende-Empgangszyklus um +1 nach oben.
  • Dadurch wird bei Master und Slave 2 dann erst 1, dann 2,3,4, usw. angezeigt.
BILDBESCHREIBUNG

Bild 11.5-1: Zustand von Master, Slave1 und Slave2 nach mehrmaligem Drücken des Tasters PB0

#include <avr/io.h>

int main(void)
{
    uint8_t akku;

    //MOSI / PB5 als Output
    DDRB |= 0b00100000;
    //MISO / PB6 als Input
    DDRB &= 0b10111111;
    //SCK  / PB7 als Output (für den Synchronisationstakt)
    DDRB |= 0b10000000;

    //SPI-Schnittstelle als Master ohne Interrupts konfigurieren und starten:
    SPCR = (0<<SPIE) | (1<<SPE) | (0<<DORD) | (1<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);            


    //Slave Select Ausgänge PA1 und PA2 als Ausgänge:
    DDRA  |= 0b00000110;
    PORTA |= 0b00000110; //Slave-select auf High setzen

    //8-Bit-Parallel-Verbindung zu erstem Mikrocontroller (muecA), also PORTC als Ausgang:
    DDRC = 0b11111111;
    //Null anzeigen lassen, solange Taster nicht das erste mal gedrückt wurde.
    PORTC = 0;
		    
	while(1)
	{		
		if(PINB & (1<<PINB0))  //Wenn Taster PB0 gedrückt
		{
//Kommunikation mit Slave 1
            //PA1 auf Low, d.h. Slave 1 anwählen:
            PORTA &= 0b11111101;
            //Zu sendende Zahl 15 für den Sende/Empfangszyklus in das SPI-Datenregister schreiben:
            SPDR = 15;
            //Warten, bis Flag für erfolgreiche Datenübertragung gesetzt ist:
            while( (SPSR & (1<<SPIF)) == 0);

            akku = SPCR; //Durch Auslesen der Register SPCR und SPDR Interrupt wieder freigeben
            //Empfangenes Byte nach Port C schicken, um es dezimal anzeigen zu lassen:
            akku = SPDR;
            PORTC = akku;
            
            //Slave-select beider Slaves wieder auf high-Pegel:
            PORTA |= 0b00000110;

//Kommunikation mit Slave 2
            //PA2 auf Low, d.h. Slave 1 anwählen:
            PORTA &= 0b11111011;
            //Zu sendende Zahl 15 für den Sende/Empfangszyklus in das SPI-Datenregister schreiben:
            SPDR = akku;
            //Warten, bis Flag für erfolgreiche Datenübertragung gesetzt ist:
            while( (SPSR & (1<<SPIF)) == 0);

            akku = SPCR; //Durch Auslesen der Register SPCR und SPDR Interrupt wieder freigeben
            //Empfangenes Byte nach Port C schicken, um es dezimal anzeigen zu lassen:
            akku = SPDR; //In diesem Fall nichts mit der empfangenen Zahl tun.
            
            //Slave-select beider Slaves wieder auf high-Pegel:
            PORTA |= 0b00000110;

            //Warten, bis Taste bei PB0 wieder losgelassen wird
			while(PINB & (1<<PINB0));
		}
		
	}
	return 0;
}

 

Code 11.5-6: Quellcode vom Master für Testprogramm 3

#include <avr/io.h>
#include <avr/interrupt.h> //Library für Interrupts

volatile uint8_t akku;
volatile uint8_t zahl=1;

SIGNAL(SIG_SPI) //Empfang über SPI vollständig, sollte auf Flag SPIF in SPSR reagieren!
{
    akku = SPCR; //Durch Auslesen der Register SPCR und SPDR Interrupt wieder freigeben
    akku = SPDR; 
    PORTC = akku; //Empfangenes Byte dezimal anzeigen. In diesem Fall die 15

    zahl++; //Zu sendende Zahl um 1 erhöhen
    SPDR = zahl; //Zusendende Zahl in das SPI-Datenregister legen.
}

int main(void)
{
    //MOSI / PB5 als Input
    DDRB &= 0b11011111;
    //MISO / PB6 als Output (genau umgekerht wie beim Master)
    DDRB |= 0b01000000;
    //SCK / PB7 als Input (für den Synchronisationstakt)
    DDRB &= 0b01111111;


	DDRC = 0b11111111;    //PORTC als Ausgang
    PORTC = 0;            //PORTC mit Null vorinitialisieren

    //SPI-Datenregister mit der zu sendenden Zahl füllen:
    SPDR = zahl;

    //SPI-Schnittstelle als Slave und mit Interrupt aktivieren:
    SPCR = (1<<SPIE) | (1<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);            

    //Interrupts allgemein aktivieren:
    sei();
	
	while(1) //Im Hauptprogramm nichts tun
	{
	}
	return 0;
}

 

Code 11.5-7: Quellcode von Slave 1 für Testprogramm 3

#include <avr/io.h>
#include <avr/interrupt.h> //Library für Interrupts

volatile uint8_t akku;

SIGNAL(SIG_SPI) //Empfang über SPI vollständig, sollte auf Flag SPIF in SPSR reagieren!
{
    akku = SPCR; //Durch Auslesen der Register SPCR und SPDR Interrupt wieder freigeben
    akku = SPDR; 
    PORTC = akku; //Empfangenes Byte dezimal anzeigen. In diesem Fall die 15

    SPDR = 255; //Zusendende Dummy-Zahl in das SPI-Datenregister legen.
}

int main(void)
{
    //MOSI / PB5 als Input
    DDRB &= 0b11011111;
    //MISO / PB6 als Output (genau umgekerht wie beim Master)
    DDRB |= 0b01000000;
    //SCK / PB7 als Input (für den Synchronisationstakt)
    DDRB &= 0b01111111;

	DDRC = 0b11111111;    //PORTC als Ausgang
    PORTC = 0;            //PORTC mit Null vorinitialisieren

    //SPI-Datenregister mit der zu sendenden Dummy-Zahl füllen:
    SPDR = 255;

    //SPI-Schnittstelle als Slave und mit Interrupt aktivieren:
    SPCR = (1<<SPIE) | (1<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);            

    //Interrupts allgemein aktivieren:
    sei();
	
	while(1) //Im Hauptprogramm nichts tun
	{
	}
	return 0;
}
 

Code 11.5-8: Quellcode von Slave 2 für Testprogramm 3

spi5_komplett.zip - Projekt zu Testprogramm 3.