USART PIC18 XC8
Postat: 21 maj 2014, 10:24:12
Så då var det dags för dagens fråga, hoppas ni orkar med mig 
Jag har som sagt en PIC18F45K20 och kör med plib och MPLAB X. Den är på 16MHz och klarar 4x PLL med den interna oscillatorn.
Har suttit hela helgen och fram tills igår och försökt fixa lite buggar med min kod som jag gjort och det visade sig vara en hel del så har kopierat delar av koden till ett nytt projekt för att enklare kunna luska fram vad som är problemet. Jag tror att jag har tre lösningar som jag dock inte lyckas implementera.
1. Skicka kommando för att stänga av all output förutom $GPRMC
2. Skicka kommando för att öka baud rate till 115200 (möjliga är:4800,9600,14400,19200,38400,57600,115200)
3. Sätta PICen i 64MHz läge via PLL
Grunden för min USART kod kommer från:
http://singularengineer.com/programming ... 8f-serial/
Det som fungerar är att läsa av en bokstav i taget och sätta på några LEDs när jag får in en hel $GPRMC och om jag får in en $GPGGA sätta på alla LEDs. Jag har en interrupt på RX. Jag försöker skicka kommandot för att endast få $GPRMC men $GPGGA LEDsen fortsätter att blinka, dvs jag får in båda. Fixas med lösning 2.
Det andra problemet är att jag hela tiden vill parsa NMEA stängarna och skapa upp en struct som innehåller longitude, latitude, speed och en timestamp. Jag vet att min design i koden inte är optimal då jag gör allt detta i min interrupt funktion. Men då detta måste ske innan nästa sträng har kommit så ser jag inte att detta egentligen skulle skapa något problem. Problemet är i alla fall att när jag lägger till funktionen så slutar min interrupt att anropas. Vad detta beror på chansar jag mig till att min kod är för långsam och därför blir det något problem (buffer overflow?). Så tanken är att lösa detta genom öka hastigheten på PICen och baud rate för att ha mer tid på mig helt enkelt. Dvs lösning 1-3. Det fungerar om jag sätter en break point innan den långsamma koden ska köras men bara några gånger.
Det tredje problemet har med de två andra att göra och det är att jag inte lyckas skicka mina kommandon. Min första tanke var att sätta upp USART inkl interrupts och sen skicka mina kommandon. Då det inte fungera tänkte jag att det kan ha något att göra med att RX blockerar min TX. Så min lösning var att öppna upp USART och direkt skicka mina kommandon för att sen sätta på interrupts för RX. Det som hände då var att mina interrupts inte anropades och för att lösa det var jag tvungen att stänga USART och öppna upp den igen.
Så varför kan jag inte skicka data när jag kan ta emot den? USART måste vara helt korrekt uppsatt och jag har dubbelcheckat manualen för kommandona och även denna länk visar att det borde fungera (även om han skickar en (int *) till putsUSART() som jag också testat)
http://adafruit.com/forums/viewtopic.php?f=31&p=179239
Varför dör min USART?
Varför fungerar inte min USART när jag sätter PLLEN = 1? Har självklart ökat min baud till 416 när jag sätter på den, har även testat att ha kvar 113. Min baud rate ska vara 9600 från början.
Koden för USART RX interrupt:
Variabler:
Koden för inläsning av char som skickats från GPSen
Min main:
Kod för initiering av USART
Kod för initiering av GPS
Vart många frågor men hoppas ni orkar läsa igenom allt och kan hjälpa mig att lösa dessa problem!

Jag har som sagt en PIC18F45K20 och kör med plib och MPLAB X. Den är på 16MHz och klarar 4x PLL med den interna oscillatorn.
Har suttit hela helgen och fram tills igår och försökt fixa lite buggar med min kod som jag gjort och det visade sig vara en hel del så har kopierat delar av koden till ett nytt projekt för att enklare kunna luska fram vad som är problemet. Jag tror att jag har tre lösningar som jag dock inte lyckas implementera.
1. Skicka kommando för att stänga av all output förutom $GPRMC
2. Skicka kommando för att öka baud rate till 115200 (möjliga är:4800,9600,14400,19200,38400,57600,115200)
3. Sätta PICen i 64MHz läge via PLL
Grunden för min USART kod kommer från:
http://singularengineer.com/programming ... 8f-serial/
Det som fungerar är att läsa av en bokstav i taget och sätta på några LEDs när jag får in en hel $GPRMC och om jag får in en $GPGGA sätta på alla LEDs. Jag har en interrupt på RX. Jag försöker skicka kommandot för att endast få $GPRMC men $GPGGA LEDsen fortsätter att blinka, dvs jag får in båda. Fixas med lösning 2.
Det andra problemet är att jag hela tiden vill parsa NMEA stängarna och skapa upp en struct som innehåller longitude, latitude, speed och en timestamp. Jag vet att min design i koden inte är optimal då jag gör allt detta i min interrupt funktion. Men då detta måste ske innan nästa sträng har kommit så ser jag inte att detta egentligen skulle skapa något problem. Problemet är i alla fall att när jag lägger till funktionen så slutar min interrupt att anropas. Vad detta beror på chansar jag mig till att min kod är för långsam och därför blir det något problem (buffer overflow?). Så tanken är att lösa detta genom öka hastigheten på PICen och baud rate för att ha mer tid på mig helt enkelt. Dvs lösning 1-3. Det fungerar om jag sätter en break point innan den långsamma koden ska köras men bara några gånger.
Det tredje problemet har med de två andra att göra och det är att jag inte lyckas skicka mina kommandon. Min första tanke var att sätta upp USART inkl interrupts och sen skicka mina kommandon. Då det inte fungera tänkte jag att det kan ha något att göra med att RX blockerar min TX. Så min lösning var att öppna upp USART och direkt skicka mina kommandon för att sen sätta på interrupts för RX. Det som hände då var att mina interrupts inte anropades och för att lösa det var jag tvungen att stänga USART och öppna upp den igen.
Så varför kan jag inte skicka data när jag kan ta emot den? USART måste vara helt korrekt uppsatt och jag har dubbelcheckat manualen för kommandona och även denna länk visar att det borde fungera (även om han skickar en (int *) till putsUSART() som jag också testat)
http://adafruit.com/forums/viewtopic.php?f=31&p=179239
Varför dör min USART?
Varför fungerar inte min USART när jag sätter PLLEN = 1? Har självklart ökat min baud till 416 när jag sätter på den, har även testat att ha kvar 113. Min baud rate ska vara 9600 från början.
Koden för USART RX interrupt:
Kod: Markera allt
void handleUsartRx(){
struct Position position = getPosition();
if(position.fixed != 1){
PIR1bits.RCIF = 0;
return;
}
PIR1bits.RCIF = 0; // clear rx flag
}
Kod: Markera allt
char rx;
char receivedData[100];
int rxIndex = 0;
int led = 0;
Kod: Markera allt
struct Position getPosition(){
while(BusyUSART());
struct Position position;
position.fixed = -1;
rx = ReadUSART(); //read the byte from rx register
if(rx == '$'){
//We got a start char!
rxIndex = 0;
for(int i = 0; i < 100; i++){
receivedData[i] = '\0';
}
}
if(rxIndex < 100){
receivedData[rxIndex] = rx;
rxIndex++;
}else{
rxIndex = 0;
}
if(rx == '\n' && strstr(&receivedData,"$GPRMC")){
//Should calculate checksum first
//if(checksumIsOk())
LATD = led;
led++;
if(led == 0xFF){
led = 0;
}
//denna funktion gör att jag inte får interrupts
//position = createPosition();
}else if(rx == '\n' && strstr(&receivedData,"$GPGGA")){
LATD = 0xFF;
}
return position;
}
Kod: Markera allt
void main(int argc, char** argv) {
SetupClock();
initPic(); //fungerar som den ska
initUsart();
initGps();
//initTimer();
while(1) //infinite loop
{
}
}
Kod: Markera allt
void initUsart(){
TRISCbits.RC6 = 0; //TX pin set as output
TRISCbits.RC7 = 1; //RX pin set as input
CloseUSART();
UART1Config = USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ASYNCH_MODE & USART_EIGHT_BIT & USART_BRGH_HIGH ;
baud = 103;//51 for 8MHz;
OpenUSART(UART1Config,baud);
RCIF = 0; //reset RX pin flag
RCIP = 1; //High priority
RCIE = 1; //Enable RX interrupt
PEIE = 1; //Enable pheripheral interrupt (serial port is a pheripheral)
ei();
}
Kod: Markera allt
void initGps(){
char strr[] = "$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n";
sendCmd(strr);
}
void sendCmd(char *str){
while(BusyUSART());
putsUSART(str);
// while(BusyUSART());
}