PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Internes USART-Modul des PIC18F252 nutzen



Adonai
13.04.2007, 15:36
Hallo,

Ich versuche seit einiger Zeit das USART-Modul des PIC18F252 zu nutzen.
Ich möchte eine Kommunikation zwischen 2 PICs aufbauen.
Der Sende-PIC scheint dabei richtig zu funktionieren.
Mit dem Empfangen habe ich noch einige Probleme.
Ich programmiere mit C.
Kann mir da jemand helfen?


Das Sendeprogramm:


//Senden
#include <P18F252.h>

int ring;

void open_serial (void)
{
// Configure UART serial transmit
// Configured for:
// 9600 Baud
// 8N1

// SPBRG - Baud Rate Generator Register
SPBRG = 63; // 20MHz => 9600 baud (BRGH = 0)

// BRGH - High Baud Rate Select Bit
TXSTAbits.BRGH = 0; // (0 = low speed)

// SYNC - USART Mode select Bit
TXSTAbits.SYNC = 0; // (0 = asynchronous)

// TRISC - Tri-state Data Direction Register for port C
// RC6 - 6th pin of port C - used for Serial Transmit
// RC7 - 7th pin of port C - used for Serial Receive
TRISCbits.TRISC6 = 0; // (0 = pin set as output)
TRISCbits.TRISC7 = 1; // (1 = pin set as input)

// SPEN - Serial Port Enable Bit
RCSTAbits.SPEN = 1; // (1 = serial port enabled)

// TXIE - USART Transmit Interupt Enable Bit
PIE1bits.TXIE = 0; // (1 = enabled)

// RCIE - USART Receive Interupt Enable Bit
PIE1bits.RCIE = 0; // (1 = enabled)

// TX9 - 9-bit Transmit Enable Bit
TXSTAbits.TX9 = 0; // (0 = 8-bit transmit)

// RX9 - 9-bit Receive Enable Bit
RCSTAbits.RX9 = 0; // (0 = 8-bit reception)

// CREN - Continuous Receive Enable Bit
RCSTAbits.CREN = 0; // (1 = Enables receiver)

// TXEN - Trasmit Enable Bit
TXSTAbits.TXEN = 1; // (1 = transmit enabled)

// GIE - Global Interrupt Enable Bit
INTCONbits.GIE = 1; // (1 = Enable all unmasked interrupts)

// PEIE - Peripheral Interrupt Enable Bit
INTCONbits.PEIE = 1; // (1 = Enable all unmasked peripheral interrupts)
}

void wait (void)
{
int k;
for(k=0;k<5000;k++);
}

void main (void)
{
ADCON1 = 7;
LATA = 0x00;
TRISA = 0x00;
TRISB = 0xFF;
ring = 0;

while(1)
{
wait();
open_serial();
ring = PORTB;
PORTA = ring;
while(PIR1bits.TXIF)
{
TXREG = ring;
}
}
}


Das Empfangsprogramm:



//Empfangen
#include <P18F252.h>

void open_serial(void)
{
// Configure UART serial transmit
// Configured for:
// 9600 Baud
// 8N1

// SPBRG - Baud Rate Generator Register
SPBRG = 63; // 20MHz => 9600 baud (BRGH = 0)

// BRGH - High Baud Rate Select Bit
TXSTAbits.BRGH = 1; // (0 = low speed)

// SYNC - USART Mode select Bit
TXSTAbits.SYNC = 0; // (0 = asynchronous)

// TRISC - Tri-state Data Direction Register for port C
// RC6 - 6th pin of port C - used for Serial Transmit
// RC7 - 7th pin of port C - used for Serial Receive
TRISCbits.TRISC6 = 0; // (0 = pin set as out)
TRISCbits.TRISC7 = 1; // (1 = pin set as input)

// SPEN - Serial Port Enable Bit
RCSTAbits.SPEN = 1; // (1 = serial port enabled)

// TXIE - USART Transmit Interupt Enable Bit
PIE1bits.TXIE = 0; // (1 = enabled)

// RCIE - USART Receive Interupt Enable Bit
PIE1bits.RCIE = 1; // (1 = enabled)

// TX9 - 9-bit Transmit Enable Bit
TXSTAbits.TX9 = 0; // (0 = 8-bit transmit)

// RX9 - 9-bit Receive Enable Bit
RCSTAbits.RX9 = 0; // (0 = 8-bit reception)

// CREN - Continuous Receive Enable Bit
RCSTAbits.CREN = 1; // (1 = Enables receiver)

// TXEN - Trasmit Enable Bit
TXSTAbits.TXEN = 0; // (1 = transmit enabled)
// GIE - Global Interrupt Enable Bit
INTCONbits.GIE = 0; // (1 = Enable all unmasked interrupts)

// PEIE - Peripheral Interrupt Enable Bit
INTCONbits.PEIE = 1; // (1 = Enable all unmasked peripheral interrupts)
}

void main (void)
{
TRISB = 0x00;
PORTB = 0b01010101;
RCREG = 0;
open_serial();

while(1)
{
if(PIR1bits.RCIF == 1)
{
PORTB = RCREG;
PIR1bits.RCIF = 0;
}
}
}


Danke für die Hilfe. mfg Adonai

Der Gärtner
14.04.2007, 10:56
Hm... Ich habe nichts gefunden im Code, aaaber:
1) Ist das kabel/die Verbindung ausgekreuzt? (TX -> RX und RX -> TX)
2) Da ich zu 99.9% annehme, dass du den C18Compiler nutzt, schau doch mal unter Help/Topics/C18 Compiler/Libraries Da drinnen gibts ne softwarelib zum benutzen der Schnittstelle. machts leichter.
3) Warum eine Serielle schnittstelle?! Das ding hat nen MSSP oben, der kann I2C und SPI. Ist dafür geeigneter...

Adonai
14.04.2007, 17:52
Hallo,

Das Kabel habe ich gekreuzt. Ich habe das Signal auch gemessen und es liegt am korrekten Pin des (Empfänger-)PICs an.
Mit den Libraries von C18 komme ich nicht wirklich klar. Ich habe das ein zwei Mal versucht aber bis jetzt bin ich immer gescheitert.
Warum USART? Schlussendlich soll ein Funkmodul die Kabel ersetzen. Dieses braucht USART.

mfg Adonai

Adonai
17.04.2007, 09:00
Hallo,

Meine Methode zur Abfragung des Empfangs-Byte erfolgt mit Polling.
Ich habe auf www.sprut.de gelesen, dass dies möglich ist.
Kann es sein dass Sprut sich getäuscht hat und das USART-Modul nur mit den Interrupts funktioniert (beim PIC18F252)?

Adonai
18.04.2007, 08:47
Hallo,

Hier die Version des Empfangsprogramm mit Interrupts...
Kommentare fehlen leider, aber ich hoffe es ist einigermassen verständlich.


//Empfangen
#include <P18F252.h> //Bibliothek einbinden
int ring; //Variable definieren
void open_serial(void); //Definition der Unterprogramme
void initINT (void); //Definition der Unterprogramme
void InterruptHandler (void); //Definition der Unterprogramme
void InterruptVektor (void); //Definition der Unterprogramme
#pragma code InterruptVektor = 0x08 //Vektor für hohe Priorität
#pragma code
#pragma interrupt InterruptHandler

void main (void)
{
ADCON1 = 7; //PORTA digital
LATA = 0x00;
TRISA = 0x00; //PORTA als Ausgang
TRISB = 0x00; //PORTB als Ausgang
ring = 0;
RCREG = 90; //Anfangswert RCREG
open_serial(); //USART-Modul konfigurieren
initINT(); //Interrupts konfigurieren
while(1)
{
PORTB = 0xFF; //PORTB auf High setzen
}
}

void open_serial()
{
SPBRG = 103; //Baud-Rate
TXSTAbits.BRGH = 0; //Baud-Rate
TXSTAbits.SYNC = 0; //Asynchrone Übertragung
TRISCbits.TRISC6 = 0; //RB6 als Ausgang
TRISCbits.TRISC7 = 1; //RB7 als Ausgang
RCSTAbits.SPEN = 1; //Seriellen Port aktivieren
TXSTAbits.TX9 = 0; //8-Bit Sendung
RCSTAbits.RX9 = 0; //8-Bit Empfang
RCSTAbits.CREN = 1; //Empfänger aktivieren
TXSTAbits.TXEN = 0; //Sender deaktivieren
PIR1bits.PSPIF = 0; //Laut Datenblatt zu löschen
PIE1bits.PSPIE = 0; //Laut Datenblatt zu löschen
IPR1bits.PSPIP = 0; //Laut Datenblatt zu löschen
RCSTAbits.FERR = 0; //Laut Datenblatt zu löschen
RCSTAbits.OERR = 0; //Laut Datenblatt zu löschen
}

void initINT()
{
PIE1bits.TXIE = 0; //Sende-Interrupt deaktivieren
PIE1bits.RCIE = 1; //Empfangs-Interrupt aktivieren
INTCONbits.GIE = 1; //Globale Interrupt-Freigabe
INTCONbits.PEIE = 1; //Periphere Interupts freigeben
RCONbits.IPEN = 1; //High-Priority Interrupts freigeben
INTCONbits.GIEH = 1; //High-Priority Interrupts freigeben
IPR1bits.RCIP = 1; //Empfangs-Interrupt erhält hohe Priorität
}

void InterruptHandler() //Interrupt-Service-Routine
{
INTCONbits.GIE = 0; //Interrupts deaktivieren
PORTB = 0x00; //PORTB löschen (zeigt dass Interrupt ausgelöst wird)
PORTA = RCREG; //Empfnags-Buffer auslesen
PIR1bits.RCIF = 0; //Flag des Empfangs-Interrupt löschen
INTCONbits.GIE = 1; //Interrupts wieder aktivieren
}

void InterruptVektor (void) //Interrupt-Vektor festlegen
{
_asm
goto InterruptHandler
_endasm
}


edit: Zum besseren Verständnis habe ich noch Kommentare hinzugefügt.