Moin, liebe mikrocontroller Community. In der Vergangenheit habe ich diese Forum schon oft genutzt um meine Probleme zu bewältigen. Leider stecke ich seit 4 Tagen an einem so simplen Problem und seh den Wald vor lauter Bäumen nicht mehr. Ich möchte eine simple SPI Kommunikation zum laufen bringen. Hierbei wird der AT90CAN128 als Master initialisiert und der ATmega16 als Slave. Es soll der Master den Slave ansprechen über den SS Pin (low) und der Atmega soll in diesem Projekt dann mit den ausgewerteten Sensordaten antworten. Da das alles nicht so gefunzt hat, hab ich angefangen die Kommunikaion Schritt für Schritt zu vereinfachen (von interrupt mode -> polling mode). Am Ende wollte ich jetzt Daten über Mosi rausschicken und diese Daten dann auf der MISO Leitung wiedersehen. Das heißt ich hab das SPDR register beschrieben, damit wird auch die CLK gestartet und die Daten werden auch einwandfrei rausgesendet (mit dem Oszi gesehen). CLK und SS funzt auch wunderbar. Nach der SPI Theorie bestehet die Kommunikation aus zwei Shift Registern, wobei diese Register gleichzeitig Bit für Bit austauschen. Um Bits auf die MISO Leitung zu senden braucht es also eigentlich nur die CLK des Masters. Ich dachte jetzt also das jetzt im aller ersten durchlauf da nichts brauchbares zurückkommen kann, aber spätestens ab dem zweiten durchlauf die MISO Daten gleich der MOSI Daten sein sollten. Stattdessen geht das MISO Signal low über die SS Zeit und verhält sich danach wie ein Kondensator der sich auflädt. Das wäre echt super wenn ihr mir helfen könntet oder falls ihr die Datenblätter kennt mich dort auf eine Seite hinweisen die ich vielleicht übersehen habe. Ich hab noch sonst zwei Ausschnitte aus dem Schaltplan mit rangehangen. Die hab ich nicht erstellt sondern wurden von einem Kollegen gemacht und ich soll die Software dafür schreiben :) Das ist mein erster Beitrag in diesem Forum, ich hoffe ich konnte alle Materialien bereitstellen und die Regeln befolgen. Wenn was fehlt oder doof geschrieben würde ich das natürlich umgehend nachreichen. Master Code:
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | #include <stdio.h> |
4 | #include <math.h> |
5 | #include <util/delay.h> |
6 | |
7 | #define MOSI PB2
|
8 | #define MISO PB3
|
9 | #define SCK PB1
|
10 | #define SS_uC PE2
|
11 | #define SS_TK1 PE0
|
12 | #define SS_TK2 PE1
|
13 | |
14 | #define SPI_Control_Reg SPCR
|
15 | #define SPI_Status_Reg SPSR
|
16 | #define SPI_Data_Reg SPDR
|
17 | #define SPI_Enable SPE
|
18 | #define SPI_Interrupt_Enable SPIE
|
19 | #define SPI_Master MSTR
|
20 | #define SPI_Data_Order DORD
|
21 | #define SPI_Clock_Poarity CPOL
|
22 | #define SPI_Clock_Phase CPHA
|
23 | #define SPI_InterruptFlag SPIF
|
24 | #define SPI_WriteCOLisionFlag WCOL
|
25 | #define SPI_DoubleSpeed_Bit SPI2X
|
26 | |
27 | void SPI_MasterInit(void){ |
28 | // Set MOSI, SCK and all SS as output
|
29 | DDRB |= (1 << MOSI) | (1 << SCK); |
30 | //Set slave selects as output
|
31 | DDRE |= (1<<SS_uC) | (1<<SS_TK1) | (1<<SS_TK2); |
32 | // Set MISO as input
|
33 | DDRB &= ~(1 << MISO); |
34 | // SCK-frequency = f_clkio/64
|
35 | |
36 | SPI_Control_Reg = (1<<SPI_Enable) | (1<<SPI_Master) | (1<<SPR0); |
37 | SPSR &= ~(1<<SPI2X); //disable double SPI speed |
38 | // Set internal pull-up for MISO
|
39 | PORTB |= (1 << MISO); |
40 | // Set all Slaveselect to pull-up
|
41 | PORTE |= (1<<SS_uC) | (1<<SS_TK1) | (1<<SS_TK2); |
42 | }
|
43 | |
44 | void SPI_MasterTransmit(char data) { |
45 | SPDR = data; |
46 | // Wait for transmission complete
|
47 | while(!(SPSR & (1 << SPIF))); |
48 | }
|
49 | |
50 | int main(void) |
51 | {
|
52 | uint8_t dummy_data = 0x22; |
53 | SPI_MasterInit(); |
54 | uint8_t dummy = 0x22; |
55 | //configure Fault-LED (PC0) and Heart-LED (PC2)
|
56 | DDRC |= (1<<PC0) | (1<<PC2); |
57 | |
58 | while(1) |
59 | {
|
60 | PORTE &= ~(1<<SS_uC); |
61 | SPI_MasterTransmit(dummy_data); |
62 | PORTE |= (1<<SS_uC); |
63 | PORTC ^= (1<<PC0); |
64 | _delay_ms(5000); |
65 | }
|
66 | }
|
Slave Code:
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | #include <stdint.h> |
4 | #include <stdio.h> |
5 | #include <math.h> |
6 | #include <util/delay.h> |
7 | #include <avr/eeprom.h> |
8 | |
9 | #define MOSI PB5
|
10 | #define MISO PB6
|
11 | #define SCK PB7
|
12 | #define SS_uC PB4
|
13 | |
14 | #define SPI_Control_Reg SPCR
|
15 | #define SPI_Status_Reg SPSR
|
16 | #define SPI_Data_Reg SPDR
|
17 | |
18 | #define SPI_Enable SPE
|
19 | #define SPI_Interrupt_Enable SPIE
|
20 | #define SPI_Master MSTR
|
21 | #define SPI_Data_Order DORD
|
22 | #define SPI_Clock_Poarity CPOL
|
23 | #define SPI_Clock_Phase CPHA
|
24 | #define SPI_InterruptFlag SPIF
|
25 | |
26 | void SPI_SlaveInit(void){ |
27 | // Set MOSI, SCK and all SS as output
|
28 | DDRB &= ~(1 << MOSI) | (1 << SCK) | (1<<SS_uC); |
29 | // Set MISO as input
|
30 | DDRB |= (1 << MISO); |
31 | // SCK-frequency = f_clkio/64
|
32 | SPI_Control_Reg = (1<<SPI_Enable); |
33 | }
|
34 | |
35 | char SPI_SlaveReceive() |
36 | {
|
37 | // Wait for reception complete
|
38 | while(!(SPSR & (1 << SPIF))); |
39 | // ???
|
40 | return(SPDR); |
41 | }
|
42 | |
43 | int main(void) |
44 | {
|
45 | uint8_t dummy_data = 0; |
46 | SPI_MasterInit(); |
47 | DDRA |= (1<<PA4); |
48 | PORTA &= ~(1<<PA4); |
49 | |
50 | while(1) |
51 | {
|
52 | if(!(PINB & (1<<SS_uC))) |
53 | {
|
54 | dummy_data = SPI_SlaveReceive(); |
55 | }
|
56 | |
57 | if(dummy_data == 0x22) |
58 | {
|
59 | PORTA |= (1<<PA4); |
60 | }
|
61 | |
62 | }
|
63 | }
|