[C] Uitleg Pic code*

Pagina: 1
Acties:

  • lamko
  • Registratie: December 2001
  • Laatst online: 20-10-2024
Ik was van plan met een projectje om met de afstandbediening een display aan te sturen dit was ik dan van planmet een pic16f877.
Hier heb ik een mooie website voor gevonden met een werkend concept.
Ik wou dan een philips afstandbediening gebruiken die de rc 5 infrarood code gebruikt.
Hiervan heb ik nu in c een implimentatie van gevonden alleen een paar dingen zijn me hier nog niet helemaal duidelijk ik hoop dat jullie hier even wat licht kunnen bijschijnen ;)
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include<16f877a.h>
#use delay (clock=4000000)
#fuses xt,nowdt,noprotect,noput,nolvp
#use rs232 (Baud=9600,xmit=pin_c6,rcv=pin_c7)                     //RS232 transmission setup
#include"lcd_new.h"                                                                  

int counter,i,com,adr;
int16 buffer;

#int_ext                                                 //interrupt
int_IR()
{
counter=0;                                            //reset counter and buffer
buffer=0;
disable_interrupts(int_ext);                     //disable interrupts

while(!input(pin_b0))                               //wait for high level
 { delay_us(15);
    ++counter; }                                      //time how long has been low
if(counter>=38&&counter<=45)              //if from about 800 to 1000 us
{                                                           //do routines
   delay_us(200);
   for(i=0;i<13;i++)                                   //13 following bits
       {
        if(input(pin_b0))                              //if the input high
          {bit_set(buffer,0);                        //set the LSB and shift left
            buffer<<=1;}
       else                                              //otherwise just shift
            buffer<<=1;
       delay_us(1740);                             //wait for naxt bit
       }
buffer>>=1;                                          //shift 1 right because of last reading
com=buffer&0b00111111;                      //command is 6-bit long; ignore the rest
buffer>>=6;                                           //shift 6 right
adr=buffer&0b00011111;                        //address is 5-bit long; ignore the rest

                                                         //display on an LCD
printf(lcd_putc,"\fAddress:%u\nCommand:%u",adr,com);
printf("A%uC%u",adr,com);              //send bytes to the rs232
delay_ms(150);}                                  //wait
return(0);                                       //return to main
}


main()
{

lcd_init();
while(1)
{
enable_interrupts(int_ext);                       //enable external interrupt
ext_int_edge(H_to_L);                             //falling edge
enable_interrupts(global);                        //enable interrupts
}
}


En dan gaat het me vooral om de interrupt routine hoe het rc 5 protocol gedecodeerd wordt. de bit set en de delay_us snap ik niet kwa werking en berekening.
En nog even een ander vraagje zou ik de infrarood ontvanger z'n stroom kunnen laten trekken vanaf de microcontroller? Ik ga dr vanuit dat dat wel moet lukken want ik heb er ook wel eens een temperatuur sensor aan gehangen!

[ Voor 11% gewijzigd door een moderator op 18-02-2007 13:57 . Reden: code even wat leesbaarder gemaakt door de highlighter te gebruiken :) ]

And this !! Is to go even further beyond!!!


  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 11:26

Reptile209

- gers -

Dit is redelijk rechttoe-rechtaan bitmanipulatie volgens mij.

De functie delay_us(x) bouwt een pauze in van x miliseconden (?) voordat wordt verdergegaan.

De "decodering" bestaat uit het 14 keer uitlezen van een bitwaarde van de pinnen. Als een bit aan staat ( if(input(pin_b0)) ), wordt de LSB (least significant bit, de 2^0 = 1) in buffer op één gezet, anders blijft hij nul. Daarna worden de bits in buffer één positie naar links geschoven (met de << operator, SHL) en wordt een nul rechts ingevoegd. Dat komt neer op vermenigvuldigen met 2. Voorbeeldje: 111 << 1 = 1110, ofwel 7 << 1 = 14. Na die loop wordt buffer weer eentje naar rechts geschoven omdat er een SHL te veel in zit.

Tot slot worden een 6 en een 5 bits deel van buffer gebruikt als command en address.

Zo scherp als een voetbal!


  • lamko
  • Registratie: December 2001
  • Laatst online: 20-10-2024
Maar als ik 38 * 15 doe kom ik nooit op die 800 us waar ze het in het protocol over hebben hoe zit dit dan ?

And this !! Is to go even further beyond!!!


  • lemming_nl
  • Registratie: Juli 2004
  • Niet online
Reptile209 schreef op zondag 18 februari 2007 @ 12:15:
...
De functie delay_us(x) bouwt een pauze in van x milimicroseconden (?) voordat wordt verdergegaan.
...

Geluk is een weerloos oud vrouwtje, alleen op straat met een bom geld


  • lamko
  • Registratie: December 2001
  • Laatst online: 20-10-2024
38 * 15 = 570 us dus dat klopt niet, waarschijnlijk zie ik iets over het hoofd maar in het protocol zoals ook op die website staat gaat het echt over 800 us

And this !! Is to go even further beyond!!!


  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 11:26

Reptile209

- gers -

lamko schreef op zondag 18 februari 2007 @ 13:18:
Maar als ik 38 * 15 doe kom ik nooit op die 800 us waar ze het in het protocol over hebben hoe zit dit dan ?
Als je 800 deelt door 38 en 45, kom je op een tijd tussen de 18 en 21 us per loop. Dat zal wel proefondervindelijk zijn vastgesteld, afhankelijk van de processorsnelheid, de precieze tijd die de delay oplevert (want zo nauwkeurig is de timing niet), het verwerken van het ++counter statement en de loop zelf. Eigenlijk zou je de waarden voor 38 en 45 moeten ijken aan het begin van je programma zodat de snelheid minder afhankelijk van je systeem is.
Voor de werking van de code moet je dus gewoon aannemen dat de pin tussen de 800 en 1000 us laag moet zijn om een geldig commando te genereren.

Zo scherp als een voetbal!


  • lamko
  • Registratie: December 2001
  • Laatst online: 20-10-2024
Zulke tijdafhankelijke dingen heb ik altijd in wat simpele asm code gedaan hier kon je namelijk precies per instructie zien hoelang hij duurde, en was het veel makkelijker om de tijd te bepalen want proefondervindelijk vindt ik ook maar een slechte manier. Vandaar dat ik deze manier niet goed begreep. Hoe zou je zo iets het beste kunnen doen ?
De asm code bekijken wat de c-compiler ervan heeft gemaakt of zou dit met elke kleine aanpassing een heel andere asm code opleveren en dus ook niet erg handig zijn?

And this !! Is to go even further beyond!!!


  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 11:26

Reptile209

- gers -

Op deze pagina zie je wat verschillende mogelijkheden qua timers in een .NET omgeving. Alleen assembly mist, maar het idee is aardig.
Je kunt overigens ook gewoon asm gebruiken in je code via een asm{} blok. Ik weet alleen niet of je jezelf het leven dan niet moeilijker maakt dan nodig is. Met andere woorden: hoe precies zou je timing moeten zijn om een correcte uitlezing te krijgen?

Zo scherp als een voetbal!


  • lamko
  • Registratie: December 2001
  • Laatst online: 20-10-2024
Opzich is deze voorbeeld code precies genoeg alleen hun idee achter het implementeren vindt ik een beetje vaag zoiets had ik dan in een stukje asm gedaan. Maar hoe bepaal je uit c-code hoelang iets gaat duren dat proefondervindelijke vindt ik ook maar niks ;) Tís allemaal embedded en dan stap je eerder over naar asm daarom leek me dat ook veel handiger omdat ik dat altijd met timers heb gedaan in de pic controller. Je kunt per asm instructie gewoon hoeveel cycles een instructie duurd en dan kan je de tijd zo behalen met behulp van je kloksnelheid.

And this !! Is to go even further beyond!!!


  • bobo1on1
  • Registratie: Juli 2001
  • Laatst online: 19-10 00:17
Reptile209 schreef op zondag 18 februari 2007 @ 14:10:
Op deze pagina zie je wat verschillende mogelijkheden qua timers in een .NET omgeving. Alleen assembly mist, maar het idee is aardig.
Je kunt overigens ook gewoon asm gebruiken in je code via een asm{} blok. Ik weet alleen niet of je jezelf het leven dan niet moeilijker maakt dan nodig is. Met andere woorden: hoe precies zou je timing moeten zijn om een correcte uitlezing te krijgen?
Bij seriele protocollen zonder apart clock signaal wordt er meestal gesynchroniseerd aan de hand van een startbit, op het moment dat er een startbit gedetecteerd wordt zit er een delay in van een halve bit zodat er altijd in het midden van het bit gelezen wordt.
Zodoende mag de timing niet meer dan een halve bit afwijken, de echte afwijking is dus afhankelijk van hoeveel bits er na het startbit komen.

Impedance, a measure of opposition to time-varying electric current in an electric circuit.
Not to be confused with impotence.


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 30-11 00:17
lamko schreef op zondag 18 februari 2007 @ 01:13:
En nog even een ander vraagje zou ik de infrarood ontvanger z'n stroom kunnen laten trekken vanaf de microcontroller? Ik ga dr vanuit dat dat wel moet lukken want ik heb er ook wel eens een temperatuur sensor aan gehangen!
Waarschijnlijk kan de up de stroom niet sourcen dus zul je er een opamp oid tussen moeten plaatsen.

edit
zit me nu te bedenken dat je waarschijnlijk al een lichtgevoelig element tussen je opnemer en up hebt zitten dus het kan best zijn dattie al gebuffered is.

edit2

Zit nu ff die code te bekijken maar veel ranziger kan het bijna niet. Je hebt delay routines in een interrupt zitten. Lijkt me mooier om een timer te gebruiken voor de timing van de pulsen, evt gebruik je de external interrupt om de tijden op te slaan, maar bedenk wel dat een interrupt op een pin alleen zinnig is als dit een heel stabiel signaal is ( gefilterd ).

[ Voor 39% gewijzigd door farlane op 19-02-2007 17:29 ]

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • Cafe_de_beuk
  • Registratie: Juni 2002
  • Laatst online: 09-11-2023

Cafe_de_beuk

Biertje?

Lamko,

Ik ga je hier morgen persoonlijk mee helpen @ skool :P

Groet'n

Don't go mad, go linux


  • lamko
  • Registratie: December 2001
  • Laatst online: 20-10-2024
@fariane
Heb je de link gechecked die ik in de topicstart gaf ?
In de Tsop (infraroodontvanger) zit al heel wat flitering heb ik in de datasheet gezien.
Ik heb zelf nul komma nul ervaring met interrupts en nu je dat idee aanbrengt met timers en de interrupt en dan gewoon saven. Dat lijkt me ook veel mooiere code op te leveren, nu je het zegt ;)
Eerst had ik niet eens gezien dat het zulke slechte code was :P ja het was me wel opgevallen dat er niet zoveel controle in zat, alleen de startbit en verder de tijd tussen elke bit maar verder niet echte controle.
En ik las gister ook nog over de werking van interrupts dat je er zo gauw mogelijk weer uit moet dus deze code is wel erg ranzig ja! Maar ook erg snel geschreven, tis net wat je wil.

@ cafe de beuk, dus jonge ek nog mar ff op got sjin ;)
Thanks, maar het gaat er mij om dat ie werkt en dat zal ie vast wel doen :)

And this !! Is to go even further beyond!!!


  • Elijan9
  • Registratie: Februari 2004
  • Laatst online: 01-12 10:22
lamko schreef op zondag 18 februari 2007 @ 13:30:
38 * 15 = 570 us dus dat klopt niet, waarschijnlijk zie ik iets over het hoofd maar in het protocol zoals ook op die website staat gaat het echt over 800 us
De rest van de loop geeft waarschijnlijk die overhead... Het is maar een PIC. ;)

War is when the young and stupid are tricked by the old and bitter into killing each other. - Niko Bellic

Pagina: 1