Het geaccepteerde antwoord van jfpoilpret is erg goed geschreven, perfect geldig en in 99% van de gevallen zal ik precies doen wat hij uitlegt. Zijn oplossingen vallen ruim binnen uw gedefinieerde parameters, dus ze zouden heel goed moeten werken. Maar wat is er beter dan " heel goed "? Perfectie! De vraag gaat tenslotte over het genereren van een exacte waarde. Zoals gezegd is dichtbij genoeg goed in de meeste gevallen (aantoonbaar allemaal), en zelfs als je met zoiets als een klok te maken hebt wanneer 1 seconde 1 seconde moet zijn, moet je nog steeds last hebben van onvolkomenheden in de erfelijke onderdelen.
Wat ik zal suggereren is niet altijd mogelijk. In sommige gevallen is het mogelijk, maar met veel meer gedoe en moeite dan in dit geval. Is het waardig, hangt van geval tot geval af. Mijn doel is vooral om een alternatief voor toekomstige referenties te laten zien dat beter is in enigszins marginale gevallen. Dit is geschreven met beginnende Arduino-gebruikers in gedachten die geen uitgebreide ervaring hebben met elektronica.
Voor meer gevorderde mensen zal dit er waarschijnlijk te uitgebreid en saai uitzien. Maar ik geloof dat diezelfde mensen het waarschijnlijk al weten en dit antwoord niet nodig hebben. Dit geldt ook voor elke microcontroller en elke fabrikant en architectuur. Maar voor andere microcontrollers moet je de juiste datasheet raadplegen om de juiste registers en voorverkoopnamen en -waarden te vinden.
In jouw geval heb je een specifieke frequentie nodig en het leuke is dat die precies 56 kHz kan eigenlijk heel gemakkelijk worden bereikt (praktische onvolkomenheden van de onderdelen niet meegerekend). Dit is dus ook een perfect voorbeeldgeval.
Het genereren van een signaal hangt af van de timers en klokbron van de microcontroller, zoals goed uitgelegd door jfpoilpret. Zijn antwoord behandelt slechts het probleem van één gezichtspunt en dat is gehannes met timers. Maar je kunt ook met de klokbron spelen, of zelfs beter met beide voor synergie en geweldige resultaten. Door de parameters van de omgeving te wijzigen, in dit geval het systeem te hacken en de klokbron te vervangen, kunnen we een specifiek probleem met veel, veel meer gemak en eenvoud aanpakken.
Allereerst, vanwege het wisselen de pinstatus, moet u de ISR twee keer meer uitvoeren dan de signaalfrequentie. Dit is 112.000 keer per seconde. 56.000 en 16.000.000 tellen niet erg goed op, zoals al is aangegeven. We moeten de signaalfrequentie of de tactfrequentie wijzigen. Laten we nu eens kijken naar een onveranderlijke signaalfrequentie en een betere kloksnelheid zoeken.
Het zou het meest eenvoudig zijn om een klok te kiezen met een orde van grootte groter dan 56 kHz (of 112 kHz, maar dat is praktisch hetzelfde), aangezien u alleen nullen toevoegt en dit soort wiskunde voor de meeste mensen het eenvoudigst is. Helaas is alles in deze wereld een soort compromis met iets. Niet elke waarde zal werken.
Het eerste voorbeeld is met een te lage tactgeneratorsnelheid.
Als je een 56.000 Hz-klok kiest, kun je niets doen zoals je zal elke cyclus de ISR moeten bellen en kan niets anders doen. Het is volkomen nutteloos. Als je kiest voor 10 keer hogere snelheid (560 kHz), heb je 9 (10 cycli voordat de timer zijn maximale waarde bereikt - één cyclus om de ISR-functie aan te roepen) microcontroller-cycli om je werk te doen en dit is heel goed mogelijk kan niet genoeg zijn. Je hebt gewoon vaak meer rekenkracht nodig.
Als je een waarde kiest die veel te groot is, zoals 56 MHz, kan de microcontroller er gewoon niet mee werken. Het is veel te snel. Dus het simpelweg kiezen van de grootste waarde in de winkel zal het ook niet besparen.
Originele Arduino Uno R3 heeft een standaardklok op 16 MHz, dus alles wat langzamer is dan gegarandeerd werkt. De volgende waarde die een grootteorde groter is dan 56 en lager dan 16 MHz is 5,6 MHz. Dit zal ertoe leiden dat we de ISR elke 50 cycli kunnen bellen en de perfecte timerfrequentie van 112.000 Hz zal creëren. En je signaal is precies 56 kHz. Je hebt 49 MCU-cycli om je programma tussen ISR-oproepen uit te voeren, maar het is nog steeds ongeveer 1/3 van de snelheid van de oorspronkelijke klok. Men kan 112 als basis gebruiken en een 11,2 MHz klok gebruiken en dit geeft ongeveer 2/3 van de standaard 16 MHz resonator. De ISR-functie wordt elke 100 cycli aangeroepen en genereert nog steeds een perfect 56 kHz-signaal.
Er zijn echter twee grote problemen met deze waarden.
-
Het eerste probleem hangt sterk af van uw behoeften: u offert ongeveer 1/3 (met 11,2 MHz) van uw maximale rekenkracht op om de exacte signaalfrequentie te krijgen die een gemakkelijk te vinden registerwaarde gebruikt (OCR iirc ). Je vindt het misschien goed of misschien niet.
-
Het tweede probleem is een harde showstopper : het is heel gemakkelijk om waarden te vinden, maar vaak bestaan ze gewoon niet als een vervaardigde klokbron. Dit is Farnell's resonatorwebpagina die simpelweg zowel 5,6 MHz als 11,2 MHz mist.
Om dit te omzeilen, kunnen we kijk naar beschikbare resonatorwaarden en ontdek iets anders dat kan worden gebruikt om precies gewenste waarden te genereren. Als we 56 door 4 delen, krijgen we 14 en gelukkig is er een 14 MHz resonator. Dit geeft ons een veel hogere snelheid en meer vermogen en een even gemakkelijk te vinden registerwaarde. Om de ISR 112.000 keer per seconde te bellen, moeten we de waarde decimaal 124 of hexadecimaal 0x7C in het OCR-register plaatsen, dus met het tellen van 124 cycli + 1 voor het aanroepen van de ISR, krijgen we onze gewenste perfecte waarde.
NB
- ISR - interrupt service routine (dit is de code die alleen wordt uitgevoerd op gegenereerde interrupts)
- Hoe groot uw programma kan zijn, hangt af van de geheugengrootte! Het heeft niets te maken met de kloksnelheid en heeft niets te maken met hoe vaak je de ISR belt.
-
Wanneer de microcontroller start met een programmacommando, wordt een teller opgehoogd. Als er een interrupt wordt gegenereerd, wordt de ISR aangeroepen en wordt deze waarde opgeslagen in een speciaal register. Wanneer de ISR-code is voltooid, wordt de waarde van de programmateller hersteld vanuit dit speciale register en gaat het programma verder waar het werd onderbroken alsof het nog nooit was gebeurd.
Ik zal een extreem dom voorbeeld geven . Als je een purist bent, waarschuw ik je: neus- en oogbloedingen kunnen optreden.
Stel je voor dat je van ergens naar ergens moet lopen. De stapsgewijze route-instructies zijn uw hoofdprogramma en de bijbehorende opdrachten. Hoe snel je loopt of rent, hangt af van je 'kloksnelheid', maar niet van de route-instructies (30 stappen vooruit, 1 draai 90 graden naar links, 10 stappen vooruit, 45 graden rechts, etc.) Ze zijn altijd hetzelfde . Stel je nu eens voor dat een klein kind of een hebzuchtige corrupte lokale politicus je schoenen zo nu en dan losmaakt. Dit is de gebeurtenis die een onderbreking genereert. Dan stop je na je laatste stap, kniel je en knoop je je schoen weer vast. Dit is je ISR-programma.
Daarna ga je verder vanaf de plek waar je bent gestopt; je begint niet vanaf het begin. Als je onbezorgd in de wereld loopt en met de hele tijd loopt, maakt het je niet uit, zelfs als je je schoen om de andere stap moet strikken. Als je het echter doet met beperkte tijd, zoals 100 meter rennen op de Olympische Spelen (of rennen voor een hongerig vleesetend roofdier), kan het stoppen en strikken van je schoenen ernstige gevolgen hebben. Hetzelfde geldt voor microcontrollers. Zelfs als u slechts één regel code uitvoert, zal uw programma doorgaan, zij het traag. Als je helemaal niets om snelheid geeft, is dat geen probleem. Als u wat tijdgerelateerde dingen moet doen, zoals andere timerafhankelijke acties, kan interferentie zeer ongewenst en problematisch zijn.
-
Minder is meer! Een snellere klok is niet altijd beter. Langzamere apparaten verbruiken aanzienlijk minder stroom. Dit kan een cruciaal punt zijn in een apparaat dat op batterijen werkt.
-
De benodigde cycli zijn afgeleid van deze formules:
(kloksnelheid / (voorschrijverwaarde * benodigde ISR oproepfrequentie)) - 1