PIC18, UART, autokompensera OSCTUNE, behöver hjälp. *LÖST*
PIC18, UART, autokompensera OSCTUNE, behöver hjälp. *LÖST*
Håller på med en grej som jävlas ganska mycket med mig.
Kommunikation över 25m kabel, jag har vald RS485. Den bit fungerar riktigt bra. Det rör sig om blockar på 66 bytes med mellan 1 och 30 sekunders mellanrum, vänttiden är ställbar. Blocken har checksum och skulle ett eller fler block kastas är det inte livet om att göra, så länge det inte är för många.
En kristallstyrd µC sänder på 9615 baud och i andra ändan kommer problemet.
Jag har en PIC18F1320 till att ta emot, har ingen kristall och den interna oscillator ska klara biffen. RS485-delen är avklarat och när jag ställer OSCTUNE lite högre än noll fungerar skiten men det är inget jag vågar lita på i framtiden. Alltså skulle jag gärna vilja att skiten på något vis kunde avkänna att UART'en tar emot men att det blir fel och att programmet då autokompenserar OSCTUNE till det är i mål.
Mitt största problem är just nu att jag kom hen ganska sent igår och då detta problem jävlades med mig satt jag ett tag med detta och 04:30 kunde jag inte sova längre av tankarna på detta jävelskap så nu tänker jag mig ta en filt o lägga mig en liten stund på soffan medan jag undrar:
Någon som har något exempel på hur jag kan göra?
Jag har en rutin som kan "zig-zagga" sig fram till rätt OSCTUNE vid att kallas när det blir fel, jag har en rutin som avkänner att en block har time-out men problemet verkar vara att UART-Rx slutar ge interrupt vid framing error eller vad som sker. Och då jag knappast kan vara ensam om detta problem skulle jag uppskatta lite tips om sättet att gå framåt.
Om inte jag får det får jag använda en del tid på att definiera vad som händer och inte händer varefter jag kan lösa problemet men skulle någon redan ha gjort detta jobb skulle jag gärna vilje nasa lite på det...
Kommunikation över 25m kabel, jag har vald RS485. Den bit fungerar riktigt bra. Det rör sig om blockar på 66 bytes med mellan 1 och 30 sekunders mellanrum, vänttiden är ställbar. Blocken har checksum och skulle ett eller fler block kastas är det inte livet om att göra, så länge det inte är för många.
En kristallstyrd µC sänder på 9615 baud och i andra ändan kommer problemet.
Jag har en PIC18F1320 till att ta emot, har ingen kristall och den interna oscillator ska klara biffen. RS485-delen är avklarat och när jag ställer OSCTUNE lite högre än noll fungerar skiten men det är inget jag vågar lita på i framtiden. Alltså skulle jag gärna vilja att skiten på något vis kunde avkänna att UART'en tar emot men att det blir fel och att programmet då autokompenserar OSCTUNE till det är i mål.
Mitt största problem är just nu att jag kom hen ganska sent igår och då detta problem jävlades med mig satt jag ett tag med detta och 04:30 kunde jag inte sova längre av tankarna på detta jävelskap så nu tänker jag mig ta en filt o lägga mig en liten stund på soffan medan jag undrar:
Någon som har något exempel på hur jag kan göra?
Jag har en rutin som kan "zig-zagga" sig fram till rätt OSCTUNE vid att kallas när det blir fel, jag har en rutin som avkänner att en block har time-out men problemet verkar vara att UART-Rx slutar ge interrupt vid framing error eller vad som sker. Och då jag knappast kan vara ensam om detta problem skulle jag uppskatta lite tips om sättet att gå framåt.
Om inte jag får det får jag använda en del tid på att definiera vad som händer och inte händer varefter jag kan lösa problemet men skulle någon redan ha gjort detta jobb skulle jag gärna vilje nasa lite på det...
Senast redigerad av Icecap 30 augusti 2012, 13:02:51, redigerad totalt 1 gång.
Re: PIC18, UART, autokompensera OSCTUNE, behöver hjälp.
Kan du inte definiera interrupt om pin-change eller liknande och sedan mäta tiden för bitarna med en noggrann timer?
Måste visserligen vara säker på att man är inom en Byte och inte mellan Bytes när man mäter tiden.
Måste visserligen vara säker på att man är inom en Byte och inte mellan Bytes när man mäter tiden.
Re: PIC18, UART, autokompensera OSCTUNE, behöver hjälp.
OK, svarar mig själv - utan att vara så värst mycket mer pigg för det...
Jag har startat en Timer2-interrupt som ger mig ~50Hz interrupt. PR2 = 249; T2CON = 0x4E; och sedan slå på T2IE-bitten.
#define BLOCK_TIMEOUT 5
unsigned char BlockTimer;
Timer2-ISR gör:
TMR2IF_Bit = false; // Clear interrupt bit
if(Block_Timer) if(!--Block_Timer) Timed_Out = true; // Flip timeout if it came
För varje UART-Recieve interrupt:
Block_Timer = BLOCK_TIMEOUT;
Alltså kommer Timed_Out att bli sann mellan 80ms och 100ms efter sista byte har tagits emot - men ENBART om man inte ställer Block_Timer till 0.
Alltså kollar programmet blocket och ser om start, stopp och checksum är rätt, om det är så nollas Block_Timeout varför inte Timed_Out aktiveras om allt är OK.
Men när det INTE är OK? Jorå, då kommer grejen som ligger i main-loop'en:
Principet: Om en block timas ut betyder det att det blev någon fel på vägen, man kan såklart bestämma vilka fel som accepteras och vilka som ska sållas bort. Jag har saxat lite i koden ovan för att ta bort saker som jag inte ser som nödvändiga i denna beskrivning.
För varje Timed_Out som kommer där Err_Flag är satt kommer rutinen att börja på noll (Deviation = 0; vid power-on) och sedan öka på den ett steg åt gången men först testa att öka OSCTUNE, därnäst minska OSCTUNE om det inte hjälper heller. För varje steg där den har testat båda att öka och minska kommer den att öka på Deviation 1 steg och sedan köra igen.
Hunting-variablen anger om den är "i lås" eller om det fortfarande är skit i kommunikationen, när den blir falsk är den i lås.
Det kan nog göras mer elegant men detta fungerar för mig, jag har testat att ändra OSCTUNE till ett för högt värde vid uppstart för att se om FERR återkom - och det gjorde det. Alltså borde denna rutin, på ett lite grovt sätt, återkalibrera allt eftersom temperatur & ålder får INTOSC att glida iväg.
Jag har inte sett någon indikation på om INTOSC har för låg kontra för hög frekvens och egentligen skulle man väl hitta första steg som fungerar OK och sedan öka/minska till det inte fungerar igen och sedan ta mitten - men jag ids inte! Inte nu iaf.
Till mitt bruk kommer detta att fungera helt OK så det får räcka för nu. Jag har kopplat OSCOUT till min frekvensräknare och kan se hur frekvensen hoppar för varje ändring så jag är nöjd.
EDIT: Oj, Andax kom mellan.
Jag är inte sugen på att börja lägga in en Capture-funktion, jag hade funderat över det men jag skippade det, PIC'en ska <option> kunde svara tillbaka på RS485-bussen varför det vore bäst att ställa in timingen rätt från början. Detta kunde jag göra med Capture-modulen men det skulle bli en del pill med det...
Jag har startat en Timer2-interrupt som ger mig ~50Hz interrupt. PR2 = 249; T2CON = 0x4E; och sedan slå på T2IE-bitten.
#define BLOCK_TIMEOUT 5
unsigned char BlockTimer;
Timer2-ISR gör:
TMR2IF_Bit = false; // Clear interrupt bit
if(Block_Timer) if(!--Block_Timer) Timed_Out = true; // Flip timeout if it came
För varje UART-Recieve interrupt:
Block_Timer = BLOCK_TIMEOUT;
Alltså kommer Timed_Out att bli sann mellan 80ms och 100ms efter sista byte har tagits emot - men ENBART om man inte ställer Block_Timer till 0.
Alltså kollar programmet blocket och ser om start, stopp och checksum är rätt, om det är så nollas Block_Timeout varför inte Timed_Out aktiveras om allt är OK.
Men när det INTE är OK? Jorå, då kommer grejen som ligger i main-loop'en:
Kod: Markera allt
Alla variabler är unsigned char;
unsigned char Toggle, Hunting, Deviation;
if(Timed_Out)
{
Timed_Out = false; // OK, got it!
if(FERR_Bit)
{ // Has UART gotten framing error due to wrong INTOSC-speed?
CREN_Bit = true; // To clear FERR
Err_Flag = true;
}
if(Err_Flag)
{
Hunting = true;
Err_Flag = false;
switch(++Toggle)
{
case 0:
OSCTUNE = Deviation;
break;
default:
OSCTUNE = -Deviation;
Toggle = 255; // Makes it go zero when incremented next time
if(Deviation < 31) Deviation++;
else Deviation = 0;
}
}
}
För varje Timed_Out som kommer där Err_Flag är satt kommer rutinen att börja på noll (Deviation = 0; vid power-on) och sedan öka på den ett steg åt gången men först testa att öka OSCTUNE, därnäst minska OSCTUNE om det inte hjälper heller. För varje steg där den har testat båda att öka och minska kommer den att öka på Deviation 1 steg och sedan köra igen.
Hunting-variablen anger om den är "i lås" eller om det fortfarande är skit i kommunikationen, när den blir falsk är den i lås.
Det kan nog göras mer elegant men detta fungerar för mig, jag har testat att ändra OSCTUNE till ett för högt värde vid uppstart för att se om FERR återkom - och det gjorde det. Alltså borde denna rutin, på ett lite grovt sätt, återkalibrera allt eftersom temperatur & ålder får INTOSC att glida iväg.
Jag har inte sett någon indikation på om INTOSC har för låg kontra för hög frekvens och egentligen skulle man väl hitta första steg som fungerar OK och sedan öka/minska till det inte fungerar igen och sedan ta mitten - men jag ids inte! Inte nu iaf.
Till mitt bruk kommer detta att fungera helt OK så det får räcka för nu. Jag har kopplat OSCOUT till min frekvensräknare och kan se hur frekvensen hoppar för varje ändring så jag är nöjd.
EDIT: Oj, Andax kom mellan.
Jag är inte sugen på att börja lägga in en Capture-funktion, jag hade funderat över det men jag skippade det, PIC'en ska <option> kunde svara tillbaka på RS485-bussen varför det vore bäst att ställa in timingen rätt från början. Detta kunde jag göra med Capture-modulen men det skulle bli en del pill med det...
Senast redigerad av Icecap 30 augusti 2012, 13:31:41, redigerad totalt 1 gång.
Re: PIC18, UART, autokompensera OSCTUNE, behöver hjälp.
Du kan inte använda rutinen som beskrivs under "16.2.3 AUTO-BAUD RATE DETECT"? Låter ju som rätt grej men har inte tid att läsa så ingående just nu.
Re: PIC18, UART, autokompensera OSCTUNE, behöver hjälp.
Kollade på den också men då jag inte kan be sändaren skicka 0x55-tecken lite hur som helst fungerar det inte heller. Samtidig ställer den bara baudrate-registerna rätt, inte OSCTUNE vilket betyder att baudrate-generatorn står bäst möjligt men ändå kan felet vara för stort för att fungera rätt.
Re: PIC18, UART, autokompensera OSCTUNE, behöver hjälp.
Om man bortser från att OSCTUNE har högre upplösning så spelar det väl ingen roll om du ändrar på baudrate eller OSCTUNE. Syfte är ju att ändra bitlängden så att den inte avviker mer än 2% av specade tiden.
Edit:
Nu vet jag ku inte vad den där auto baud funktionen har för upplösning. Den kan kanske bara sätta baudrate i steg om tex 4800, 9600 etc
Edit:
Nu vet jag ku inte vad den där auto baud funktionen har för upplösning. Den kan kanske bara sätta baudrate i steg om tex 4800, 9600 etc
Re: PIC18, UART, autokompensera OSCTUNE, behöver hjälp.
Jo, den kan gå "mellan stolarna" men det hjälper inget när jag inte kan få sändaren att sända 0x55 som är den synkroniseringskaraktär som behövs.
Re: PIC18, UART, autokompensera OSCTUNE, behöver hjälp.
Eftersom man inte vet tiden mellan varje tecken med säkerhet Och att paketen kommer ganska sällan så känns det som att man bör mäta på varje tecken för att det ska bli bra.