Toon posts:

De μC programmers Kroeg

Pagina: 1 2 Laatste
Acties:

Onderwerpen


  • RobV
  • Registratie: juni 2013
  • Niet online

RobV

Welcome to the grid, Program.

Topicstarter
(overleden)
Via de EL Kroeg kwam de suggestie om een μCPU programmer kroeg te starten. Wat houdt dat in?
  • μC is microProcessor, dus niet per sé de programmeertaal C.
  • Stel je vraag over bugs, performance, optimalisatie, settings.
  • Dit is de software-kroeg, van weerstandjes, torretjes en caps hebben we geen verstand (nou ja, ik niet)
  • We hebben het hier over microProcessor talen. Dus geen Java, PHP, C#, Swift, en andere desktop-based talen. Daarvoor verwijs ik graag naar het Tweakers Programming forum
  • zelf kan ik helpen met C/C++ maar er zijn ongetwijfeld tweakers die PiCbasic en Processing goed beheersen.
  • Als je een vraag hebt, vertel dan
    1. duidelijk je probleem en de omgeving,
    2. wat heb je al geprobeerd en
    3. toon zoveel mogelijk (relevante) code.
  • gebruik de code tags voor code. Als je moet quoten, quote dan selectief.
  • houdt het gezellig!

[Voor 14% gewijzigd door RobV op 09-03-2015 20:52]

 | Mijn joystick / simpit project | Blog | Elite Dangerous CMDR Cataclysm72


  • Wolfboy
  • Registratie: januari 2001
  • Niet online

Wolfboy

ubi dubium ibi libertas

Leuk idee, μC implementaties hebben vaak wel wat vervelende haken en ogen (eerste keer had ik wel issues toen m'n variabelen na het re-runnen van m'n programma nog steeds gevuld waren).

Blog [Stackoverflow] [LinkedIn]


  • conara
  • Registratie: februari 2010
  • Laatst online: 08-12 22:03
Interessant! Ga dit topic zeker in de gaten houden. Ik neem aan dat dit ook dé plek is om te praten over de verschillende microcontrollers en er geholpen kan worden met keuzes m.b.t. microcontrollers.

Zelf heb ik veel gewerkt met de 8-bitters van Atmel, maar ben nu van plan om te werken met de 32-bit van Atmel (niet ARM, maar hun eigen architectuur). Reden waarom ik eigenlijk kies voor een 32-bit van Atmel is, omdat ik al redelijk wat ervaring heb met de software van Atmel (en me dat erg bevalt). De keuze van microcontrollers is soms toch een beetje persoonlijk , zeker als je naar de discussies op internet kijkt :P.

  • Sokkeh
  • Registratie: januari 2012
  • Laatst online: 08-12 17:45
Ah, duidelijk met de uitleg er bij ;) ik dacht een heel topic over micro-C (OS laag voor multitasking op microcontrollers).

Heb zelf redelijk wat ervaring met C programmeren, en ook de micro-C os laag. Heb gewerkt met arduino, ARM en ben momenteel bezig met andere ATMEL processoren.

  • mux
  • Registratie: januari 2007
  • Nu online

mux

99% efficient!

TVP :) Ik ben zelf 100% functioneel µC-programmeur, dus ik heb eigenlijk alleen ervaring met embedded C (op gcc). Zooi zoals RTOS raak ik zelden aan.

Youtube: PowerElectronicsBlog - Plank2 (4W computer)


  • begintmeta
  • Registratie: november 2001
  • Niet online
Ik kan zelf niets, maar ik vind het WP 34S-project heel aardig bezig, zou zoiets ook binnen het kader van dit topic vallen?

  • Ploink
  • Registratie: april 2002
  • Laatst online: 26-11 10:36
Programmeert niemand meer hardcore ASM tegenwoordig? Of kun je een PIC16 of ATTINT13A met 1024 bytes flash ook in C programmeren?

  • RobV
  • Registratie: juni 2013
  • Niet online

RobV

Welcome to the grid, Program.

Topicstarter
(overleden)
Een kort stukje over mijzelf: In 1989 begonnen aan een studie Informatica, ik deed toen al assembly en C op een C64 en Amiga. In ’95 afgestudeerd op Software Engineering en Datastructures. Toen 3 jaar gewerkt met HP mainframes, toentoch de stap naar Microsoft gemaakt. Eerst grote project was migratie van VB3 apps naar het toen splinternieuwe VB5. Al snel naar ASP en toen snel naar ASP.Net over (hoera C#, eindelijk af van interpreted languages). Ikheb nog meegedraaid met de 1.0 beta van C#, waren mooie tijden. Sindsdien alles met C# gedaan wat er mogelijk was (helaas ook Sharepoint). Nu 3 jaar met Apple en dus ObjectiveC en Swift. 2 jaar geleden uit verveling begonnen met electronica en dus viel de Arduino makkelijk aan te leren. Inmiddels al flink wat zaken gefröbelt, met displays, bluetooth, gsm, etc. Eigen libraries geschreven omdat het kan (en om te leren hoe de hardware werkt).

 | Mijn joystick / simpit project | Blog | Elite Dangerous CMDR Cataclysm72


  • SA007
  • Registratie: oktober 2002
  • Laatst online: 09:37

SA007

Moderator Tweaking
Ploink, gezien hoe goed gcc is is er eigenlijk nooit behoefte aan ASM.

Ik heb een enkele keer wat routines in ASM gedaan, maar het kost 10x zoveel tijd om iets te doen en dus alleen zinnig als je echt de performance moet hebben.
In mijn geval was dat 30 kanalen software pwm wat op vrij hoge snelheid moest.

En ja, ik programmeer een attiny13 ook gewoon in C, geen enkel probleem.

Zelf prog ik voor vanalles, voornamelijk avr, maar ook dos-ish rtos chipcomputers, pic, wat arm en allerlei andere vage meuk.

[Voor 7% gewijzigd door SA007 op 09-03-2015 20:06]

Klok is stuk :(


  • Sissors
  • Registratie: mei 2005
  • Laatst online: 10:56
Met zijn 32 registers heb ik vroeger complete programmas voor AVRs in assembly geschreven die nooit irritante dingen als RAM geheugen moesten benaderen, toch maar irritant traag tov registers :P. Maar tegenwoordig houd ik het op C(++). Dat gezegd denk ik niet dat er nooit behoefte is aan ASM, voor de echt specifieke tijd kritische dingen of de hele kleine MCUs zal het nog wel nodig zijn.

  • jeroen3
  • Registratie: mei 2010
  • Laatst online: 10:57
Als programmeur van uC's is het wel degelijk belangrijk om ook wat te weten van assembler.
Je compiler, ook al is hij zo goed, maakt ook fouten. En daar kun je erg lang naar zoeken.
Inderdaad zullen mensen op het abstracte niveau van arduino zich niet zo druk maken om assembler. Maar als je de beste prestaties uit je LCD driver met DMA wil halen. Is het toch fijn dat je weet hoe het werkt. En ook hoe verschillende aanpakken in C invloed hebben op de assembler. Ken dus ook je gereedschappen!

Assembler word voornamelijk toegepast bij zeer vaak voorkomende interrupts, task-switching, handmatige exclusive access en special commando's of whatever voor iets leuks jij beter denkt te kunnen dan de compiler/optimizer.

Je bent gek als nu nog je hele programma's gaat maken in assembler (voor andere doelen dan educatief). Zelfs op aan attiny10 kun je beperkt C gebruiken. Functies aanroepen wil alleen niet zo goed.

  • SA007
  • Registratie: oktober 2002
  • Laatst online: 09:37

SA007

Moderator Tweaking
En sowieso heb je vaak veel meer aan je chip echt goed kennen dan zijn instructieset.

Hoe werkt precies de SPI hardware, hoe werken de timers precies, etc.
Dan kom je erachter dat je tijdkritische dingen in verassend veel gevallen door de vrij uitgebreide hardware van de chip kan laten doen.

Klok is stuk :(


  • RobV
  • Registratie: juni 2013
  • Niet online

RobV

Welcome to the grid, Program.

Topicstarter
(overleden)
Leuk dat jullie er allemaal zo enthousiast bovenop duiken. Welkom!

 | Mijn joystick / simpit project | Blog | Elite Dangerous CMDR Cataclysm72


  • mux
  • Registratie: januari 2007
  • Nu online

mux

99% efficient!

Als ik iets moet optimaliseren schrijf ik zelf nooit ASM, maar geef ik C compiler hints en bekijk ik de .lss output om te zien hoe de timing is. Werkt net zo goed als ASM schrijven zonder de hoofdpijn :)

Youtube: PowerElectronicsBlog - Plank2 (4W computer)


  • Sissors
  • Registratie: mei 2005
  • Laatst online: 10:56
SA007 schreef op maandag 09 maart 2015 @ 20:25:
En sowieso heb je vaak veel meer aan je chip echt goed kennen dan zijn instructieset.
Maar zijn instructieset goed kennen kan je ook erg helpen! En dan hoef je niet direct ASM in te gaan.

Voorbeeld, situatie was kijken van welke input pin een interrupt kwam. Er was een 32-bit register, waarbij de pin die de interrupt veroorzaakte hoog was. Hoe zoek je zo snel mogelijk welke pin dat was?

Eerste code was iets van:
code:
1
for (int i = 0; i<32; i++) { }


Dat is natuurlijk niet het meest efficiente. Plan B waar je dan voor kan gaan is een simpel search algorithme wat steeds het in twee'en opsplitst en kijkt of daar een '1' in zit.

Maar omdat ik dat teveel werk vond keek ik eens in de instructieset rond, en wat vond ik daar? __CLZ(uint32_t). (IIG dat is de C macro die de clz assembler instructie inlined). Waarbij CLZ staat voor Count Leading Zeros. Oftewel niks kloten met algorithme om het zo snel mogelijk te vinden, gewoon een enkele instructie uitvoeren en je weet op welk bit je '1' staat.

  • Anthor
  • Registratie: juni 2002
  • Niet online
Intressant topic, al moet ik toegeven dat ik de laatste tijd niet zo heel veel meer doe met elektronica.

Ik programmeer vrijwel alleen maar ASM (attiny's en atmega's). Ik vind het wel fijn om precies te kunnen bepalen wat er gebeurt.
Lekker zoveel mogelijk uit de registers en alleen 16 bit integers als het echt nodig is :P

Ik ben qua uC's begonnen met een pic16f628, met iets dat dacht ik mikroBasic heette. Daar had ik wat in geschreven en om te leren hoe die uC nou precies werkte ben ik gaan ontcijferen wat die compiler er nou precies van maakte. Zo heb ik asm geleerd, en ben eigenlijk snel daarna overgestapt op AVR's (door een demo contest hier :) )

  • Ploink
  • Registratie: april 2002
  • Laatst online: 26-11 10:36
Ik ben begonnen met machinecode met de commodore 64, nog niet eens in ASM, maar met een equivalent van het DOS "debug" alles met absolute adressen en getallen in het geheugen zetten en dan dat stukkie geheugen saven op een casettebandje. Zo heb ik hele stukken code geschreven, dat waren nog eens tijden :) Later nog af en toe asm gedaan voor diverse processoren.

C is veel praktischer, maar ASM heeft zeker zijn charme en het is gewoon leuk om een efficiënte routine uit te puzzelen :) Voor bepaalde dingen zoals een bitbang SPI is het simpeler en sneller dan C. Over timing heb je ook betere controle en kun je hier of daar een NOP plaatsen om het kloppend te maken.

Wat ik mis in C is het carry bit en bijbehorende instructies. Ik heb wel een CARRY macro, maar die doet gewoon bit manipulatie op het STATUS register, toch niet helemaal hetzelfde.
GCC is niet echt optimaal, er zijn andere (dure) compilers die ingebouwde extensies hebben voor microcontrollers, zoals bit variabelen. Voor zover ik weet produceert GCC nooit de AVR sbi/cbi instructies.

[Voor 5% gewijzigd door Ploink op 10-03-2015 00:27]


  • AlexanderB
  • Registratie: maart 2007
  • Laatst online: 02:45

AlexanderB

7800 rpm

Ik ben ooit begonnen met een Lego Mindstorms RCX, daar zat een blokken-programma bij wat erg handig was om simpele logica mee te leren, maar behoorlijk beperkt. Er zijn wel C *en* Basic programmeeromgevingen voor te krijgen, maar heb ze nooit echt gebruikt.

Daarna voor de middelbare school Basic geprogrammeerd geknipt en geplakt op een PIC om een lijnvolg-robotje te maken.

Daarna volledig overgegaan op AVR chips icm C / hier en daar een losse assembler instructie als ik iets specifieks wil. Voorbeeld hierboven van Sissors is precies wat ik daarmee bedoel, als je iets wil wat in C te lang duurt en in assembler direct kan met 1 instructie. :)

  • Sprite_tm
  • Registratie: september 2002
  • Laatst online: 08-12 02:47

Sprite_tm

Semi-Chinees

* Sprite_tm heeft laatst nog lopen ranten over hoeveel minder efficient arm thumb-code te schrijven is in vergelijking met 'volle' 32-bit arm-machinetaal... in een project waar ook 6809 assembly voor geschreven moet worden. Was wel hobby trouwens. Mijn kennis van assembly is uberhaupt redelijk aanwezig, maar dat krijg je snel als je wat reverse-engineering-projectjes doet: bij een blob firmware krijg je vaak geen C-sources :)

Maar inderdaad, als het op snelheid aankomt is er een hoop te doen met gcc nudgen, maar imo gaat er niets boven assembly als je het zeker wilt weten. Ook al was het maar omdat de code die een compiler genereert wel eens kan veranderen van versie tot versie, en dan kan het ineens zijn dat je timings anders worden. Met assembly heb je daar geen last van.

Relaxen und watchen das blinkenlichten. | Laatste project: Ikea Frekvens oog


  • lordprimoz
  • Registratie: november 2013
  • Laatst online: 28-11 17:38
interessant topic, ga ik zeker volgen.

Overigens ben ik zelf meer van de electro, maar dat neemt niet weg dat software kennis erg belangrijk is.

  • RobV
  • Registratie: juni 2013
  • Niet online

RobV

Welcome to the grid, Program.

Topicstarter
(overleden)
Voor de meeste projectjes hoeft je je nauwelijks druk te maken over assembly en de quirks van je compiler. Er zijn natuurlijk mensen die een eigen PAL display driver schrijven en daar graag hulp bij hebben, is helemaal geweldig natuurlijk en lezen we graag meer over.

Helaas lopen veel beginnende gebruikers al spaak op een ';' teveel of te weinig. Ik hoop dat dit topic die mensen ook helpen kan en dat zij niet beangstigd worden door goed bedoelde overkill adviezen.

 | Mijn joystick / simpit project | Blog | Elite Dangerous CMDR Cataclysm72


  • mux
  • Registratie: januari 2007
  • Nu online

mux

99% efficient!

Sprite_tm schreef op dinsdag 10 maart 2015 @ 09:30:
Maar inderdaad, als het op snelheid aankomt is er een hoop te doen met gcc nudgen, maar imo gaat er niets boven assembly als je het zeker wilt weten. Ook al was het maar omdat de code die een compiler genereert wel eens kan veranderen van versie tot versie, en dan kan het ineens zijn dat je timings anders worden. Met assembly heb je daar geen last van.
Dit is toch wel meestal een functie van de complexiteit van de µC. Op 8-bitters (waar ik veruit het meeste op heb gewerkt) heb ik nog nooit instabiele compilers gehad, maar op 32-bit komt dit veel vaker voor (en is het imo dan wel gauw waardevol om direct in assembly te werken). Het scheelt nogal of je 48 of 500+ instructies hebt om mee te optimaliseren.

Youtube: PowerElectronicsBlog - Plank2 (4W computer)


  • lordprimoz
  • Registratie: november 2013
  • Laatst online: 28-11 17:38
zijn verilog of vhdl issues/vragen hier trouwens ook welkom? Niet dat ik er nu problemen mee heb, maar wie weet in de toekomst.

  • RobV
  • Registratie: juni 2013
  • Niet online

RobV

Welcome to the grid, Program.

Topicstarter
(overleden)
geen idee, ik heb nooit gehoord van verilog of vhdl !!

 | Mijn joystick / simpit project | Blog | Elite Dangerous CMDR Cataclysm72


  • lordprimoz
  • Registratie: november 2013
  • Laatst online: 28-11 17:38
verilog en vhdl zijn beide hardware description languages, die de aansturing van fpga's verzorgen. Ik denk dat het duidelijker was geweest te vragen of fpga's hier ook aan bod mogen komen?

Valt wel een beetje onder uC's =P

[Voor 8% gewijzigd door lordprimoz op 10-03-2015 12:01]


  • RobV
  • Registratie: juni 2013
  • Niet online

RobV

Welcome to the grid, Program.

Topicstarter
(overleden)
Wat mij betreft geen probleem. Ik ben dan wel de topicstarter maar niet de moderator en zeker niet de deskundige!

 | Mijn joystick / simpit project | Blog | Elite Dangerous CMDR Cataclysm72


  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
Assembly... Tsja. Ik heb er ooit eens aan geroken en daarna gingen we door met C, hetgeen ik nu veel praktischer vindt. Ik heb altijd het gevoel dat voor simpele routines ASM juist zoveel groter wordt.

  • 187449
  • Registratie: augustus 2006
  • Niet online
ChipWhisperer laughs at your AES-256 implementation 8)

  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
Hmmm, het lijkt erop dat ik mijn probleem met de niet resettende indexer getackled heb. Een mooi if else statementje van gemaakt (if(BF == 1 && SSPADD+1 = SSP1BUF) en dat lijkt de truc te zijn

  • lordprimoz
  • Registratie: november 2013
  • Laatst online: 28-11 17:38
Pizza_Boom schreef op woensdag 11 maart 2015 @ 15:36:
Hmmm, het lijkt erop dat ik mijn probleem met de niet resettende indexer getackled heb. Een mooi if else statementje van gemaakt (if(BF == 1 && SSPADD+1 = SSP1BUF) en dat lijkt de truc te zijn
ik heb het verhaal niet gevolgt, maar weet je zeker dat je niet SSPADD+1 == SSP1BUF bedoeld?

  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
lordprimoz schreef op woensdag 11 maart 2015 @ 16:49:
[...]


ik heb het verhaal niet gevolgt, maar weet je zeker dat je niet SSPADD+1 == SSP1BUF bedoeld?
Ja, dat bedoel ik en dat staat ook zo in de code... :P Typotje dus. :+ :D

  • DaWaN
  • Registratie: oktober 2002
  • Laatst online: 11:33

DaWaN

'r you wicked ??

Ik zou ook even een kleine intro geven van mijzelf:
Sinds 2007 aan de slag met MCU's. Begonnen met PIC16's en ASM. Daarna vanalles gedaan: AVR, LPC2xxx (ARM7, later Cortex M), STM32, PIC18, XAP5, MicroC OS-II, ChibiOS/RT, etc.
Sprite_tm schreef op dinsdag 10 maart 2015 @ 09:30:
* Sprite_tm heeft laatst nog lopen ranten over hoeveel minder efficient arm thumb-code te schrijven is in vergelijking met 'volle' 32-bit arm-machinetaal... in een project waar ook 6809 assembly voor geschreven moet worden.
Tja, ik vind het niet raar dat Thumb code niet zo makkelijk te schrijven is als de volle ARM instructieset.
Dat is ook het hele probleem met oude instructiesets: aangezien 90% van de wereld C schrijft is een instructieset die afgestemt is op de output van een C compiler veel nuttiger. Dikwijls is code snelheid ook niet eens echt van belang, code density is veel belangrijker.

Schrijf voor de grap eens een stuk code voor een AVR of Cortex Mx (mét Thumb) in C compile het en verlijk de code density eens met zoiets als een 8051... Dan snap je wat de waarde is van nieuwe instructiesets.
Ik ben het wel eens met het feit dat het minder lekker programmeren is in ASM, maar je bent daarmee in de minderheid..
mux schreef op dinsdag 10 maart 2015 @ 10:42:
[...]
Dit is toch wel meestal een functie van de complexiteit van de µC. Op 8-bitters (waar ik veruit het meeste op heb gewerkt) heb ik nog nooit instabiele compilers gehad, maar op 32-bit komt dit veel vaker voor (en is het imo dan wel gauw waardevol om direct in assembly te werken). Het scheelt nogal of je 48 of 500+ instructies hebt om mee te optimaliseren.
Wat is een instabiele compiler? Bugs kun je altijd hebben, belangrijk is dat er een goede userbase is waardoor de compiler onderhouden wordt.
Ik heb vroeger met PIC18's gewerkt i.c.m. de Microchip MCC18 compiler, teh horror :'( :X

If you do not change direction, you may end up where you are heading


  • Hans1990
  • Registratie: maart 2004
  • Laatst online: 10:59
Dat komt dan juist weer omdat de PIC16/18 core horror is voor C. Het programma draait, maar niet supersnel en al helemaal niet compact. Dan vragen ze ook nog eens honderden euro's voor een pro edition, die broodnodige optimisations doet voor zo'n arme CPU core. Tbh kan ik nog niet begrijpen waarom ze geld vragen om hun eigen producten beter te laten presteren. Klinkt meer als een "after market" model (bvb chiptuning van auto's)

Bvb ik heb laatst een paar routines geschreven die met enkele macro truuks op GCC compilers (ARM, AVR, Mchp XC16, Mchp XC32) prima terug naar enkel instructies compileert - zoals bitset PORTB, 3 e.d.
Op XC8 krijg ik dat gewoon niet voor elkaar - terwijl die core ook een bset instructie kent. De compiler wil gewoon niet afweten welke zaken constant zijn en dus bepaalde pointers tijdens compilatie al uitgezocht kunnen worden. Table access is vreselijk want het moet Wreg op de "stack" zetten (die het niet heeft - dus ergens static in RAM), vervolgens een call doen naar zijn table section, en vervolgens met nog meer indirect-access register een pointer proberen te volgen (die ook gebruikt wordt voor andere zaken, zoals door een array heen lopen). :(

Ik vind het zeker essentieel om je assembler output te bekijken en (waar nodig) zo netjes mogelijk te krijgen. Ik beschouw C als een "portable assembler" - maar ik moet er niet aan te denken om een ingewikkeld meer-laags protocol (USB, TCP/IP, oid) in ASM te schrijven.. met name software logic dat op andere controllers ook prima had kunnen draaien.

Meestal met GCC -O1 kom je al een heel eind om code compact te krijgen. Ik werk het liefst op -Os; ik leun niet graag op snelheid optimalisaties van -Ox omdat het debuggen vaak minder fijn is. Ik waardeer dan veel meer de kleinere code size.

[Voor 10% gewijzigd door Hans1990 op 12-03-2015 18:17]


  • mux
  • Registratie: januari 2007
  • Nu online

mux

99% efficient!

DaWaN schreef op woensdag 11 maart 2015 @ 23:58:
Wat is een instabiele compiler? Bugs kun je altijd hebben, belangrijk is dat er een goede userbase is waardoor de compiler onderhouden wordt.
Ik heb vroeger met PIC18's gewerkt i.c.m. de Microchip MCC18 compiler, teh horror :'( :X
Ik bedoel hier instabiliteit in de wiskundige zin; beetje zoals bij sorting-algoritmes. Een stabiele compiler zal met dezelfde conceptuele input altijd dezelfde machinecode uitspugen. Een instabiele compiler zal zelfs bij kleine veranderingen in de code opeens hele andere dingen maken.

Youtube: PowerElectronicsBlog - Plank2 (4W computer)


  • Damic
  • Registratie: september 2003
  • Laatst online: 07:07

Damic

Afwezig soms

borroz schreef op woensdag 11 maart 2015 @ 14:34:
ChipWhisperer laughs at your AES-256 implementation 8)
Ey ik heb dat voorbij zien komen op het eevblog, de prijs is er ook wel naar, maarja als je zo heel snel iets kunt vinden waarom ook niet.

Ik kan vanalles en nog wat maar niets te goei, klinkt bekent?? Al wat ik aanraak werk niet meer zoals het hoort. Damic houd niet van zijn verjaardag


  • janwillemCA
  • Registratie: mei 2014
  • Laatst online: 10:24
Dit ga ik zeker volgen, ben zelf sinds een maand of 2 bezig met Atmel microcontrollers (Ja nog een arduino),
Ik ben momenteel een soort "zelfrijdende" auto aan het maken op basis van een oude RC auto.

Ik ga dit zeker volgen, en hoop een boel op te steken.

Unix is simple. It just takes a genius to understand its simplicity


  • RobV
  • Registratie: juni 2013
  • Niet online

RobV

Welcome to the grid, Program.

Topicstarter
(overleden)
Tips voor beginners in C

1. Let op het verschil tussen '=' ipv '=='. De meeste compilers vangen dit tegenwoordig af.

C++:
1
2
3
4
5
int x = 2;
if(x = 4)
{
   //x is nu 4 en de code binnen de accolades wordt uitgevoerd.
}


2. commentaar niet afgesloten. Een syntaxhilighter doet wonderen.

C++:
1
2
x = 1; /* let op deze regel
x = 2; /* wordt nooit uitgevoerd */


3. ';' achter if,for of while
C++:
1
2
3
4
for(int i=0; i<4; i++);
{
   //wordt maar 1 keer uitvoerd.
}


4. verwarring tussen #define en const
C++:
1
2
3
4
5
6
7
8
9
//FOUT
#define PIN_POWER = 4 

//GOED
#define PIN_POWER 4

//BETER (de definitie is nu strongly typed)
//let op de = en de ';'
const int PIN_POWER = 4;


5. index buiten de array:
C++:
1
int buffer[10];

geldige waarden zijn van buffer[0] en buffer[9].

6. het verschil tussen een character en een string:
C++:
1
2
char x = 'x';   //just 1 byte
char str[] = "xyzab";  // /0-terminated array.


7. verwarring tussen && en &, of | en ||. De '&' is de reken-operator, terwijl de && booleans combineert. Officieel heten ze Bitwise AND (&) en Logical AND (&&)
(thanks @Ploink)
C++:
1
2
3
4
5
6
7
if(dit && dat)  //dus wanneer 'dit' en 'dat' beide waar zijn.
{
}

if(x & 0x0F > 0x07) // & operator met opzet, heeft overigens voorrang boven die '>'
{
}


8. LEES de foutmeldingen. Krijg je een hele reeks meldingen, dan zijn dat meestal vervolgfouten. Los altijd eerst de bovenste foutmelding op.
9 . Copy/Paste zo weinig mogelijk, en probeer te begrijpen WAT je copy-paste.
10. Kies een andere hobby.

[Voor 9% gewijzigd door RobV op 13-03-2015 22:55]

 | Mijn joystick / simpit project | Blog | Elite Dangerous CMDR Cataclysm72


  • Ploink
  • Registratie: april 2002
  • Laatst online: 26-11 10:36
RobV schreef op vrijdag 13 maart 2015 @ 20:16:
Tips voor beginners in C
7. verwarring tussen && en &, of | en ||. De '&' is de AND operator, terwijl de && booleans combineert.
Dat noem je Bitwise AND (&) en Logical AND (&&)
10. Kies een andere hobby.
Goed idee, lekker naar buiten, wandelen, fietsen, vakantie.... veel leuker :D

  • RobV
  • Registratie: juni 2013
  • Niet online

RobV

Welcome to the grid, Program.

Topicstarter
(overleden)
bedankt, ploink

 | Mijn joystick / simpit project | Blog | Elite Dangerous CMDR Cataclysm72


  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
Mooie voor een spoiler in de OP, denk?

  • RobV
  • Registratie: juni 2013
  • Niet online

RobV

Welcome to the grid, Program.

Topicstarter
(overleden)
Pizza_Boom schreef op vrijdag 13 maart 2015 @ 22:22:
[...]
Mooie voor een spoiler in de OP, denk?
Gaan we doen, als ik alle spelvoutjes eruit heb.

 | Mijn joystick / simpit project | Blog | Elite Dangerous CMDR Cataclysm72


  • Sokkeh
  • Registratie: januari 2012
  • Laatst online: 08-12 17:45
RobV schreef op vrijdag 13 maart 2015 @ 20:16:
1. Let op het verschil tussen '=' ipv '=='. De meeste compilers vangen dit tegenwoordig af.

C++:
1
2
3
4
5
int x = 2;
if(x = 4)
{
   //x is nu 4 en de code binnen de accolades wordt uitgevoerd.
}
Misschien makkelijker / beter begrijpbaar uit te leggen.

= voor wordt gelijk aan.
code:
1
int x = 4; // x wordt 4

== is hetzelfde als.
code:
1
2
if( x == 4 )
   // voer code uit als x gelijk is aan 4.


de if statement in het voorbeeld is namelijk redelijk overbodig ;)

[Voor 6% gewijzigd door Sokkeh op 13-03-2015 23:10]


  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
Iemand hier ervaring met een NRF24L01+ i.c.m. I2C(Uit een PIC16F1459)?

[Voor 16% gewijzigd door Pizza_Boom op 14-03-2015 01:54]


  • Daedalus
  • Registratie: mei 2002
  • Niet online

Daedalus

Moderator Apple Talk

Keep tryin'

De NRF24L01+ gaat via SPI, niet I2C.

“You know what I've noticed Hobbes? Things don't bug you if you don't think about them. So from now on, I simply won't think about anything I don't like, and I'll be happy all the time!” | 宇多田ヒカル \o/


  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
Dat vreesde ik al. Leesfout in oktober dus. Kak.

  • RobV
  • Registratie: juni 2013
  • Niet online

RobV

Welcome to the grid, Program.

Topicstarter
(overleden)
Sokkeh schreef op vrijdag 13 maart 2015 @ 23:09:
[...]
de if statement in het voorbeeld is namelijk redelijk overbodig ;)
Overbodig wil ik niet zeggen. Ik heb de fout gemaakt die ik wel vaker maak: ik neem teveel stappen ineen zonder iedere stap uit te leggen. Ik was gestart met de post als 'top 10 beginnersfouten' en heb dit later omgezet naar 'tips'. De voorbeeld waren geschreven als 'foute voorbeelden' en dan kloppen ze niet als 'tip'. Ik had ook de voorbeelden moeten aanpassen naar de schrijfwijze van de post.

Ik zal het nog eens proberen (o.b.v. mijn eigen voorbeeld):

Stel, je hebt een variable 'x' en de variable heeft een bepaalde waarde. Je wilt iets doen wanneer die variabele 4 is, maar niét als het het andere waarde heeft, bijvoorbeeld de waarde 2 (twee). In je code vergeet je echter om de comparison operator (==) te gebruiken en je typt dan de assignment operator (=)

/me Je krijgt dan deze code (uit het voorbeeld, en deze illustreert de fout)
C:
1
2
3
4
5
6
//let op, dit voorbeeld is fout.
int x = 2;
if(x = 4)
{
   Serial.println("Print deze regel alleen als x 4 is");
}

Helaas is dit niet het resultaat was je wilt hebben, want de regel wordt ook afgedrukt als x ongelijk is aan de waarde 4. Bovendien heeft x nu ook niet langer de waarde die hij eerste had, maar '4'. De oorzaak is dat 'x = 4' altijd true oplevert (hierover straks meer). Indien je 'x == 4' had getypt, levert deze alleen true op wanneer de x daadwerkelijk een 4 bevat en bleef zijn waarde ongewijzigd.

Hieronder volgt de juiste code:
C:
1
2
3
4
5
int x = 2;
if(x == 4)
{
   Serial.println("Print deze regel alleen als x 4 is");
}


Waarom levert x =4 altijd true op zul je je afvragen? Nou dat komt omdat je jongens die de taal hebben bedacht het leuk vonden om het resultaat van de assignment te kunnen gebruiken als expressie voor andere functies. We gebruiken nu een constante, maar stel dat je de returnwaarde van een functie wilt gebruiken in een conditie, en die waarde ook wilt bewaren, dan kunnen we het in C op 2 manieren schrijven.

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
//1e manier met een variabele.
char character = Serial.read();
if(character != 0)
{
   //doe iets met character.
}

//2e manier zonder variabele, bijvoorbeeld als character als globale variabele is gebruikt.
char character;
if( (character = Serial.read()) != 0)
{
   //do iets met character.
}


Persoonlijk ben ik van mening dat de 2e methode slecht is voor de leesbaarheid van de code en dat deze dan ook met mate gebruikt dient te worden. Overigens is het in sommige C-varianten mogelijk om de variabele binnen de expressie te declareren maar dat is hier buiten scope van het voorbeeld.

Ik hoop dat deze uitleg de keuze van mijn voorbeeld verduidelijkt.

 | Mijn joystick / simpit project | Blog | Elite Dangerous CMDR Cataclysm72


  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
Daedalus schreef op zaterdag 14 maart 2015 @ 02:49:
De NRF24L01+ gaat via SPI, niet I2C.
Hmm, ik heb inmiddels I2C uit mijn PICjes (met MSSP module) en ik snap wat er gebeurt. Zou het heel lastig zijn om hier nu ook nog SPI uit te halen?

  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
Het is toch ook wel erg gesteld met me. I2C werkt, maar een interrupt op IO pinnen van de master krijg ik niet draaiend. :X 8)7 Zal wel weer ergens overheen kijken. |:( |:(

  • RobV
  • Registratie: juni 2013
  • Niet online

RobV

Welcome to the grid, Program.

Topicstarter
(overleden)
Pizza_Boom schreef op maandag 16 maart 2015 @ 21:51:
Het is toch ook wel erg gesteld met me. I2C werkt, maar een interrupt op IO pinnen van de master krijg ik niet draaiend. :X 8)7 Zal wel weer ergens overheen kijken. |:( |:(
Misschien kunnen we helpen, maar dan moet je wel wat meer info geven. De sourcecode en een schema bijvoorbeeld.

 | Mijn joystick / simpit project | Blog | Elite Dangerous CMDR Cataclysm72


  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
Gaat om een PIC16F1459

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void interrupt ISR(void)
    {
        if(INTF)
            {
                if(RA0 == 1)
                    {
                        knop1 = 1;
                    }
                else if (RA1 == 1)
                    {
                        knop2 = 1;
                    }
            }
    }

Knop1 en knop2 worden gecleared in de routine waar ze in gebruikt worden.

INTCON is gesteld op 0b11010001, PIE1/2 en PIR1/2 zijn volledig 0.

Neem aan dat er voor een simpel drukknopje geen schema nodig is. Knopjes werken (en zijn voorzien van puldowns), want als ik de hulpvariabele in de maincode vervang voor RA0/RA1 dan werkt het wel (okee, moet alleen het knopje ingedrukt houden totdat de code daarlangs is gekomen).

[Voor 28% gewijzigd door Pizza_Boom op 16-03-2015 22:30]


  • Sissors
  • Registratie: mei 2005
  • Laatst online: 10:56
Zijn knop1 en knop2 als volatile gedeclareerd?

  • lordprimoz
  • Registratie: november 2013
  • Laatst online: 28-11 17:38
Pizza_Boom schreef op maandag 16 maart 2015 @ 22:28:
(okee, moet alleen het knopje ingedrukt houden totdat de code daarlangs is gekomen).
interrupt gebruiken om bijv een boolean op true te zetten, waarmee je de code voor het indrukken van het knopje kan laten uitvoeren.

  • peterkuli
  • Registratie: september 2003
  • Laatst online: 08:37
Debounce je de schakelaar wel?
When a switch is pressed it does not fully close the first time you press it because the metal contacts bounce off each other!

Feeding the signal into a logic gate or a microcontroller sends multiple key press signals which is not what you want so you have to ignore the bouncing signal - this is known as debouncing the switch.
Bron

  • Infant
  • Registratie: januari 2008
  • Laatst online: 08-12 11:21

Infant

It's a floating Dino!

Mooi topic!

Ik zit zelf met een makefile te klooien. (Het is ook van toepassing op een .hex file, dus dit topic is relevant...vind ik.)
Het probleem is dat ik twee programma's compile met één makefile, maar graag wil dat hij een object file opnieuw bouwt voor het 2e programma. (Omdat die andere precompiler instelling heeft.)

Als ik ze los aanroep met make app1, of make app2 werkt het zoals ik wil (mits eerst de relevante .o files verwijderd zijn.)
Maar make all voert build en objs maar 1 keer uit. Na finished 1 zou ik weer "compiling source files" willen zien.

code:
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
56
57
58
CC      = gcc
CFLAGS  = -std=gnu99 -lpthread -lm -w

#Source file list.
SOURCES_LOCAL =
SOURCES_LOCAL += client.c
SOURCES_LOCAL += ../lib/tcp/tcp.c
SOURCES_LOCAL += ../lib/crypt/sha2.c
SOURCES_LOCAL += ../lib/crypt/aes.c
SOURCES_LOCAL += ../lib/crypt/tcpcrypt.c
SOURCES_LOCAL += ../lib/common/common.c

OBJECTS_LOCAL = $(SOURCES_LOCAL:.c=.o)

#Application name.
APPNAME1 = client
APPNAME2 = client2

all:  app1  app2

objs: $(OBJECTS_LOCAL)

app1:build objs link-msg    
    $(CC) -o $(APPNAME1) $(OBJECTS_COMMON)  $(OBJECTS_LOCAL) $(ARCH)  $(CFLAGS) $(LIBS) $(DEFS)
    @echo =================================
    @echo !          FINISHED 1           !
    @echo =================================
    @echo   

#Hier zou build nog een keer moeten uitgevoerd worden.
app2: build objs link-msg 
    $(CC) -o $(APPNAME2) $(OBJECTS_COMMON)  $(OBJECTS_LOCAL) $(ARCH)  $(CFLAGS) $(LIBS) $(DEFS)
    @echo =================================
    @echo !          FINISHED 2           !
    @echo =================================
    @echo   

build: 
    @echo 
    @echo =================================
    @echo !     COMPILING SOURCE FILES    !
    @echo =================================

link-msg:
    @echo =================================
    @echo !     LINKING OBJECT FILES      !
    @echo =================================

$(OBJECTS_LOCAL): %.o: %.c  
    $(CC) -c $(CFLAGS) $(DEFS) $(LIBS) $< -o $@ 

clean: 
    #-rm  $(OBJECTS_COMMON)  $(OBJECTS_LOCAL)
    -rm -r */*.o
    -rm -r *.o
    -rm ./client    
    -rm -r ../lib/*/*.o 
    -rm *.exe*


De output ziet er zo uit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
=================================
! COMPILING SOURCE FILES !
=================================
gcc -c -std=gnu99 -lpthread -lm -w   client.c -o client.o
gcc -c -std=gnu99 -lpthread -lm -w   ../lib/tcp/tcp.c -o ../lib/tcp/tcp.o
gcc -c -std=gnu99 -lpthread -lm -w   ../lib/crypt/sha2.c -o ../lib/crypt/sha2.o
gcc -c -std=gnu99 -lpthread -lm -w   ../lib/crypt/aes.c -o ../lib/crypt/aes.o
gcc -c -std=gnu99 -lpthread -lm -w   ../lib/crypt/tcpcrypt.c -o ../lib/crypt/tcpcrypt.o
gcc -c -std=gnu99 -lpthread -lm -w   ../lib/common/common.c -o ../lib/common/common.o
=================================
! LINKING OBJECT FILES !
=================================
gcc -o client   client.o ../lib/tcp/tcp.o ../lib/crypt/sha2.o ../lib/crypt/aes.o ../lib/crypt/tcpcrypt.o ../lib/common/common.o   -std=gnu99 -lpthread -lm -w
=================================
! FINISHED 1 !
=================================

gcc -o client2   client.o ../lib/tcp/tcp.o ../lib/crypt/sha2.o ../lib/crypt/aes.o ../lib/crypt/tcpcrypt.o ../lib/common/common.o   -std=gnu99 -lpthread -lm -w
=================================
! FINISHED 2 !
=================================


Iemand een idee? .PHONY lijkt niet veel te doen, en de .o files weg gooien voor app2 geeft alleen maar als output dat hij alle .o files kwijt is.

  • RobV
  • Registratie: juni 2013
  • Niet online

RobV

Welcome to the grid, Program.

Topicstarter
(overleden)
probeer eens een target toe te voegen die een touch doet op je file.

(http://www.nondot.org/sabre/Mirrored/GNUMake/make_4.html)

edit: het valt met ook op dat 'build' en 'link' geen dependencies hebben. Zonder dependencies wordt een target volgens mij niet uitgevoerd (maar vergeef me, mijn make kennis is een beetje weggezakt na 24 jaar)

[Voor 44% gewijzigd door RobV op 17-03-2015 11:18]

 | Mijn joystick / simpit project | Blog | Elite Dangerous CMDR Cataclysm72


  • Infant
  • Registratie: januari 2008
  • Laatst online: 08-12 11:21

Infant

It's a floating Dino!

Touch update de file time, maar in build komt geen file voor.

Build en link printen alleen een berichtje. Ik zou ook verwachten dat dat bericht twee keer voorbij komt, maar dat is dus niet het geval.

Als build eenmaal uitgevoerd is, weigert hij het nog een keer toe doen. Ik zou dus willen dat hij domweg elke keer als ik build aanroep dat berichtje print.

Edit: Hebbes:
code:
1
$(MAKE) build objs link-msg

Als ik hiervoor het gesharde object file verwijder, doet hij het, en print hij twee keer het bericht.

Het voelt nog steeds als donkere magie. Een berg wiebeltjes, kronkeltjes haakjes, comma's tiltes en accolades (ben ik leestekens vergeten?) achter elkaar zetten en tadaa: Een programma.

[Voor 33% gewijzigd door Infant op 17-03-2015 12:11]


  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
lordprimoz schreef op dinsdag 17 maart 2015 @ 09:34:
[...]


interrupt gebruiken om bijv een boolean op true te zetten, waarmee je de code voor het indrukken van het knopje kan laten uitvoeren.
Dat was ook de bedoeling, maar dat pakt ie dus niet.
Sissors schreef op dinsdag 17 maart 2015 @ 07:25:
Zijn knop1 en knop2 als volatile gedeclareerd?
Aangezien dat me niets zegt, zal dat wel een nee zijn.
peterkuli schreef op dinsdag 17 maart 2015 @ 10:26:
Debounce je de schakelaar wel?


[...]


Bron
Ook niet (en nog nooit gedaan)... Maar dat zou toch geen invloed mogen hebben op het niet werken van mijn interrupt? Ik zou bij bouncen juist verwachten dat de interrupt meermaals aangeroepen wordt.

  • Sissors
  • Registratie: mei 2005
  • Laatst online: 10:56
Afhankelijk van wat je doet kan het daardoor onduidelijk zijn of hij uberhaupt aangeroepen wordt. Maar meestal is het wel duidelijk dat hij dan iets doet.

Maar waarschijnlijk is je probleem dan dat hij niet volatile is. Als hij als volatile is gedeclareerd dan dwing je de compiler om in de normale code waar hij wordt uitgelezen, om de laatste waarde steeds uit zijn geheugen te halen. Dit moet je doen voor alle variabelen die in een interrupt routine worden aangepast, omdat de compiler niet begrijpt wat een interrupt is, en dat de variabele dus voor hem zomaar kan veranderen.

  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
Sissors schreef op dinsdag 17 maart 2015 @ 12:37:
Maar waarschijnlijk is je probleem dan dat hij niet volatile is. Als hij als volatile is gedeclareerd dan dwing je de compiler om in de normale code waar hij wordt uitgelezen, om de laatste waarde steeds uit zijn geheugen te halen. Dit moet je doen voor alle variabelen die in een interrupt routine worden aangepast, omdat de compiler niet begrijpt wat een interrupt is, en dat de variabele dus voor hem zomaar kan veranderen.
Hoe maak ik hem volatile?

  • lordprimoz
  • Registratie: november 2013
  • Laatst online: 28-11 17:38
gewoon "volatile" voor je variabele plaatsen? (zonder quotes)

edit: bijv: volatile int volatileVariable;

[Voor 9% gewijzigd door lordprimoz op 17-03-2015 13:57]


  • RobV
  • Registratie: juni 2013
  • Niet online

RobV

Welcome to the grid, Program.

Topicstarter
(overleden)
lordprimoz schreef op dinsdag 17 maart 2015 @ 13:56:
[...]


gewoon "volatile" voor je variabele plaatsen? (zonder quotes)

edit: bijv: volatile int volatileVariable;
Met syntax highlighting gaat het wellicht beter, want ik dacht dat er 2x volatile stond..
C++:
1
volatile int deVariabeleDieVolatileMoetZijn;

 | Mijn joystick / simpit project | Blog | Elite Dangerous CMDR Cataclysm72


  • elleP
  • Registratie: januari 2001
  • Laatst online: 10:16
code:
1
2
3
4
if(x = 4)
{
   Serial.println("Print deze regel alleen als x 4 is");
}

compilet (met een waarschuwing)
code:
1
2
3
4
if(4 = x)
{
   Serial.println("Print deze regel alleen als x 4 is");
}

compilet niet, want 4 is een constante, en die kan je niet een andere waarde geven

Ik heb deze tip ooit eens gekregen, en als je deze manier van if-en aanhoud kan het bijna niet mis gaan.
Overigens gebruik ik liever -Wall -Wextra, en zorg ervoor dat mijn code 0 warnings oplevert.

[Voor 7% gewijzigd door elleP op 17-03-2015 14:42]

elleP


  • RobV
  • Registratie: juni 2013
  • Niet online

RobV

Welcome to the grid, Program.

Topicstarter
(overleden)
^^Goede tip dat, hoewel ik 'x = 4' prefereer, wellicht omdat ik klassiek (ouderwets) geschoold ben is en '4 = x' een beetje krom eruit vind zien. Net als dat mensen tegenwoordig het hebben over 'me smartphone'. Da's ook hip :D

 | Mijn joystick / simpit project | Blog | Elite Dangerous CMDR Cataclysm72


  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
RobV schreef op dinsdag 17 maart 2015 @ 14:39:
[...]

Met syntax highlighting gaat het wellicht beter, want ik dacht dat er 2x volatile stond..
C++:
1
volatile int deVariabeleDieVolatileMoetZijn;
lordprimoz schreef op dinsdag 17 maart 2015 @ 13:56:
[...]


gewoon "volatile" voor je variabele plaatsen? (zonder quotes)

edit: bijv: volatile int volatileVariable;
Zo simpel :o

  • elleP
  • Registratie: januari 2001
  • Laatst online: 10:16
Ik kan me nog goed herinneren dat ik voor de eerste keer in de volatile-val getrapt ben, ik dacht dat het een bug in de compiler was, ik heb zelfs de assembly uit zitten pluizen om er achter te komen dat de waarde maar een keer uit ram gelezen werd, en daarna altijd vanuit een tijdelijk register. Tot iemand op een support forum helemaal uit zijn plaat ging want "dat staat toch in de manual" (als je weet waar je moet zoeken ;)).

Met volatile erbij leest 'ie keurig elke keer dat je de variabele gebruikt de waarde uit ram.

elleP


  • jbhc
  • Registratie: juli 2007
  • Laatst online: 08-12 16:30
elleP schreef op dinsdag 17 maart 2015 @ 14:41:
code:
1
2
3
4
if(x = 4)
{
   Serial.println("Print deze regel alleen als x 4 is");
}

compilet (met een waarschuwing)
Moet dat dan niet zijn:

code:
1
2
3
4
if(x==4)
{
   Serial.println("Print deze regel alleen als x 4 is");
}

  • RobV
  • Registratie: juni 2013
  • Niet online

RobV

Welcome to the grid, Program.

Topicstarter
(overleden)
Ja, dat moet idd x==4 zijn, maar we waren bezig met voorbeelden hoe het fout zou kunnen gaan. Als je even terugleest wordt het allemaal vanzelf duidelijk.

 | Mijn joystick / simpit project | Blog | Elite Dangerous CMDR Cataclysm72


  • Hans1990
  • Registratie: maart 2004
  • Laatst online: 10:59
Zal iedereen wel overkomen zijn, vooral als je programma zonder GCC optimisations het wel doet en met optimisations stuk gaat. Unoptimized GCC output is namelijk vrij recht toe recht aan, wat geweldig is voor debuggen, maar minder geweldig voor performance.

Volatile wilt ruwweg zeggen dat de variable buiten de context van die functie kan wijzigen. Dat kan door een interrupt zijn maar ook door hardware (bvb een hardware register - want de hardware kan de waarde doen wijzigen).

De compiler kan zelfs flink los lopen op deze code:

void main(void)
{
int a = 0;
while (a == 0);
}

Hier bij is er eerst a=0 gesteld, wordt niet meer gewijzigd (in de context zichtbaar), en daarna wordt er oneindig gewacht totdat a van waarde verandert. Dat is effectief hetzelfde aan while(1);, immers is niet zichtbaar hoe a zou moeten wijzigen. Dat terwijl met een volatile er voor de compiler de code wel zal vertalen "zoals je wil".
De compiler is met dit voorbeeld dus wenselijk bezig, want op deze manier kan het flinke optimisations maken (kan delen programma weglaten door simpelweg een variable op 0 te zetten). In dit voorbeeld is niet zichtbaar hoe a moet wijzigen, deels ook omdat die lokaal is. Echter in een "vies" programma zou een pointer naar de variable kunnen worden opgeslagen, en dan die pointer worden gebruikt om een variable op de lokale stack te wijzigen ( :N ). De compiler kan dat echter ook niet zien; dus kan je programma niet werken zoals je wil.

Het betekent ook dat als je een waarde uit een volatile register haalt, de compiler nooit (lang) de waarde op de stack of ergens wegzet omdat die ondertussen gewijzigd kan zijn. Er zal dus (lang) niet zo aggressief worden geoptimized.

Voorbeeld met XC16:
https://gist.github.com/nlhans/1502f886593ea1d51d66
(Vandaar mensen zeggen om naar de ASM code van je C te kijken; niet altijd zal de compiler precies doen wat je wil, vooral met optimisations :p )

[Voor 22% gewijzigd door Hans1990 op 17-03-2015 19:30]


  • peter00
  • Registratie: oktober 2006
  • Niet online
iemand hier ervaring met Atmel Studio? ik probeer een hex & binary dump van een Atmega64L te analyseren. Doel is de recordsamenstelling van een bepaald RF packet eruit te halen.

Ben niet digibeet of elctrofoob, maar iemand hier ervaring welke add-ons ik moet laden cq wat de handigste stappen zijn? Goegel en Jouwbuis helpen me nog niet heel erg op weg.

Het is vervelend als cynicus steeds gelijk te krijgen.


  • Ploink
  • Registratie: april 2002
  • Laatst online: 26-11 10:36
Kun je dat niet debuggen via de JTAG interface?

  • jeroen3
  • Registratie: mei 2010
  • Laatst online: 10:57
Ik zou eerst kijken of je van de hexdump weer assembler kan maken. Daarna bekende adressen vervangen in registernamen. En die code uitvoeren in de chip (met de debugger) zodat je kan zien wat er in het ram terecht komt. Mits je de originele hardware nog hebt.

  • peter00
  • Registratie: oktober 2006
  • Niet online
jeroen3 schreef op donderdag 19 maart 2015 @ 09:00:
Ik zou eerst kijken of je van de hexdump weer assembler kan maken. Daarna bekende adressen vervangen in registernamen. En die code uitvoeren in de chip (met de debugger) zodat je kan zien wat er in het ram terecht komt. Mits je de originele hardware nog hebt.
ja , die hardware heb ik nog. Assembler code heb ik ook. De adressen vervangen door registernamen is een goede. kan lekker vlot. Had ik nog niet eens aan gedacht. Scheelt een hoop dubbel werk.

debugger heb ik dus niet, maar dat wordt dus de volgende stap

thanks

Het is vervelend als cynicus steeds gelijk te krijgen.


  • Anthor
  • Registratie: juni 2002
  • Niet online
Hoeveel gebruiken jullie eigenlijk van de Atmel Studio features?
Ik heb versie 6.2 en ik zie een hoop dingen waarvan ik niet echt een idee heb wat ze doen zoals VAssistX en iets als ASF. Ik heb lang AVR studio 4 gebruikt, en 5 min of meer overgeslagen

Ik gebruik tot nog toe 1 project per solution, schrijf m'n .asm code voor 8-bitters, gebruik de simulator en mijn dragon als programmer/debugger. Is het de moeite waard om me in die extra features te verdiepen?

  • mux
  • Registratie: januari 2007
  • Nu online

mux

99% efficient!

Neuh, niet echt. Er zijn eigenlijk niet zoveel features, hoor. VAssistX is niks anders dan een totaal onbehulpzame naam voor een standaard meegeleverde visual studio extensie waarmee je marginaal betere variable/struct management kunt doen. Maar Visual Studio for C is an sich al een vrij goede IDE, dus ik heb het nooit aangezet.

ASF is atmel's eigen onleesbare, ondoordringbare set libraries en projecten. Ik heb geen idee waar ze voor zijn, misschien mensen die extra moeilijke code willen hebben om van te leren? Ja, ze werken en ze zijn goed onderhouden, maar het is een ware strijd om functionaliteit toe te voegen op een consistente manier. Doorgaans gebruik ik andere open source-projecten als codebase om zelf aan toe te voegen, bijvoorbeeld LUFA of ChibiOS.

Verder is Atmel Studio niks anders dan een gelicenseerde Visual Studio for C/C++ met de Atmel-toolchain en Atmel-targets. Oh, en een hardware debug target zit erin wat wel fijn is als je met wat complexer spul bezig bent.

Youtube: PowerElectronicsBlog - Plank2 (4W computer)


  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
En maar eens pielen met SPI... Is het nog aan te raden nadat je de slave hebt aangeroepen, een delay in te zetten?

  • DuDePrOdUcTiOnS
  • Registratie: augustus 2001
  • Laatst online: 08-12 23:26
Dat is helemaal afhankelijk van de slave, check de datasheet :)

www.teamgenie.nl
You raise the blade, you make the change
You re-arrange me till I'm sane
You lock the door, and throw away the key
There's someone in my head but it's not me


  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
Slave en master zijn hetzelfde chipje (PIC16F1459), kan er niets over vinden. Verder zit ik ermee: Moet ik nog pull ups plaatsen? Staat ook niets over in de datasheet.

  • Hans1990
  • Registratie: maart 2004
  • Laatst online: 10:59
Bij SPI heb je geen pull-ups nodig, omdat alle pinnen gewoon door push-pull outputs worden aangestuurd (I2C is enkel open-drain, pinnen kunnen dus enkel de lijnen naar GND schakelen).

Een delay kan handig zijn al wil je je slave niet overspoelen met gegevens. Dat ligt er dus compleet aan hoe snel jouw slave programma weer klaar kan zijn met het uitvoeren van wat het ook moet doen.

  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
Ah, key, maar het hoeft niet perse dus.
Hans1990 schreef op dinsdag 24 maart 2015 @ 20:04:
Bij SPI heb je geen pull-ups nodig, omdat alle pinnen gewoon door push-pull outputs worden aangestuurd (I2C is enkel open-drain, pinnen kunnen dus enkel de lijnen naar GND schakelen).
Maar het mag wel als je de bus dubbel gebruikt voor SPI en I2C?

SPI master lijkt te werken. Heb de SDI en SDO aan elkaar geknoopt en aan de inkomende data een if statement gehangen. Die code vond ik ook niet zo lastig, maar de SPI slave, die heb ik nog niet helemaal kunnen doorgronden om tot code te komen. Ik heb in de 1459 2 slave select kanalen, een hoofdselect en een alternatief. Ik begrijp dat ie standaard op RC6 zit en ik dat niet hoef te bevestigen, tenzij ik hem anders wil hebben. Moet het wel in SSP1CON1 bit 3 tot 0 aanzetten bij dit chipje. Als ik het goed begrijp is het een omgekeerd evenredig systeem, hoge SS betekent geen actie, lage SS betekent dat die chip moet luisteren.

Maargoed, nu dus nog die slave code. Er moet data in SSPBUF gezet worden om terug naar de master te sturen. Na een transactie moet die data er weer uitgehaald worden zodat je een nieuwe transactie kan starten. Maar is het handig om dat, net als bij I2C, in een interrupt te knallen? Want dan zou je dus je interrupt aan je SS hangen?

[Voor 4% gewijzigd door Pizza_Boom op 24-03-2015 22:34]


  • Hans1990
  • Registratie: maart 2004
  • Laatst online: 10:59
Even terzijde; heb je de SPI slave echt nodig? Ik heb je volgens mij laatst iets horen zeggen over zo'n NRF radio chip, en waar je toen achter kwam dat het geen I2C was maar SPI.
Master's zijn namelijk super eenvoudig op te zetten ten opzichte van slaves. Een slave implementatie schrijven probeer ik het liefst zo veel mogelijk te vermijden, vanwege de interrupts, delays, buffer overflows, etc..

De MSSP module kan zoals I2C bij elke ontvangen byte een interrupt genereren. Afhankelijk hoe je je programma indeelt kan dat handig zijn om met interrupts te doen.

Chip Selects zijn meestal laag actief. Alternatieve pin locaties zou ik niet zo druk om maken, tenzij je ze echt nodig hebt.

Bus dubbel gebruiken: zou ik niet doen. Daarom zijn er (grotere) controllers die meer MSSP modules hebben voor gescheiden SPI & I2C.
Mocht je echt een I2C naast SPI nodig hebben , kan je overwegen om een software master I2C te schrijven zodat je I2C op zijn eigen pinnen kan draaien.

  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
NRF radio is inderdaad nog steeds de bedoeling. Volgens mij moet ik 1 kant van de NRF met een master doen en de andere NRF aan een slave hangen? Of heb ik dat verkeerd begrepen?* Dat de master veel makkelijker is, dat heb ik inmiddels gemerkt ja, die had ik zo in elkaar zitten, wat gespiekt bij mijn I2C read en write routine en dat gecombineerd en vooralsnog lijkt het te werken (SDO SDI aan elkaar geknoopt).

Verder weet ik even genoeg. Thanks iig. :)

*EDIT* Verkeerd begrepen dus. Er zit een floating high pin op de NRF die naar beneden trekt op het moment dat de NRF activiteit op de bus signaleert. :) NRF zelf wil altijd slave zijn.

[Voor 17% gewijzigd door Pizza_Boom op 25-03-2015 13:18]


  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
Dat stomme ding wil nog een hoop instellingen vooraf hebben ook. Begrijp ik goed dat je die ook via SPI door moet zetten voordat je een transactie begint, het liefste bij inschakelen van de stroom? Vanmiddag nog ff 2 break out boardjes gesoldeerd zodat ik die 24L01+'s in een breadboard kan gebruiken. Verdient niet de schoonheidsprijs, maar het werkt. O-) :P

[Voor 29% gewijzigd door Pizza_Boom op 26-03-2015 01:54]


  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
Iemand enig idee hoe ik register 10 van pagina 57 moet interpreteren in de datasheet van de NRF24L01+? Ik heb mijn addressing (reg. 3) op 3 bytes staan en de payload (reg. 11) staat op 4 bytes in data pipe 0, maar ik heb geen flauw idee hoe ik reg. 10 moet gaan uitvoeren in mijn initialisatie.

datasheet

  • Infant
  • Registratie: januari 2008
  • Laatst online: 08-12 11:21

Infant

It's a floating Dino!

Dat register is 5 bytes lang.
Dus je moet het register schijven: (0x20 | 0x10)
En dan 5 keer de adress bytes naar buiten shiften.

  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
Infant schreef op zaterdag 28 maart 2015 @ 12:59:
Dat register is 5 bytes lang.
Dus je moet het register schijven: (0x20 | 0x10)
En dan 5 keer de adress bytes naar buiten shiften.
Maar ik heb in register 13 een address width van 3 bytes ingesteld... Moet ik dan niet 3x address bytes shiften?

  • RobV
  • Registratie: juni 2013
  • Niet online

RobV

Welcome to the grid, Program.

Topicstarter
(overleden)
@Pizza_Boom, het klinkt alsof je je eigen driver aan het schrijven bent? Kun je niet beginnen met het gebruiken van de bestaande libraries? Of zijn die niet beschikbaar op PIC? Arduino C is niet zo moeilijk te begrijpen, je zou stiekem kunnen spieken hoe anderen het gedaan hebben.

 | Mijn joystick / simpit project | Blog | Elite Dangerous CMDR Cataclysm72


  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
RobV schreef op zaterdag 28 maart 2015 @ 18:34:
@Pizza_Boom, het klinkt alsof je je eigen driver aan het schrijven bent? Kun je niet beginnen met het gebruiken van de bestaande libraries? Of zijn die niet beschikbaar op PIC? Arduino C is niet zo moeilijk te begrijpen, je zou stiekem kunnen spieken hoe anderen het gedaan hebben.
Dat ben ik ook. Ik had wat info gevonden en heb mijn init zo goed als af. Ik zit eigenlijk alleen met dat address in mijn maag, de rest zou moeten werken (dat roep ik echter vaker. :+ ). Verwarrende is ook dat ze uit gaan van een 5 bit registeraddress, maar om hem te schrijven, je bit 5, 6 en 7 ook moet gebruiken en wel als 001. Daardoor schrijf je dus niet register 0x10, maar 0x30.

Iets anders "lastigs" aan dat ding is dat hij of dummydata verzend als je zelf schrijft, of dummydata wil ontvangen om jou te kunnen schrijven. Efficiëntie van het SPI protocol is dus een beetje weg, maarja. Ik ben nog niet zo ver dat ik hem op de volle 100% zou willen laten draaien en daardoor in de problemen kom. Dan is het wel weer tijd voor een ander apparaatje.

Arduino heb ik eigenlijk niet genoeg kennis van om daar goed uit te kunnen spieken, datzelfde heb ik ook vaak met assembler. Ik wil nog wel eens met Arduino aan de slag, maar momenteel heeft de PIC de prioriteit. Googlen op het TX_ADDR levert me eigenlijk ook vrij weinig op. DIYembedded heeft een leuke tutorial, maar is ontzettend langdradig en ik kan bepaalde stappen van ze niet linken aan wat er moet gebeuren in de code.
Verder is dit een heel handig topic, maar ik wil het niet 1:1 kopiëren. Deze en de DIY tutorial hebben een hoop duidelijk gemaakt, de stijl is heel overzichtelijk, maar ik wil het zelf doen. En ik maak ook andere keuzes op bepaalde punten.


code:
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
56
57
58
59
60
61
62
63
64
65
66
67
68
void nrf_config()           // NRF initialisation code TX mode
    {
        CE = laag;          // chip standby, does not monitor the airdata
        __delay_ms(10);     // delay
        CSN = hoog;         // must be high when idle
        __delay_ms(100);    // delay

        CSN = laag;         // indicate data transmitting to NRF
        spiNRF_write(0x20); // write register(=001) 0 0000
        spiNRF_write(0x0A); // (0000 1010) CRC enabled, interrupts on IRQ enabled, PTX (=transceiver), power up
        CSN = hoog;         // end data transmitting
        __delay_us(1);      // delay

        CSN = laag;
        spiNRF_write(0x21); // write register(=001) 0 0001
        spiNRF_write(0x00); // turn off auto ACK
        CSN = hoog;
        __delay_us(1);
                            // register 0x22 is used only in RX mode

        CSN = laag;
        spiNRF_write(0x23); // write register(=001) 0 0003
        spiNRF_write(0x01); // address width 3 bytes
        CSN = hoog;
        __delay_us(1);

        CSN = laag;
        spiNRF_write(0x24); // write register(=001) 0 0004
        spiNRF_write(0x03); // retry transmitting when failed after 250 uS, try 3 times
        CSN = hoog;
        __delay_us(1);

        CSN = laag;
        spiNRF_write(0x25); // write register(=001) 0 0005
        spiNRF_write(0x05); // operating frequency set to 0000 0101
        CSN = hoog;
        __delay_us(1);

        CSN = laag;
        spiNRF_write(0x26); // write register(=001) 0 0006
        spiNRF_write(0x04); // 1MB/s data rate, -6 dBm output power
        CSN = hoog;
        __delay_us(1);

                            // register 0x27 is status register
                            // register 0x28 is transmitter observer
                            // register 0x29 is received power detector
                            // triggered by power levels above -64dBm in slected channel
                            // register 0x2A - 2F = data pipe addresses
                            // register 0x30 is transmit address

        int i;
        CSN = laag;
        spiNRF_write(0x30); // write register (=001) 1 0000 = transmit address
        for (i=0; i<3; i++) // write addressbyte E7 3x for complete TX_ADDR (= E7E7E7)
            {
                spiNRF_write(0xE7);
            }
        CSN = hoog;
        __delay_us(1);

        CSN = laag;
        spiNRF_write(0x31); // write register (=001) 1 0001
        spiNRF_write(0x04); // 4 byte payload in data pipe 0
        CSN = hoog;
        __delay_us(1);

    }

Deze code zou in principe grotendeels gelijk moeten zijn voor de RX chip, maar als ik al niet zeker ben van mijn TX systeem... Het builden gaat iig zonder errors, ook wel prettig. 8)

[Voor 4% gewijzigd door Pizza_Boom op 28-03-2015 18:52]


  • Sissors
  • Registratie: mei 2005
  • Laatst online: 10:56
SPI is nou eenmaal full duplex, echter veruit de meeste chips hebben dat niet nodig, en dan is inderdaad één lijn gevuld met dummy data.

  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
Maar dat mag het probleem niet zijn atm. Ik zit meer met dat address register...

  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
Hmmm, bij mijn address width register:
RX/TX Address field width
'00' - Illegal
'01' - 3 bytes
'10' - 4 bytes
'11' – 5 bytes
LSByte is used if address width is below 5 byte
Dus ik moet wel 5 bytes erin trappen, maar hij gebruikt alleen de laatste 3 bytes die ik verstuur als address.

  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
Even een vervolg op deze post, dar ik heb nog steeds niet werkend krijg, wellicht dat iemand hier nog een fout ziet? Dit zijn momenteel de RX en TX code:

TX Device:
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*

             ________  _______
        VDD |        \/       | VSS
        RA5 |   PIC16F1459    | RA0
        RA4 |                 | RA1 
        RA3 |                 | Vusb3v3
LED Red RC5 |                 | RC0
LED Gr  RC4 |                 | RC1
SDI CSN RC3 |                 | RC2 
SDI CE  RC6 |                 | RB4 SPI Serial Data in
SPI SDO RC7 |                 | RB5
SDI IRQ RB7 |_________________| RB6 SPI SCL (white)

*/

 #include   <xc.h>
 #include   <stdbool.h>

 #define _XTAL_FREQ 16000000
 #define byte unsigned char


 #define laag   0
 #define hoog   1

 #define CE     RC6     // Chip Enable          output
 #define IRQ    RB7     // Interrupt            input
 #define CSN    RC3     // Chip Select Not      output
 #define SDO    RC7     // Serial Data Out      output
 #define SDI    RB4     // Serial Data In       input
 #define CLK    RB6     // Clock                output



// Config Register: CONFIG1
// Oscillator Selection:                 FOSC_ECH,FOSC_ECH,FOSC_ECL,FOSC_INTOSC,FOSC_EXTRC,FOSC_HS,FOSC_XT,FOSC_LP
// Watchdog Timer Enable:                WDTE_ON,WDTE_NSLEEP,WDTE_SWDTEN,WDTE_OFF
// WDT enabled
// Power-up Timer                        PWRTE_OFF,PWRTE_ON
// MCLR Pin Function Select              MCLRE_ON,MCLRE_OFF
// Flash Program Memory Code Protection  CP_OFF,CP_ON
// Brown-out Reset Enable                BOREN_ON,BOREN_NSLEEP,BOREN_SBODEN,BOREN_OFF
// Clock Out Enable                      CLKOUTEN_OFF,CLKOUTEN_ON
//   
// Internal/External Switchover          IESO_ON,IESO_OFF
// Fail-Safe Clock Monitor Enable        FCMEN_ON,FCMEN_OFF
// Config Register:CONFIG2 
// Flash Memory Self-Write Protection    WRT_OFF,WRT_BOOT,WRT_HALF,WRT_ALL
// PLL                                   PLLEN_ENABLE,PLLEN_DISABLE
// Stack Overflow/Underflow Reset Enable STVREN_ON,STVREN_OFF
// Brown-out Reset Voltage Selection     BORV_LO,BORV_HI
// Low-Voltage Programming Enable        LVP_ON,LVP_OFF

#pragma config FOSC=INTOSC, WDTE=OFF, PWRTE=OFF, MCLRE=ON, CP=OFF, BOREN=OFF, CLKOUTEN=OFF, IESO=OFF, FCMEN=OFF, WRT=OFF, PLLEN=DISABLED, STVREN=OFF, BORV=HI, LVP=OFF,

int knop1, knop2;
bool ack;
unsigned char dataR;
unsigned char dummydata;

unsigned char spi_send(unsigned char dataS)
    {
        SSP1IF  = 0;        // clear interrupt flag
        SSP1BUF = dataS;    // send dataS(end)
        while (!SSP1IF);        // wait till SSP interrupt flag is set
        dataR   = SSP1BUF;  // read SSPBUF to dataR(ead)
        return dataR;
    }

void nrf_config()           // NRF initialisation code TX mode
    {
        CE = laag;          // chip standby, does not monitor the airdata
        __delay_ms(10);     // delay
        CSN = hoog;         // must be high when idle
        __delay_ms(100);    // delay

        CSN = laag;         // indicate data transmitting to NRF
        spi_send(0x20);     // write register(=001) 0 0000
        spi_send(0x0A);     // (0000 1010) CRC enabled, interrupts on IRQ enabled, PTX (=transceiver), power up
        CSN = hoog;         // end data transmitting
        __delay_us(1);      // delay

        CSN = laag;
        spi_send(0x21);     // write register(=001) 0 0001
        spi_send(0x00);     // turn off auto ACK
        CSN = hoog;
        __delay_us(1);
                            // register 0x22 is used only in RX mode

        CSN = laag;
        spi_send(0x23);     // write register(=001) 0 0003
        spi_send(0x01);     // address width 3 bytes
        CSN = hoog;
        __delay_us(1);

        CSN = laag;
        spi_send(0x24);     // write register(=001) 0 0004
        spi_send(0x03);     // retry transmitting when failed after 250 uS, try 3 times
        CSN = hoog;
        __delay_us(1);

        CSN = laag;
        spi_send(0x25);     // write register(=001) 0 0005
        spi_send(0x05);     // operating frequency set to 0000 0101
        CSN = hoog;
        __delay_us(1);

        CSN = laag;
        spi_send(0x26);     // write register(=001) 0 0006
        spi_send(0x04);     // 1MB/s data rate, -6 dBm output power
        CSN = hoog;
        __delay_us(1);

                            // register 0x27 is status register
                            // register 0x28 is transmitter observer
                            // register 0x29 is received power detector
                            // triggered by power levels above -64dBm in slected channel
                            // register 0x2A - 2F = data pipe addresses
                            // register 0x30 is transmit address

        int i;
        CSN = laag;
        spi_send(0x30);     // write register (=001) 1 0000 = transmit address
        for (i=0; i<5; i++) // write addressbyte E7 3x for complete TX_ADDR (= E7E7E7)
            {
                spi_send(0xE7);
            }
        CSN = hoog;
        __delay_us(1);

        CSN = laag;
        spi_send(0x31);     // write register (=001) 1 0001
        spi_send(0x04);     // 4 byte payload in data pipe 0
        CSN = hoog;
        __delay_us(1);

    }

        // send to NRF unit, 4 byte payload
        // after sending data to NRF, empty FIFO by transmitting this data
unsigned char nrf_send(unsigned char data1, unsigned char data2, unsigned char data3, unsigned char data4)
    {
        CSN = laag;
        spi_send(0xA0);         // command to write TX FIFO
        spi_send(data1);        // send data1 to TX FIFO
        spi_send(data2);        // send data2 to TX FIFO
        spi_send(data3);        // send data3 to TX FIFO
        spi_send(data4);        // send data4 to TX FIFO
        CSN = hoog;
        __delay_us(1);


        CE = hoog;                  // make CE high to initiate data transmitting
        __delay_us(100);            // keep CE high for at least 10 uS to transmit data
        CE = laag;                  // make CE low again to stop transmitting
        __delay_us(1);
        
        return 0;
    }
    

void main(void)                         // main program
{
    ANSELA  =   0x00;
    ANSELB  =   0x00;
    ANSELC  =   0x00;
    TRISA   =   0x00;
    TRISB   =   0b10010000;
    TRISC   =   0b00000000;
    OSCCON  =   0b00111100; //internal clock 16 MHz no PLL
    PORTB   =   0x00;
    PORTC   =   0x00;

    // [SPI mastermode]     
    INTCON = 0xD1;
    PIE1 = 0b00001000;
    PIE2 = 0x00;
    PIR1 = 0x00;
    PIR2 = 0x00;
    SSP1ADD  = 0x27;    // 100 kHz, SSPAD 39. instellen Fosc zo langzaam mogelijk !!!
    SSP1STAT = 0b11000000;  // input sampled at end of output time, sending at clock from active to idle
    SSP1CON1 = 0b00111010;  // SSP high clock, baudrate calculated with SSPADD
    SSP1CON3 = 0b00010000;  // SSP overwrite data when buffer is not read in slave mode, no use in mastermode
    // [/SPI mastermode]

    nrf_config();

//mastercode start
    while (1)
    {
        LATC5 = 1;
        __delay_ms(500);
        nrf_send(0x12, 0x12, 0x12, 0x12);
        LATC4 = 1;
        __delay_ms(500);
        LATC4 = LATC5 = 0;
        __delay_ms(500);
    

    }
}

//master stop


RX Device:
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
/*

             ________  _______
        VDD |        \/       | VSS
        RA5 |   PIC16F1459    | RA0
        RA4 |                 | RA1
        RA3 |                 | Vusb3v3
LED Red RC5 |                 | RC0
LED Gr  RC4 |                 | RC1
SDI CSN RC3 |                 | RC2 
SDI CE  RC6 |                 | RB4 SPI Serial Data in
SPI SDO RC7 |                 | RB5
SDI IRQ RB7 |_________________| RB6 SPI SCL (white)

*/

 #include   <xc.h>
 #include   <stdbool.h>

 #define _XTAL_FREQ 16000000
 #define byte unsigned char


 #define laag   0
 #define hoog   1

 #define CE     RC6     // Chip Enable          output
 #define IRQ    RB7     // Interrupt            input
 #define CSN    RC3     // Chip Select Not      output
 #define SDO    RC7     // Serial Data Out      output
 #define SDI    RB4     // Serial Data In       input
 #define CLK    RB6     // Clock                output



// Config Register: CONFIG1
// Oscillator Selection:                 FOSC_ECH,FOSC_ECH,FOSC_ECL,FOSC_INTOSC,FOSC_EXTRC,FOSC_HS,FOSC_XT,FOSC_LP
// Watchdog Timer Enable:                WDTE_ON,WDTE_NSLEEP,WDTE_SWDTEN,WDTE_OFF
// WDT enabled
// Power-up Timer                        PWRTE_OFF,PWRTE_ON
// MCLR Pin Function Select              MCLRE_ON,MCLRE_OFF
// Flash Program Memory Code Protection  CP_OFF,CP_ON
// Brown-out Reset Enable                BOREN_ON,BOREN_NSLEEP,BOREN_SBODEN,BOREN_OFF
// Clock Out Enable                      CLKOUTEN_OFF,CLKOUTEN_ON
//   
// Internal/External Switchover          IESO_ON,IESO_OFF
// Fail-Safe Clock Monitor Enable        FCMEN_ON,FCMEN_OFF
// Config Register:CONFIG2 
// Flash Memory Self-Write Protection    WRT_OFF,WRT_BOOT,WRT_HALF,WRT_ALL
// PLL                                   PLLEN_ENABLE,PLLEN_DISABLE
// Stack Overflow/Underflow Reset Enable STVREN_ON,STVREN_OFF
// Brown-out Reset Voltage Selection     BORV_LO,BORV_HI
// Low-Voltage Programming Enable        LVP_ON,LVP_OFF

#pragma config FOSC=INTOSC, WDTE=OFF, PWRTE=OFF, MCLRE=ON, CP=OFF, BOREN=OFF, CLKOUTEN=OFF, IESO=OFF, FCMEN=OFF, WRT=OFF, PLLEN=DISABLED, STVREN=OFF, BORV=HI, LVP=OFF,

int knop1, knop2, j;
bool ack;
unsigned char dataR;
unsigned char dummydata;
unsigned char data1, data2, data3, data4;

unsigned char spi_send(unsigned char dataS)
    {
        SSP1IF  = 0;        // clear interrupt flag
        SSP1BUF = dataS;    // send dataS(end)
        while (!SSP1IF);        // wait till SSP interrupt flag is set
        dataR   = SSP1BUF;  // read SSPBUF to dataR(ead)
        return dataR;
    }

void nrf_config()           // NRF initialisation code RX mode
    {
        CE = laag;          // chip standby, does not monitor the airdata
        __delay_ms(10);     // delay
        CSN = hoog;         // must be high when idle
        __delay_ms(100);    // delay

        CSN = laag;         // indicate data transmitting to NRF
        spi_send(0x20);     // write register(=001) 0 0000
        spi_send(0x09);     // (0000 1010) CRC enabled, interrupts on IRQ enabled, PRX (=transceiver), power up
        CSN = hoog;         // end data transmitting
        __delay_us(1);      // delay

        CSN = laag;
        spi_send(0x21);     // write register(=001) 0 0001
        spi_send(0x00);     // turn off auto ACK
        CSN = hoog;
        __delay_us(1);
/*                          // register 0x22 is used only in RX mode
        CSN = laag;
        spi_send(0x22);     // write register(=001) 0 0010
        spi_send(0x03);     // receive trough data pipe 0 & 1
        CSN = hoog;
        __delay_us(1); */

        CSN = laag;
        spi_send(0x23);     // write register(=001) 0 0003
        spi_send(0x01);     // address width 3 bytes
        CSN = hoog;
        __delay_us(1);

/*      CSN = laag;         // enable in TX mode
        spi_send(0x24);     // write register(=001) 0 0004
        spi_send(0x03);     // retry transmitting when failed after 250 uS, try 3 times
        CSN = hoog;
        __delay_us(1); */

        CSN = laag;
        spi_send(0x25);     // write register(=001) 0 0005
        spi_send(0x05);     // operating frequency set to 0000 0101
        CSN = hoog;
        __delay_us(1);

        CSN = laag;
        spi_send(0x26);     // write register(=001) 0 0006
        spi_send(0x04);     // 1MB/s data rate, -6 dBm output power
        CSN = hoog;
        __delay_us(1);

                            // register 0x27 is status register
                            // register 0x28 is transmitter observer
                            // register 0x29 is received power detector
                            // triggered by power levels above -64dBm in slected channel
                            // register 0x2A - 2F = data pipe addresses
                            // register 0x30 is transmit address

        int i;
        CSN = laag;
        spi_send(0x2A);     // write register (=001) 1 0000 = transmit address
        for (i=0; i<5; i++) // write addressbyte E7 3x for complete TX_ADDR (= E7E7E7)
            {
                spi_send(0xE7);
            }
        CSN = hoog;
        __delay_us(1);

        CSN = laag;
        spi_send(0x31);     // write register (=001) 1 0001
        spi_send(0x04);     // 4 byte payload in data pipe 0
        CSN = hoog;
        __delay_us(1);

        CSN = laag;         // indicate data transmitting to NRF
        spi_send(0x20);     // write register(=001) 0 0000
        spi_send(0x0B);     // (0000 1010) CRC enabled, interrupts on IRQ enabled, PRX (=transceiver), power up
        CSN = hoog;         // end data transmitting
        __delay_us(1);      // delay

        CE = hoog;          // CE high means receiver is listening to the air data

    }

        // send to NRF unit, 4 byte payload
        // after sending data to NRF, empty FIFO by transmitting this data
unsigned char nrf_send(unsigned char data1, unsigned char data2, unsigned char data3, unsigned char data4)
    {
        CSN = laag;
        spi_send(0xA0);         // command to write TX FIFO
        spi_send(data1);        // send data1 to TX FIFO
        spi_send(data2);        // send data2 to TX FIFO
        spi_send(data3);        // send data3 to TX FIFO
        spi_send(data4);        // send data4 to TX FIFO
        CSN = hoog;
        __delay_us(1);


        CE = hoog;                  // make CE high to initiate data transmitting
        __delay_us(100);            // keep CE high for at least 10 uS to transmit data
        CE = laag;                  // make CE low again to stop transmitting
        __delay_us(1);
        
        return 0;
    }

        // read from NRF unit, 4 byte payload
        // empty RX FIFO after transmission 
void nrf_read()
    {
        CSN = laag;
        spi_send(0x61);             // command to read RX FIFO
        spi_send(0x01);             // read data, send 0x01
        data1 = dataR;              // read SSP1BUF to data1
        spi_send(0x01);             // read data, send 0x01
        data2 = dataR;              // read SSP1BUF to data2
        spi_send(0x01);             // read data, send 0x01
        data3 = dataR;              // read SSP1BUF to data3
        spi_send(0x01);             // read data, send 0x01
        data4 = dataR;              // read SSP1BUF to data4
        CSN = hoog;
        __delay_us(1);

        CSN = laag;
        spi_send(0xE2);             // flush RX FIFO data, data not needed anymore
        CSN = hoog;
        __delay_us(1);

        CSN = laag;
        spi_send(0x27);             // call status register
        spi_send(0x4E);             // clear interrupt, RX FIFO empty
        CSN = hoog;
        __delay_us(1);
    }

        
void main(void)                         // main program
{
    ANSELA  =   0x00;
    ANSELB  =   0x00;
    ANSELC  =   0x00;
    TRISA   =   0x00;
    TRISB   =   0b10010000;
    TRISB7  =   1;
    TRISB4  =   1;
    TRISC   =   0b00000000;
    OSCCON  =   0b00111100; //internal clock 16 MHz no PLL
    PORTB   =   0x00;
    PORTC   =   0x00;

    // [SPI mastermode]     
    INTCON = 0xD1;
    PIE1 = 0b00001000;
    PIE2 = 0x00;
    PIR1 = 0b00;
    PIR2 = 0x00;
    SSP1ADD  = 0x27;    // 100 kHz, SSPAD 39. instellen Fosc zo langzaam mogelijk !!!
    SSP1STAT = 0b11000000;  // input sampled at end of output time, sending at clock from active to idle
    SSP1CON1 = 0b00111010;  // SSP high clock, baudrate calculated with SSPADD
    SSP1CON3 = 0b00010000;  // SSP overwrite data when buffer is not read in slave mode, no use in mastermode
    // [/SPI mastermode]

    nrf_config();

//mastercode start
    while (1)
    {
        if (IRQ == 0)
            {
                LATC4 = 1;
            }
        else if (IRQ == 1)
            {
                LATC5 = 1;
            }
        __delay_ms(300);
        LATC4 = LATC5 = 0;
        __delay_ms(300);

/*      LATC5 = 1;
        __delay_ms(500);
        nrf_read();
        if (data1 == 0x12)
            {
                LATC4 = 1;
            }
        else
            {
                LATC5 = 0;
                __delay_ms(100);
                LATC5 = 1;
            }
        __delay_ms(500);
        LATC5 = LATC4 = 0;
        __delay_ms(500); */
    }
}

//master stop


Probleem is dat ik geen low krijg op mijn IRQ aan de ontvangende (RX) zijde en dus ook geen data uit kan lezen, want er is niets. Als ik de IRQ pin loskoppel gaat ie wel omlaag. Ik heb al de nrf's vervangen met elkaar en vervangen door 2 nieuwe, haalt allebei niets uit. Ik heb gisteravond ook al de code geprobeerd qua registers identiek te maken aan het voorbeeld dat ik gevonden had, maar dat haalde ook niets uit. Ik hoop dat iemand hier nog een idee heeft, want ik weet niet waar ik het nu nog moet zoeken.
Voor de mensen die geen zin hebben om alles terug te lezen: PIC16F1459 en nRF24L01+, 2x.

[Voor 0% gewijzigd door Pizza_Boom op 31-03-2015 18:22. Reden: code=c gemaakt]


  • RobV
  • Registratie: juni 2013
  • Niet online

RobV

Welcome to the grid, Program.

Topicstarter
(overleden)
Misschien nrf-send rond regel 155, CE toggle. Moet de chip niet enabled zijn TIJDENS de data transfer ipv erna?

Bonuspunten voor de documentatie bovenaan met de pinout.

[Voor 4% gewijzigd door RobV op 31-03-2015 13:52]

 | Mijn joystick / simpit project | Blog | Elite Dangerous CMDR Cataclysm72


  • EMP
  • Registratie: november 2000
  • Laatst online: 07:49

EMP

Krulloos!

AH, leuk, een kroegtopic waar ik ook kan meepraten.

Ik heb gewerkt met wat Motorola, Renesas (Hitachi) en Arm (cortex M0 t/m A9) μC'tjes, met de meeste grote studio's en debuggers en vooral veel in C/C++ geprogrammeerd. Ook ASM, maar dat probeer ik tot een minimum te beperken :+

Reden voor zoveel verschillende controllers: een aantal jaar in de detachering werken!

Ik heb ook grotere systemen gedaan (een Intel-i7 IPC met QNX of linux), maar mijn liefde blijft toch bij de kleine chipjes.

De lappen code zal ik een ander keertje moeten lezen ;)

So RAMdisk is *NOT* an installation procedure?


  • RobV
  • Registratie: juni 2013
  • Niet online

RobV

Welcome to the grid, Program.

Topicstarter
(overleden)
Welkom @EMP

 | Mijn joystick / simpit project | Blog | Elite Dangerous CMDR Cataclysm72


  • Ploink
  • Registratie: april 2002
  • Laatst online: 26-11 10:36
Pizza_Boom schreef op dinsdag 31 maart 2015 @ 13:08:
Probleem is dat ik geen low krijg op mijn IRQ aan de ontvangende (RX) zijde en dus ook geen data uit kan lezen, want er is niets. Als ik de IRQ pin loskoppel gaat ie wel omlaag.
Lijkt er op dat je pin geconfigureerd is als output en de nrf hem niet omlaag kan trekken.
Pin RB7 zet je wel als input, maar er is een leuke valkuil. RB7 doet ook dienst als TX voor de serial port en als die aan staat (bitje SPEN in RCSTA), dan kun je de pin nog zo hard op input zetten, het blijft een output ;)

Je gebruikt de uart blijkbaar niet, maar misschien zet een van je libs hem aan?

  • Infant
  • Registratie: januari 2008
  • Laatst online: 08-12 11:21

Infant

It's a floating Dino!

70% van deze kroeg pagina is nu code...

Ik heb die nRFjes altijd op 5 bytes adres gehad, ik kreeg ook niet elke pakket lengte werkend. Een te klein pakketje kan ik me herinneren werkt niet, en een te groot pakket ook niet.

Zo moeten "under the hood" ook op lijp veel rf-ellende synchroniseren, daar schijnt bij die van mij een sweet spot in te zitten.

Nou had ik van die brakke met een PCB antenne, dat als je ze 1 milimeter verschuift het berijk meteen weg is.

Op zich wil je dit, want volgens D. Adams is dat nou eenmaal de toekomst:
For years radios had been operated by means of pressing buttons and turning dials; then as the technology became more sophisticated the controls were made touch-sensitive - you merely had to brush the panels with your fingers; now all you had to do was wave your hand in the general direction of the components and hope. It saved a lot of muscular expenditure of course, but meant that you had to sit infuriatingly still if you wanted to keep listening to the same programme.
Dus ja...

[Voor 38% gewijzigd door Infant op 31-03-2015 17:46]


  • RobV
  • Registratie: juni 2013
  • Niet online

RobV

Welcome to the grid, Program.

Topicstarter
(overleden)
Infant schreef op dinsdag 31 maart 2015 @ 17:40:
70% van deze kroeg pagina is nu code...
Dit is dan ook het software draadje :D

Douglas A. wordt altijd gewaardeerd door mij.

 | Mijn joystick / simpit project | Blog | Elite Dangerous CMDR Cataclysm72


  • Ploink
  • Registratie: april 2002
  • Laatst online: 26-11 10:36
Infant schreef op dinsdag 31 maart 2015 @ 17:40:
70% van deze kroeg pagina is nu code...
Misschien een idee om voor grote lappen code pastebin oid te gebruiken en alleen een linkje in de reactie te plaatsen.

oh en "[code=c]" ipv "[code]" maakt het leesbaarder met kleurtjes :)

C:
1
2
3
4
5
6
7
8
unsigned char spi_send(unsigned char dataS)
    {
        SSP1IF  = 0;        // clear interrupt flag
        SSP1BUF = dataS;    // send dataS(end)
        while (!SSP1IF);        // wait till SSP interrupt flag is set
        dataR   = SSP1BUF;  // read SSPBUF to dataR(ead)
        return dataR;
    }

[Voor 40% gewijzigd door Ploink op 31-03-2015 18:06]


  • Wolfboy
  • Registratie: januari 2001
  • Niet online

Wolfboy

ubi dubium ibi libertas

Ploink schreef op dinsdag 31 maart 2015 @ 18:01:
[...]

Misschien een idee om voor grote lappen code pastebin oid te gebruiken en alleen een linkje in de reactie te plaatsen.

oh en "[code=c]" ipv "[code]" maakt het leesbaarder met kleurtjes :)

C:
1
2
3
4
5
6
7
8
unsigned char spi_send(unsigned char dataS)
    {
        SSP1IF  = 0;        // clear interrupt flag
        SSP1BUF = dataS;    // send dataS(end)
        while (!SSP1IF);        // wait till SSP interrupt flag is set
        dataR   = SSP1BUF;  // read SSPBUF to dataR(ead)
        return dataR;
    }
Imho zou het forum gewoon moeten auto-collapsen bij 20+ regels, zodat je het wel kan uitklappen als je dat wilt maar dat het standaard wat beperkter is kwa grootte.

Op een pastebin hosten is opzich geen slecht idee maar als het een keer down zou gaan ben je alle data kwijt en is de helft van zon' topic zinloos.

Blog [Stackoverflow] [LinkedIn]


  • Pizza_Boom
  • Registratie: juli 2012
  • Laatst online: 08-12 20:30
En toen was er, na het heraanleggen van de las in de centrale lijn, helemaal geen internet meer... Excuseer mij bij langere reactietijd. Ik wil wel, maar kan niet. En bijna 500 regels code op je telefoon doorwerken is niet echt prettig.
RobV schreef op dinsdag 31 maart 2015 @ 13:52:
Misschien nrf-send rond regel 155, CE toggle. Moet de chip niet enabled zijn TIJDENS de data transfer ipv erna?
Volgens de data sheet pagina 72 valt de nrf in standby-II als de FIFO leeg is en CE hoog. Zodra CE laag is, wordt het standby-I.
Bonuspunten voor de documentatie bovenaan met de pinout.
Thanks. Maakt het voor jezelf ook zoveel makkelijker.
Ploink schreef op dinsdag 31 maart 2015 @ 14:59:

Lijkt er op dat je pin geconfigureerd is als output en de nrf hem niet omlaag kan trekken.
Pin RB7 zet je wel als input, maar er is een leuke valkuil. RB7 doet ook dienst als TX voor de serial port en als die aan staat (bitje SPEN in RCSTA), dan kun je de pin nog zo hard op input zetten, het blijft een output ;)

Je gebruikt de uart blijkbaar niet, maar misschien zet een van je libs hem aan?
Ik heb ook 0 ervaring met uart en 4/5 maanden terug wist ik niets van communicatie tussen chips, inmiddels draait I2C en nu wil ik draadloos met spi. Echte libs gebruik ik niet echt, enkel 2 headers, waarvan xc8 voor de compilers is. Maar ook met pulldown erbij verandert er niets. Trek ik echter de nrf lijn eruit, dan valt ie wel naar 0 (en zonder pulldown zweeft ie soms richting 1 en weer terug).
Infant schreef op dinsdag 31 maart 2015 @ 17:40:
70% van deze kroeg pagina is nu code...

Ik heb die nRFjes altijd op 5 bytes adres gehad, ik kreeg ook niet elke pakket lengte werkend. Een te klein pakketje kan ik me herinneren werkt niet, en een te groot pakket ook niet.

Zo moeten "under the hood" ook op lijp veel rf-ellende synchroniseren, daar schijnt bij die van mij een sweet spot in te zitten.

Nou had ik van die brakke met een PCB antenne, dat als je ze 1 milimeter verschuift het berijk meteen weg is.

Op zich wil je dit, want volgens D. Adams is dat nou eenmaal de toekomst:

[...]


Dus ja...
Ik heb ook pcb antenne, maar momenteel staan ze nog geen 10 cm uit elkaar. Ik heb op 3 bytes address geprobeerd, op 5 bytes, geen verschil. Ik las dat je ze op dezelfde payload moet hebben, ze staan samen hetzelfde ingesteld en ik stuur hetzelfde.

Het lastige is nu natuurlijk ook dat er 2 onbekenden zijn. Met I2C heb ik een eeprom genomen om eerst de fouten in de master te elimineren, maar hier gaat dat niet.

Zou jij niet jouw code kunnen opsnorren en e.e.a. eens kunnen vergelijken?
Ploink schreef op dinsdag 31 maart 2015 @ 18:01:
[...]

Misschien een idee om voor grote lappen code pastebin oid te gebruiken en alleen een linkje in de reactie te plaatsen.

oh en "[code=c]" ipv "[code]" maakt het leesbaarder met kleurtjes
Dat kon ik nog net wel aanpassen op mijn telefoon. Ik had eigenlijk verwacht dat het codevak een lengtelimiet had en scrollbaar zou worden.
Pagina: 1 2 Laatste


Nintendo Switch (OLED model) Apple iPhone 13 LG G1 Google Pixel 6 Call of Duty: Vanguard Samsung Galaxy S21 5G Apple iPad Pro (2021) 11" Wi-Fi, 8GB ram Nintendo Switch Lite

Tweakers vormt samen met Hardware Info, AutoTrack, Gaspedaal.nl, Nationale Vacaturebank, Intermediair en Independer DPG Online Services B.V.
Alle rechten voorbehouden © 1998 - 2021 Hosting door True

Tweakers maakt gebruik van cookies

Bij het bezoeken van het forum plaatst Tweakers alleen functionele en analytische cookies voor optimalisatie en analyse om de website-ervaring te verbeteren. Op het forum worden geen trackingcookies geplaatst. Voor het bekijken van video's en grafieken van derden vragen we je toestemming, we gebruiken daarvoor externe tooling die mogelijk cookies kunnen plaatsen.

Meer informatie vind je in ons cookiebeleid.

Sluiten

Forum cookie-instellingen

Bekijk de onderstaande instellingen en maak je keuze. Meer informatie vind je in ons cookiebeleid.

Functionele en analytische cookies

Deze cookies helpen de website zijn functies uit te voeren en zijn verplicht. Meer details

janee

    Cookies van derden

    Deze cookies kunnen geplaatst worden door derde partijen via ingesloten content en om de gebruikerservaring van de website te verbeteren. Meer details

    janee