Hi, ich habe einen ATTiny2313 und versuche dort über USI ein Signal an meinen Rechner zu schicken. ich hatte im Internet Beispiele zu Ähnlichen µC's gefunden und habe so folgendes Programm geschrieben. Hab dort aber bereits in der Simulation das Problem, das ich das USISR-Register nicht setzten kann. (Dieses benötige ich um den Überlauffläg zu löschen. Hier das von mir geschriebene Programm: #include <avr/io.h> #include <stdlib.h> #include <util/delay.h> void SPI_init(void) { //Eigene Initialisierung WatchDog MCUSR =0; MCUCR = 0x80; //JTAG abschalten MCUCR = 0x80; DDRA |= (1<<PB7)|(1<<PB6); //Output: PB7=USCK, PB6=DO DDRA &= ~(1<<PB5); //Input: PB5=DI DDRA |= (1<<PD5); //LED auf Ausgang USICR = (1<<USIWM0) | (1<<USICLK)|(1<<USITC)| (1<<USICS1); // USIWM0 = 1: SPI-Betrieb mit DO, DI und USCK // USICLK = 1, USITC = 1, USICS1 = 1: generiert den Taktimpuls für das Schieberegister und // den 4bit Timer. Der Takt wird am USCK-Pin (PA4) ausgegeben. } void SPI_transfer(int data) { USIDR = data; //Daten in Data Register laden USISR = (1<<USIOIF); //Überlaufflag löschen while (!(USISR & (1<<USIOIF))) //solange kein Timerüberlauf... { USICR |= (1<<USITC); //Toggle clk (2x) USICR |= (1<<USITC); } } int main (void) { SPI_init(); while(1) { SPI_transfer(0x41); // Daten (A) senden PORTA |= (1<<PD5); // Led on _delay_ms(100); PORTA &= !(1<<PD5); // Led off _delay_ms(100); } } Hat jemand eine Idee wo der Fehler sein könnte? Gruß Anthony
Tach Anthony, > SICR |= (1<<USITC); du willst hier ein xor haben: > SICR ^= (1<<USITC); Thor
Die Zeile > USICR |= (1<<USITC); funktioniert als XOR. Das Problem das ich habe, ist das er in der Zeile > USISR = (1<<USIOIF); //Überlaufflag löschen den Wert für USIOIF nicht setzt. Das USISR Register bleibt komplett leer. Gibts es dafür eine Erklärung
> den Wert für USIOIF nicht setzt. Das USISR Register bleibt komplett > leer. Das ist richtig so. Das sind flags. Die werden von der Hardware gesetzt und müssen durch schreiben einer 1 zurück gesetzt werden. Wenn du da eine 1 reinschreibst wird das bit also zurück gesetzt! Thor
OK, verständlich. Aber dann würde die while-schleife nie beendet werden. (Was bei mir auch der Fall ist) Zudem habe ich diese Whileschleife mit genau den befehlen öfters im Internet gesehen. Ist der Code dann so Falsch? Und wenn ja wie würde es Richtig gehören? Schonmal Danke Anthony
Mhh, ich sehe grade, dass USITC auch eine flag ist. Das bedeutet, dass das bit ebenfalls selbstständig zu 0 zurück kehrt. Das |= wirkt also nicht als xor sondern schreibt einfach nur eine 1 in USITC, während es sich selbst zurücksetzt. Ich muss da nochmal drüber nachdenken. Ist schon zu spät um das jetzt noch zu lösen. Bis morgen. Thor
Hi, hat den vieleicht noch jemand anders der auch schonmal mit USI gearbeitet hat eine Idee wo hier der Fehler sein könnte? Gruß Anthony
Hab schonmal einen großen Fehler gefunden. Bei der Initialisierung sowie an ein paar anderen stellen, habe ich beim übernehmen des Codes nicht alle > PORTA in PORTB etc. umgeändert. Jedoch hat sich in der Simulation nichts geändert: -> weiterhin das Problem, das er dort nicht aus der Whileschleife wieder rauskommt. Programmiere ich allerdings den µC mit dem Code: -> die LED blinkt -> er scheint doch aus der Whileschleife raus zu kommen. Ich kann allerdings weder am Oszi noch am Rechner (verbunden über USB TTL Serial Kabel) ein Signal erkennen. Lediglich ein Rauschen um den Nullpunkt herrum. Vieleich noch einen Idee? Gruß Anthony
> (1<<USICS1)
Bedeutet, trigger auf external positiv edge. Das ist richtig. Du
solltest aber auch noch USICLK setzen. UU wird sonst der counter nicht
imkrementiert.
Thor
Soll ich USICLK noch an irgend einer anderen stelle setzten? Denn in der Initialisierung habe ich doch bereits gesetzt. Anthony
Nein außer beim init brauchst du das nicht zu setzen. Aber warum toggelst du eigentlich schon beim init USITC? Äham, wo ich mir deine post grade noch mal so duch lese: Du hast gemerkt, dass du einige PortA statt PortB stehen hast aber hast du auch gemerkt, dass das auch für die DDRs gilt? Thor
Ja das hatte ich auch gemerkt. Das hab ich alles ausgebessert. Habs jetzt dazu gebracht, das ich das Signal am Oszi sehe, allerdings kommt an meinem zweiten Mikrocontroller noch nichts an. Ich glaube das der Fehler irgendwas damit zu tun hat das ich beide µCs als Master programmiert habe. Weißt du was ich genau Einstellen muss um einen als Slave zu programmieren? Reicht es wenn ich folgende Implementierung mache?: > DDRA |= (1<<PB7)|(1<<PB6); //Output: PB7=USCK, PB6=DO > DDRA &= ~(1<<PB5); //Input: PB5=DI > DDRA |= (1<<PD5); //LED auf Ausgang > USICR = (1<<USIWM0)|(1<<USICS1); Nochmal vielen Dank für die bisherige Hilfe Gruß Anthony
Du hast immer noch DDRA da stehen. Das macht mich etwas nervös. Ansonsten musst du um beide µC zu verketten an deinem setup kaum etwas verändern. Die DDRs von DO und DI bleiben gleich. Du musst aber bedenken, dass DO und DI gekreuzt werden müssen. Auch das setting von USICR bleibt gleich: external clock source. Nur das DDR von USCK muss aus, weil nur der master die clock treibt. Thor
OK, da war jetzt der Fehler ich hatte "USCK" noch als output eingestellt. >Hab jetzt aber ein Problem mit meinem Probeprogramm. Ich hatte dieses so Programmiert das: -der eine µC_1 "UART" Signale erhält und diese über "USI" wieder ausgibt -der anderen µC_2 die ausgegebenen "USI" Signale erhält und diese über "UART" wiederum ausgibt Die beiden UART Schnittstellen sind am Rechner angeschlossen, sodass ich von dort die Signale Senden und Empfangen kann. >Jetzt habe ich folgendes Problem: -Endet das zu Sendene Signal auf 0 ("B" ; 0x42 ; 0100 0010) kommt es einwandfrei an -Endet das zu Sendene SIgnal auf 1 ("A" ; 0x41 ; 0100 0001) kommt irgendwas an >FRAGE1: Eine Idee woran das liegen könnte? (Ich hatte dazu feststellen können, das der µC_2 ZWEI Byte rauschickt obwohl er eigendlich nur EINEN Byte erhalten haben sollte) >FRAGE2: Da ich ja jetzt beim µC_2 die Clock (USCK) auf input gestellt habe stellt sich mir dort jetzt die Frage: -Wie kann der µC_2 der die Clock als Input hat Signale rauschicken ohne selber die Clock zu erzeugen? Gruß Anthony
> Eine Idee woran das liegen könnte? > (Ich hatte dazu feststellen können, das der µC_2 ZWEI Byte > rauschickt obwohl er eigendlich nur EINEN Byte erhalten haben > sollte) Uff, das war jetzt etwas kurz. Mit "irgendwas" meist du reproduzierbar "irgendwas"? > Da ich ja jetzt beim µC_2 die Clock (USCK) auf input gestellt > habe stellt sich mir dort jetzt die Frage: > -Wie kann der µC_2 der die Clock als Input hat Signale rauschicken > ohne selber die Clock zu erzeugen? Du meinst SPI seitig. Das clocking des USI läuft bei master und slave genau gleich. Beide holen sich die clock vom USCK pin rein. Nur muss klar sein wer die clock erzeugt und das ist halt der master. Deshalb hat der master das DDR auf und der slave zu. Thor
>Uff, das war jetzt etwas kurz. Mit "irgendwas" meist du reproduzierbar >"irgendwas"? Habs mir gerade nochmal genauer angeschaut: Er scheint das Ganze Signal um EINE Stelle zu Verschieben und ein High ans Ende zu hängen. --> Aus ("A" ; 0x41 ; 0100 0001) Wird ("ƒ" ; 0x83 ; X100 0001 1) --> Aus ("C" ; 0x43 ; 0100 0011) Wird ("‡" ; 0x87 ; X100 0011 1) Eine Idee?
Das ist doch schon mal ein Anfang. Zeig mal wie du den UART initialisierst. Thor
>DAS wär jetzt das Komplette Programm von beiden µCs >Receive_UART_Transmit_USI #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> /* Prototypes */ void InitUART (unsigned char baudrate); void InitUSI (void); unsigned char ReceiveUART (void); void TransmitUSI (uint8_t data); // Main - simple program that Transmit Data main (void) { InitUART(12); /* Set the baudrate to 4.8k bps using a 1MHz crystal */ InitUSI(); while (1) { TransmitUSI(ReceiveUART()); } } /* Initialize UART */ void InitUART (unsigned char baudrate) { //Eigene Initialisierung WatchDog MCUSR =0; //JTAG abschalten MCUCR = 0x80; MCUCR = 0x80; /* Set the baud rate */ UBRRL = baudrate; /* Enable UART receiver and transmitter */ UCSRB = (1 << RXEN) | (1 << TXEN); /* 8 data bits, 1 stop bit */ UCSRC = (1 << UCSZ1) | (1 << UCSZ0); } void InitUSI(void) { //Eigene Initialisierung WatchDog MCUSR =0; //JTAG abschalten MCUCR = 0x80; MCUCR = 0x80; //Eigene Initialisierung (Outputs) DDRD |= (1<<PD5); //Output: PB7=USCK, PB6=DO DDRB |= (1<<PB7)|(1<<PB6); //Input: PB5=DI DDRB &= ~(1<<PB5); // USIWM0 = 1: SPI-Betrieb mit DO, DI und USCK // USICLK = 1, USITC = 1, USICS1 = 1: generiert den Taktimpuls für das Schieberegister und // den 4bit Timer. Der Takt wird am USCK-Pin (PB7) ausgegeben. USICR = (1<<USIWM0) | (1<<USICLK) | (1<<USITC) | (1<<USICS1); } void TransmitUSI (uint8_t data) { //Daten in Data Register laden USIDR = data; //Überlaufflag löschen USISR = (1<<USIOIF); //solange kein Timerüberlauf... while (!(USISR & (1<<USIOIF))) { //Toggle clk (2x) USICR |= (1<<USITC); USICR |= (1<<USITC); } PORTD |= (1<<PD5); // Led on _delay_ms(1000); PORTD &= !(1<<PD5); // Led off _delay_ms(1000); } unsigned char ReceiveUART(void) { /* Wait for incomming data */ while (!(UCSRA & (1 << RXC))); return UDR; } >Receive_USI_Transmit_UART #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> /* Prototypes */ void InitUART (unsigned char baudrate); void InitUSI (void); unsigned char ReceiveUSI (void); void TransmitUART (unsigned char data); // Main - simple program that Transmit Data main (void) { InitUART(12); /* Set the baudrate to 4.8k bps using a 1MHz crystal */ InitUSI(); while (1) { TransmitUART(ReceiveUSI()); } } /* Initialize UART */ void InitUART (unsigned char baudrate) { //Eigene Initialisierung WatchDog MCUSR =0; //JTAG abschalten MCUCR = 0x80; MCUCR = 0x80; //Eigene Initialisierung (Outputs) DDRD |= (1<<PD5); /* Set the baud rate */ UBRRL = baudrate; /* Enable UART receiver and transmitter */ UCSRB = (1 << RXEN) | (1 << TXEN); /* 8 data bits, 1 stop bit */ UCSRC = (1 << UCSZ1) | (1 << UCSZ0); } void InitUSI(void) { //Eigene Initialisierung WatchDog MCUSR =0; //JTAG abschalten MCUCR = 0x80; MCUCR = 0x80; //Output: PB6=DO DDRB |= (1<<PB6); //Input: PB5=DI DDRB &= ~(1<<PB5); //Input: PB7=USCK DDRB &= ~(1<<PB7); // USIWM0 = 1: SPI-Betrieb mit DO, DI und USCK // USICLK = 1, USITC = 1, USICS1 = 1: generiert den Taktimpuls für das Schieberegister und // den 4bit Timer. Der Takt wird am USCK-Pin (PB7) ausgegeben. USICR = (1<<USIWM0)|(1<<USICS1); } void TransmitUART (unsigned char data) { /* Wait for empty transmit buffer */ while (!(UCSRA & (1 << UDRE))); /* Start transmittion */ UDR = data; PORTD |= (1<<PD5); // Led on _delay_ms(1000); PORTD &= !(1<<PD5); // Led off _delay_ms(1000); } unsigned char ReceiveUSI(void) { //Wait for incomming data while(USIDR == 0x00); //Pass Data to returnData unsigned char returnData = USIDR; //Delete Data in USIDR USIDR = 0x00; //Return the data return returnData; }
Also erstmal könntest du das setzen der DDRs beim µC2 noch zusammen fassen. Die DDRs von PB5 und PB7 sind immerhin im selben Register. Dein Problem könnte sein, dass du die Beendigung des Empfangs beim µC2 durch das bloße Prüfen auf Verschiedenheit von null beurteils. Leider ist USIDR aber nicht gepuffert und es kann daher dazu kommen, dass deine Warteschleife zu früh abbricht. Trigger am besten auf den counter overflow. Der sagt dir zuverlässig, wann der shfit fertig ist. Thor
Das wars, jetzt funktioniert es. Vielen Dank für deine Hilfe, hast mir echt gut weiter geholfen. Gruß Anthony
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.