AVR C fråga, bit_is_clear/set vimsig?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
Icecap
Inlägg: 26651
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: AVR C fråga, bit_is_clear/set vimsig?

Inlägg av Icecap »

Bara så du förstår helt klart: när jag skriver 0x03 menar jag inte att man ska skriva '0' 'x' '0' '3', jag menar den hexadecimala representation av värdet 3.

Men i det protokoll jag håller på att skriva kommer jag att skriva värden just HEX-värden som ASCII tecken. Så i protokollet kommer jag att skicka t.ex. tecknet '0' som "30" (då utan ") som representation av värdet 0x30.

Orsaken är att det är enkelt att "sniffa" med ett terminalprogram, det kommer inte en massa "rensa skärmen" eller "plinga" kommandon. Samtidig är det enkelt att kolla om värden är legala (måste ju vara '0'-'9' eller 'A'-'F'). Checksumman är mest för snygghetens skull, jag har oftast med den men använder den aldrig...

Och vad man kan skriva i PHP har knappast betydelse i C eller hur? Jag kan skriva danska flytande (modersmål vettu) men det har knappast betydelse heller när jag programmerar.

Men mitt tips är att du specificerar (för dig själva) vad du behöver av kommandon, vilka värden du vill överföra (min/max, förtecken osv) och sedan klurar ut ett protokoll efter det. Själv är jag ganska säker på att mitt protokoll blir med 16-bit kommandovärden även om de som mest hamnar på kanske 100 vilket ju lätt täcks med 8 bit. Men bara för att vara framtidssäker och för att ha en viss standard.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: AVR C fråga, bit_is_clear/set vimsig?

Inlägg av sodjan »

> men det är främst AVR <-> AVR...

Ja, då har du ju inget problem med att kontroll-tecken "fastnar" i en terminaldriver o.s.v.
Du kan i princip skicka vad du vill mellan USART'arna.

> ...men även vilja skriva ett program på datorn för kommunikation mellan dator och AVR.

Om det gäller samma kommuniktionsgränssnitt så får du tänka till lite.
Det gäller inte samma avväganden o.s.v i detta fall. Det är också viktigt
att *VI* vet vad det är som diskuteras... :-) Jag trodde hela tiden att det
enbart var AVR <-> PC som gällde. Är det AVR <-> AVR så gäller delvis
lite andra avväganden.

Hela frågan om vilken prestanda du behöver är ju inte heller tydlig.

> Jag förstår dock inte riktigt vad du gör med enum?

Skapar ett antal konstanter med värdena 0, 1, 2, 3 o.s.v. Dock saknas det nog ett namn
för datatypen, "enum commands {Command_Ping, Command_Pong, // Anybody out there?"

> Mottagaren kommer ju "se" samma sak oavsett om man skickar ASCII, HEX eller Binärt.. Har jag lärt mig nåt?

Nja, jag är inte helt säker på det (d.v.s på det där sista)... :-)

Du kan inte skicka ASCII, HEX eller binärt. Du skickar alltid *ett värde* som du sedan
kan uttrycka på lite olika sätt, t.ex i ASCII, HEX eller binärt i *din källkod (i detta fall C)*.

Men resultatet blir ju EXAKT DETSAMMA hur du än skriver det.
Som jag sa i ett tidigare inlägg, använd det skrivsätt som är mest rellevant
med hänsyn till vad värdet "står för" (betyder).

Sen så är jag inte en lika övertygad anhängare av STX/ETX som Icecap. :-)
Visst, det finns ASCII kontroll-tecken som heter "Start of text" och "End of text",
men de har värden som gör t.ex debugning med en terminalemulator lite krångligare
eftersom de inte kan visas direkt. Vad som händer (på skärmen) beror på emulatorn...
Men *fungerar* gör det ju i alla fall... :-)

> som använder RS485 kommunikation,

RS485 specar hur det ser ut elektriskt (nivåer) på själva kablen.
Vad man skickar på kabeln är inte standardiserat via RS485.
Du har läst någon kommunikationsstandard som i sig kanske använder RS485.

> som för övrigt verkar rätt död eftersom det inte kommit någon uppdatering på 4-5 år..

Märkligt sätt att se på det! Det finns standards som inte har ändrats på 20-30 år eller
mer (t.ex "ASCII" !) utan att det betyder att det är "dött" på något sätt. Tvärtom, så
kan det tyda på att det hela är moget och välfungerande.

> Men jag gillar själva upplägget och därav själva idén med att jag vill skicka EN byte och
> dela upp denna i bitar där vardera bit står för en inställning.

Det är självklart helt OK, om omständigheterna kräver det eller om det ger andra
fördelar som prestanda o.s.v. Det måste ju du avgöra. Vi har nog bara försökt förslå
något som fungerar praktiskt för en hemmapulare. Gör som du vill och måste.
Det är ju dessutom kanske enkelt att testa bitar på en AVR.

> Men nu har ni i alla fall sett vart jag fått idén ifrån...

Men det visste ju inte vi... :-)
labmaster
Inlägg: 2919
Blev medlem: 5 april 2011, 01:10:25

Re: AVR C fråga, bit_is_clear/set vimsig?

Inlägg av labmaster »

När jag läser din långa text toffie så får jag intrycket av att du rört ihop en del. Det är kanske lätt att det blir så när flera kockar skall ge sitt bidrag till soppan.

Hur som helst, det finns egentligen inget som heter ASCII-tecken. ASCII är en standard för teckenkodning som bland annat stipulerar att tecknet A kodas som värdet 65 decimalt eller 41 hexadecimalt (4 x 16 + 1 = 65). Vilket tecken som grafiskt kommer att visas på displayen beror på vilken teckentabell som används. Använder du exempelvis ett typsnitt som bara har symboler kommer det inte ut något A på displayen när den skall visa tecknet för det binära värdet 41.

Om du kopplar ihop det två AVR:erna med exempelvis RS232 behövs i princip ingen checksumma eller adressfält i databpaketet som du sänder. Är det enkla kommandon räcker det med att du specificerar en fast längd på datapaketet som innehåller själva kommandot och tillhörande argument. Ett exempel kan vara visa ett värde på 8 bitar på port B dör lysdioderna sitter. Datapaketet kan då se ut som följer:

1: Sänd värdet 10 som betyder set portB till värdet i nästa mottagna byte
2: Sänd värdet som skall visas på portB exempelvis AA hexadecimalt

I detta enkla fall med ett kommando i första byten behöver du inte använda fast paketlängd ty du kan låta kommandot styra hur många byt mottagande AVR skall läsa för var kommandokod.

Nar jag debugar ett kommunikationsprotokoll mellan två mikroprocessorer ser jag till att ha dator med debugger till varje mikroprocessor. Ett sätt att slippa debugger på både mottagere och sändare kan vara att skriva ett program som emulerar mottagarsidan och dumpar byte för byte som kommer i kommunikationskanalen i hexformat till ett fönster på en PC. På så sätt kan man försäkra sig att rätt data kommer.

Ett annat sätt kan vara att implementera kommunikationskanalen i samma AVR. Det vill säga bygga både sändande programkod och mottagande programkod i samma AVR under utvecklingsfasen. Då kan man enkelt debugga kommunikationsprotokollet i såväl sändardelen som i mottagardelen. När applikationen sen är färdig är det bara att spitta upp koden i två olika program.

Vill du bygga lite mera avancerade kommunikationsprotokoll som är mera generellt kan det vara bra att använda en teknik man brukar kalla State Machine.

Det du i första hand nu skall koncentrera dig på är att enbart skicka binära värden. Inte ASCII-kodade tecken för motsvarande värden. Det är bara aktuellt om du vill visa värdena på bildskärmen i en terminalemulator.

Jag kanske skall tillägga att du kan visa värdena direkt i ett terminalfönster om du väljer att alltid skicka värden som motsvarar ett skrivbart tecken. Ovanstående kommando för att tända dioderna på portB skulle exempelvis kunna vara värdet 65, då visas ett A i terminalfönstret på PC:n. Detta kan du enkelt göra genom att lägga till konstanten 55 till kommandot med värdet 10. Vill du exempelvis skriva ut 41 HEX på dioderna så kommer det att stå AA i terminalfönstret när du skickar kommandokoden 0x41 och portvärdet 0x41 i två byte till terminalemulatorn. Om du istället vill skicka portvärdet 0x42 så kommer det att stå AB i terminalfönstret. Hänger du med?
Användarvisningsbild
toffie
Inlägg: 1888
Blev medlem: 22 juli 2004, 21:38:07
Ort: Töreboda / Stockholm
Kontakt:

Re: AVR C fråga, bit_is_clear/set vimsig?

Inlägg av toffie »

Icecap
Aha, jag tror att jag förstår ;)

Nu vet jag att ni kommer hoppa på mig, men mycket av det sätt att skriva i PHP kommer ju från C och liknande språk. Upplägget på hur man skriver IF satser, skriver funktioner osv. Sen visst, det ser olika ut och man initierar variabler, char, arrays, int och så vidare på ett annat sätt i C. Det "slipper" man ju göra i PHP. Man har ju dessutom ett par gigabyte att spela med när man programmerar PHP så där gör det oftast inte så mycket om det blir några tecken eller funktioner mer än vad som behövs ;)


sodjan
Ah jo, men anledningen till att det varit ovisst är ju för att jag än så länge bara har kommunicerat mellan PC och en AVR. Så därför har jag ju fått en hel massa problem att handskas med, som om jag bara körde med AVR hade sluppit.. tydligen :P

När det gäller prestanda är det ju inte något som är super-super viktigt.. Jag vill helst bara ha så hög hastighet som möjligt med så lite datamängd som möjligt för att hålla nätet tyst när sändarna och mottagarna är nöjda. När det behövs sändas något så ska det gå fort och helst så rent som möjligt. Det är ju givetvis något man får utveckla med tiden och förbättra allteftersom, men det är mitt "mål".

Ja jo, men det var det jag tänkte med enum. Har inte använt det något direkt tidigare, bara lite exempel för att se hur den fungerade. Men jag tyckte det saknades ett namn :P

Sen är ju frågan, varför man gör så. Det är väl inte samma som att man i toppen av .C filerna definierar, vad heter det.. funktionerna utan själva innehållet?

Kod: Markera allt

void minFunktion(int antal);

..och längre ner på sidan har man själva funktionen..

void minFunktion( int antal )
{
    // saker att utföra..
}
Det är väl inte samma sak?
Jag tänker mig att Icecap använder enum funktionen för att sätta siffror på funktioner som finns tillgängliga som sedan anropas i form med commands[1] när han får in ett paket som STX "01" "02" "32" "xx" ETX, där första delen av kodblocket består av 01. Skulle det kunna stämma eller går det inte att göra så i C?


Nej STX/ETX kanske inte är det bästa, om man ser på kompatibilitet med vanliga terminalemulatorer, men mellan processorerna ska det ju fungera, har jag förstått nu? ;) Man skulle kanske kunna ha 0xFF som start och 0xFE som slut annars? Det blir ju i stort sett samma funktion, bara andra värden som inte har några kontrollfunktioner?


Gällande projektet, ja det är ju ett annat sätt att se på det. Men jag ser det mer som att många delar av det som funnits tillgängligt för projektet inte går att få tag på längre som scheman, kod osv. Endast protokoll-dokumentationen och lite bilder på hur kontrollprogrammet ser ut finns kvar. Det i sig räcker säkerligen för att uppfinna egna moduler som använder samma teknik, inget ont menat.

Men det skulle vara kul om de själva gjorde uppdateringar med ny kod, fler moduler osv :)


Slutligen, jag är enormt tacksam för diskutionerna i denna tråd, jag har lärt mig massor och förhoppningsvis kommer det leda till att andra kan få idéer och tips om hur de ska lösa sina projekt.


Ultimat skulle jag nog helst vilja utveckla det hela utan några problem med tolkningen av data. Det verkar ju inte vara så lätt om man inte ska begränsa sig till vissa tecken som är godkända enligt standard. Så, jag kanske skulle ta och låta AVR'erna prata med varandra bara istället.

Då uppstår ett annat problem, hur jag ska visa inkommande data på en LCD display. Om jag skickar datavärdet som INT så ser jag ju en representation i decimal form... Nej stopp..!


labmaster
Till att börja med, jag förstår hela ditt inlägg fram tills sista 5 raderna.. Det blev lite krångligt ;)
labmaster skrev:...Nar jag debugar ett kommunikationsprotokoll mellan två mikroprocessorer ser jag till att ha dator med debugger till varje mikroprocessor. Ett sätt att slippa debugger på både mottagere och sändare kan vara att skriva ett program som emulerar mottagarsidan och dumpar byte för byte som kommer i kommunikationskanalen i hexformat till ett fönster på en PC. På så sätt kan man försäkra sig att rätt data kommer...
Det är det jag skrivit om tidigare, att jag vill skapa ett sådant program på datorn för kommunikation med AVR kretsarna i samma protokoll som ska köras internt på AVR kretsarna. Det kunde dock bli problem om man skickar kontrollbitarna dec 0-32 i alla fall? Hur som helst, om man skriver ett sådant program, så slutar ju inte användningen bara vid utvecklingen av protokollet, utan kan ju både användas som debugger men även vidare styrning av systemet om så skulle önskas.

Så ett eget program som kan kommunicera med systemet är ju helt klart något jag måste göra, vid något tillfälle :P
labmaster skrev:...Ett annat sätt kan vara att implementera kommunikationskanalen i samma AVR...
Det är ju också ett sätt, fast kanske inte precis lika tydligt på utsidan av kretsen som kanske output till UART alt. LCD skulle kunna vara. Men klart det går, bra sätt att lägga på minnet! :)

State machine känner jag ju igen, det tog ju Icecap upp tidigare tror jag plus att jag förmodligen arbetat med det.. jo i PHP faktiskt.. tror jag.. Hur som helst, givetvis, det används ju för att gå vidare när man känner av exempelvis ett visst tecken eller i mitt fall kanske en viss bit i den inkomna datan.

Just ja,gällande;
labmaster skrev:...Om du kopplar ihop det två AVR:erna med exempelvis RS232 behövs i princip ingen checksumma eller adressfält i databpaketet som du sänder...
Tack vare uppbyggnaden eller funktionen om man kanske ska säga så med ett RS485 nät, som jag ska haka på efter jag utvecklat första delen av protokollet, så kan jag ju hänga på flera moduler på kommunikationslinan. Därav att jag både vill ha CRC och adressfält för att kunna rikta in mig på en specifik modul för en specifik uppgift. Ex. fråga om en specifik modul fortfarande lever :P Eller kanske fråga om temperaturen från just en specifik modul..



Edit..
Vet ni vad.. vet ni vad Atmel kan vara duktiga ibland.. (jag kanske också för att jag använde ögonen och hittade funktionen ;))
Den terminalemulator som finns att ladda ner som ett insticksprogram till AVR Studio, den klarar att visa inkommande data som ASCII, Hex, Dec samt Bin.. Att skicka kan man dock bara göra i Hex och ASCII men det gör det samma.. Nu har jag äntligen den kommunikation som jag behöver för att kunna utveckla det protokoll som jag önskar :D

Helt underbart... heeelt underbart!! :D

Det blir mest säkerligen en hel del frågor till framöver, men nu har jag åtminstone mitt sätt att se det på.. Den representation jag vill se ;) dvs HEX ;)

Men ändå, oavsett om detta inlägg blir slutet på tråden eller inte, så vill jag verkligen tacka alla som medverkat och kommit med inlägg av alla dess slag. Jag är väldigt tacksam för all hjälp, alla råd, tips och idéer. :D

Det roligaste av allt är, när jag får ihop kod så som jag vill ha det så blir det open source, och då kan ni se fram emot att läsa massa kod som ni kan kommentera vidare på ;) Jag ska göra mitt bästa för att ni inte ska hitta några fel ;)
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: AVR C fråga, bit_is_clear/set vimsig?

Inlägg av sodjan »

> ...med så lite datamängd som möjligt för att hålla nätet tyst...

Vilket "nät" ??
Det är ju bara en punkt-till-punkt förbindelse mellan två noder !?

> Jag tänker mig att Icecap använder enum funktionen för att sätta siffror på funktioner som finns tillgängliga som sedan anropas

Nja, jag tolkade det enbart som ett sätt att skapa ett antal konstanter med olika värde.
Dessa kan sedan användas för att testa mot det värde som skickas som "kommando" över linjen.
Om man sedan använder samma enum i båda ändar så får man symboliska namn som är
samma utan att man behöver hantera värderna som sådan direkt.

STX/ETX är helt OK, det är bara jag som inte gillar det. Men glöm det, det är i *helt*
annorlunda miljö... :-)

> Gällande projektet,

Jag har ingen susning om vad "projektet" är. Har det finnits någon länk så har jag
missat det. Har "projektet" någon rellevans för tråden för övrigt ? Eller är det
det som diskuteras i tråden som är "projektet" ?

> Om jag skickar datavärdet som INT så ser jag ju en representation i decimal form...

Fortfarande blandes det frisk utan att det framgår hur du menar. Vad menar du med att
"skicka dataväder som INT" ? Och vad har det med displayen att göra ? Du kan ju visa
precis vad du vill hur du vill med lämplig konvertering.

> Det kunde dock bli problem om man skickar kontrollbitarna dec 0-32 i alla fall?

Det *kan* bli problem, speciellt med standard/enklare terminalemulatorer. De lite mer
professionella emulatorerna har ofta ett "dump" läge där alla tecken inkl de lägsta
32 i ASCII tabellen visas istället för att "exekveras". Det betyder att man får CR på
skärmen istället för att det görs en "return" o.s.v Det finns även fler lite enklare
(sök i forumet t.ex!) terminalprogram just för den typ av tester som du håller på med.
Man kan skapa teststrängar (angivna i hex t.ex) och den kan dumpa allt som kommer
in som hex. Jag ser inte att du behöver siriva något eget bara för att testa
kommunikationen. Om du däremot behöver en "applikation" som gör något mer
utöver den rena terminalfunktionen, så är de så klart en helt annan fråga.

Ser nu nr jag läser vidare att du redan har hittat ett hos Atmel. Jahaja... :-)
Aja, texten ovan (som nu blev lite onödig) får stå kvar i alla fall.
Användarvisningsbild
toffie
Inlägg: 1888
Blev medlem: 22 juli 2004, 21:38:07
Ort: Töreboda / Stockholm
Kontakt:

Re: AVR C fråga, bit_is_clear/set vimsig?

Inlägg av toffie »

sodjan
toffie skrev:Tack vare uppbyggnaden eller funktionen om man kanske ska säga så med ett RS485 nät, som jag ska haka på efter jag utvecklat första delen av protokollet, så kan jag ju hänga på flera moduler på kommunikationslinan. Därav att jag både vill ha CRC och adressfält för att kunna rikta in mig på en specifik modul för en specifik uppgift. Ex. fråga om en specifik modul fortfarande lever Eller kanske fråga om temperaturen från just en specifik modul..
Som du skrev, så kanske du redan har läst detta, men det är vad jag kallar "nätet" ;)

Det med enum, det var så jag tänkte, på ett ungefär ;)

Projektet i sig är inte presenterat än, har ju inte så mycket att visa ännu ;) Denna tråd har största relevans för projektet helt klart eftersom det bygger på kommunikationen. Det är ju första byggstenen :)

Men det kommer mer, i en riktig projekttråd, någon gång framöver :)
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46989
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: AVR C fråga, bit_is_clear/set vimsig?

Inlägg av TomasL »

Med tanke på "vimsigheten" :D , föreslår jag att du läser på lite om kommunikationsprotokoll och elektriska protokoll.
Ett förslag från min sida är att du studerar MODBUS-protokollet, fullständig dokumentation finns att hämta hos modbus.org
Då får du lite grundläggande kunskap om både rena ASCII-protokoll såväl som binära protokoll.

Huruvida du använder RS485 eller inte är fullständigt ointressant för kommunikationsprotokollet, då RS485 enbart är en elektrisk specifikation, vilket talar om spänningsnivåerna på trådarna, och hur en etta eller nolla ser rent elektriskt.
RS485 specificerar också vilken kabel du skall använda.
Användarvisningsbild
toffie
Inlägg: 1888
Blev medlem: 22 juli 2004, 21:38:07
Ort: Töreboda / Stockholm
Kontakt:

Re: AVR C fråga, bit_is_clear/set vimsig?

Inlägg av toffie »

Jodå mer läsning kommer behövas ;) Hade glömt modbus, men ska kolla på det lite mer :)

Men sen är det ju som så att RS485 stödjer att flera noder kopplas in på samma kabelpar, gentemot RS232 som man inte bör koppla in mer än två stycken på.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46989
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: AVR C fråga, bit_is_clear/set vimsig?

Inlägg av TomasL »

Javisst, RS485 är en multidrop-bus. Antingen Simplex (3 trådar) eller Duplex (5 trådar)
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: AVR C fråga, bit_is_clear/set vimsig?

Inlägg av jesse »

Men det är ju fortfarande väldigt svårt att ge någon konkret hjälp när du inte säger vad det är för data du ska skicka, och från vad till vad? Förut fick jag uppfattningen att det skulle skickas kommandon från PC-terminalprogram till AVR, nu är det mellan två AVR, och nånstans mitt i tråden talas det om tecken till en display.... :wacko:

Hur ditt dataprotokoll ska se ut beror givetvis helt på vad som ska skickas, från vad och till vad.

exempel:

om du har en AVR som ska skicka data till en annan AVR för att tända eller släcka fyra lysdioder, då behöver du ju inte krångla med startbyte, hexkoder och stoppbyte. Då skickar du helt enkelt en byte varje gång du vill ändra något på lysdioderna. Låt de sista fyra bitarna motsvara var sin lysdiod och de översta fyra bitarna är nollor.

Om du även vill kunna använda PC-terminal för att skicka/titta på kommunikationen så gör du om det fyra bitarna (som kan bilda ett tal mellan 0 och 15) till en hexadecimal siffra - och skickar den.
'F' tänder alla lysdioder, '0' släcker dem, '3' tänder två av dem osv... Vill man göra det ännu enklare för en användare med PC-terminal så använder du siffrorna 1-8 och tänder lysdioderna en och en med siffrorna '1'-4', och släcker dem med siffrorna '5' till '8'. OBSERVERA DÅ ATT T.EX. SIFFRAN '4' SKICKAS SOM 0x34 (eller 00110100) ENLIGT ASCII-TABELLEN. Fortfarande bara en byte, alltså.

Är det mer komplicerat, så att du ska skicka data, t.ex. temperaturer eller liknande, då kan det vara mer intressant med olika "protokoll".

Om du bara ska skicka en temperatur, och du lyckas skala ner det till åtta bitar, så kan du skicka en byte, precis som i exemplet med lysdioderna - men nu tolkas byten som en signed char - dvs. med decimala värdet -128 till +127. Då får du hela grader.

Ska du skicka ett 16-bitars tal blir det svårare eftersom du måste veta vilken byte som är första och vilken som är den andra. Då kan du ta till timing som ett knep (används bland annat i MODBUS). En paus på t.ex. 10 ms eller mer betyder att nästa byte är "första" byte, lämpligtvis MSB (most significant byte - , höga byten, dvs. bit 15-8 i talet). Andra byten måste då komma direkt efter första, annars räknas det inte.

Att skicka ett 16-bitars tal på detta viset kan göras så här:

Kod: Markera allt

void send_16_bit(uint16_t data) {
    UART_send_byte(data >> 8); // skicka den höga byten.
    UART_send_byte(data & 0xff); // skicka den låga byten.
    _delay_ms(15); // vänta lite mer än 10 ms plus den tid det tar att sända andra byten.
}
Om du ska ha flera kommandon (som det spånades om tidigare i tråden) så kan ditt exempel med startbyte, hexkod (i asciiformat) och stoppbyte vara väldigt bra.

Exempel:
alla "paket" innehåller 12 bytes:

byte 1 : startbyte 0x02
byte 2 : hex: kommando, hög nibble
byte 3 : hex: kommando, låg nibble
byte 4 : hex: argument 1, hög nibble
byte 5 : hex: argument 1, låg nibble
byte 6 : hex: argument 2, hög nibble
byte 7 : hex: argument 2, låg nibble
byte 8 : hex: argument 3, hög nibble
byte 9 : hex: argument 3, låg nibble
byte 10: hex: argument 4, hög nibble
byte 11: hex: argument 4, låg nibble
byte 12: eventuellt stoppbyte 0x03 (behövs egentligen inte)

Här kan man nu låta ett kommando ha ett motsvarande numeriskt värde (i hex):
t.ex:

0x00 start
0x01 stopp
0x02 hello

argument till kommandona:

start: använder de tre argumenten som:
argument 1: motor nummer
argument 2 och 3: bildar ett 16-bitars tal - anger uppstartstid i millisekunder för mjukstart. hög byte först.
argument 4: spelar ingen roll.

stopp: använder de tre argumenten som:
argument 1: motor nummer
argument 2 och 3: bildar ett 16-bitars tal - anger uppstartstid i millisekunder för mjukstart. hög byte först.
argument 4: spelar ingen roll.

Hello använder de fyra argumenten som ascii-tecken som skrivs ut på en display.

Då kan byte-följden se ut så här:

kommando: starta motor nr 16, uppstartstid 1000 ms.
(vi översätter 1000 ms till hexadecimalt och får 03E8).

Kod: Markera allt

byte 1 : 0x02 // startbyte

byte 2 : 0x30 // '0' 
byte 3 : 0x30 // '0'  ---> kommando 00 => start

byte 4 : 0x31 // '1' 
byte 5 : 0x30 // '0' värde 10 hex = 16 decimalt => motor nummer 16.

byte 6 : 0x30 // '0' 
byte 7 : 0x33 // '3' 
byte 8 : 0x3E // 'E' 
byte 9 : 0x38 // '8' ---> värde 03E8 hex = 1000 decimalt => 1000 ms uppstartstid

byte 10: 0x30 // '0'
byte 11: 0x30 // '0' ---> värde 00 hex. värdet används ej i detta kommandot.

byte 12:  0x03 // stoppbyte
kommando "hello": skriv texten "HEJ!"

Kod: Markera allt

byte 1 : 0x02 // startbyte

byte 2 : 0x30 // '0' 
byte 3 : 0x32 // '2'  ---> kommando 02 => hello

byte 4 : 0x34 // '4' 
byte 5 : 0x38 // '8' ---> värde 48 hex = 'H'

byte 6 : 0x36 // '6' 
byte 7 : 0x35 // '5'  värde 65 hex = 'e'
 
byte 8 : 0x36 // '6' 
byte 9 : 0x3A // 'A' --->  värde 6A hex = 'j'

byte 10: 0x32 // '2'
byte 11: 0x31 // '1' --->  värde 21 hex = '!'

byte 12:  0x03 // stoppbyte
Nu är det helt OK med startbyte 0x02 och stoppbyte 0x03, men rent praktiskt vore det bättre om det var koder som kunde skickas med en PC-terminal. I så fall kan man ersätta både startbyte och stoppbyte med 0x0D eller <CR> - koden för "enter" i terminalen. Fixar du så att mottagarprocessorn accepterar en enda 0x0D mellan kommandona så slipper du dessutom att trycka på enter två gånger. Men du kan alltid synka på nytt genom att trycka på "enter" innan du skickar ett kommando. Flera "enter" i rad ska alltså vara tillåtet även om ett "enter" räcker mellan två kommandon.

Detta var bara ett exempel, och dessutom envägskommunikation. Man kan ju tänka sig att den mottagande processorn (som är slav) ska svara på varje kommando med ett likadant paket , fast med t.ex. databyte utbytta mot "svarsdata".... exempelvis kan den svara med den verkliga uppstartstiden när en motor startat. (Då får man räkna med ett par sekunders fördröjning på svaret).

Här är en exempelkod som implementerar ovanstående kommandon:
(skriven på frihand - finns säkert fel i koden)

Kod: Markera allt

struct hexkod {
    unsigned char kod;
    unsigned char arg1;
    unsigned char arg2;
    unsigned char arg3;
    unsigned char arg4;
} kommando;

kommando.startbyte = 0x02;
kommando.stoppbyte = 0x03;

int main {
// skicka kommando starta motor
uint16_t uppstartstid = 1000;
uint8_t motornr = 32;

kommando.kod = 0x00; // starta motor
kommando.arg1 = motornr;
kommando.arg2 = uppstartstid >> 8;
kommando.arg3 = uppstartstid & 0xff;
kommando.arg4 = 0x00;
send_commando();
}

void send_command(void) {
    UART_send_byte(0x02); // skicka startbyte
    uint8_t* datapekare = kommando; // pekar på data-structen.
    uint8_t i, hexkod, databyte;
    for (i=0; i<siezof(kommando); i++) {
        databyte = &datapekare++; // plocka fram data som ska skickas
        hexkod = tillHex(databyte >> 4); // omvandla höga nibble till hexadecimalt tecken.
        UART_send_byte(hexkod); // skicka tecken
        hexkod1 = tillHex(databyte & 0x0f); // omvandla låga nibble till hexadecimalt tecken.
        UART_send_byte(hexkod); // skicka tecken
    }
    UART_send_byte(0x03); // skicka stoppbyte
}
Senast redigerad av jesse 24 juli 2012, 13:10:43, redigerad totalt 2 gånger.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: AVR C fråga, bit_is_clear/set vimsig?

Inlägg av jesse »

TomasL skrev:Javisst, RS485 är en multidrop-bus. Antingen Simplex (3 trådar) eller Duplex (5 trådar)
Hur är det, Tomas, det får väl inte finnas mer än en master, eftersom RS485 driver både nolla och etta, dvs. det blir kortslutning om två noder försöker sända samtidigt (till skillnad från t.ex CANBUS). Då gäller det att mastern har ordning på vem som sänder när, annars går det höga strömmar i onödan.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46989
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: AVR C fråga, bit_is_clear/set vimsig?

Inlägg av TomasL »

Det första du MÅSTE göra är att skriva ned en specifikation på vad du vill göra och vad du vill uppnå.

Nä i alla fall i teorin så kan det bara finnas en master, med MultiDrop-bus menar man en sändare och flera mottagare (eller snarare 1 Master och flera Slavar, där slavarna enbart gör vad de blir tillsagda att göra, dvs de kan aldrig och får aldrig skicka data på bussen om de inte har blivit beordrade att göra så.).
Sedan kan man infoga kollisionsdetektering mm, som till exempel I2C, men eftersom det är en differentiell buss, så blir det lite överkurs.
Användarvisningsbild
Icecap
Inlägg: 26651
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: AVR C fråga, bit_is_clear/set vimsig?

Inlägg av Icecap »

Min anledning att använda enum är att man då undviker att fler kommandon har samma värde. Enum är en funktion som ger de olika element som ingår fortlöpande värden om man inte tvingar dom till andra värden.

Första värdet blir 0, andra värdet blir 1, tredje värdet blir 2 osv. Detta sätt är bra för att undvika trubbel med värden som blir lika osv. Samtidig är det enkelt att infoga fler delar utan att förstöra tidigare värden.
Skriv svar