Början Microcontrollers del 7: Omarbetning av det första programmet att göra LED blinkar
Du har skrivit det första programmet, som visade på en LED. Ja, det var spektakulärt! Tja, inte riktigt, men låt oss införa lite galenskap till LED. Vi ska ge det en "bipolära" personlighet genom att blinka. Då vi kliver upp ett snäpp och gör det blinka verkligen snabbt. Programmet är förvånansvärt koncis och lätt att genomföra.
Se själv:
#include < avr/io.h >
#include < util/delay.h >
int main(void)
{DDRB | = 1 << PINB0;
samtidigt (1)
{
PORTB ^ = 1 << PINB0;
_delay_ms(100);
}
}
Hallå!! Vilka är dessa galna symboler! Crazy verkar vara ett gemensamt tema här. Tja, ska jag förklara. Men jag lovar, det är ganska lätt. Du behöver bara att memorera några saker. Jag kommer komma in en liten bit av detalj, men om du inte får det, inte oroa sig, bara memorera vad i hela uttrycket åstadkommer och du kommer att bli bra. Jag kommer att ge dig ett tips på vägen. Här kommer detaljerna i bitvis operationer:
Det finns logiska operatorer kallas och, eller inte och XOR som vi sysslar med på denna punkt. De verkligen menar vad de säger. Detta är allt för att jämföra två bitar, "1" och "0". Se? Hur kan bara jämföra två tal vara svårt! "1" och "1" är sann eller "1". Och ja, du gissade rätt, "0" och "0" är FALSKT eller "0". Men vad är "0" och "1" och vice versa? Tja, falskt eller "0", uppenbarligen. Dessa killar är olika, så, verkligen, de är falska.
Exempel och binära tal drift (den "&" används i C-programmering för och):
01001011 &
10001101
är lika med
00001001
Enkelt, rätt? Väl, eller ännu enklare! "1" eller "1" är "1", naturligtvis. "0" eller "0" är också "0". Det börjar mycket liknar AND, men här är skillnaden. Om två tal är olika, kommer att det resultera i "1". Så, "1" eller "0" "1".
Låt oss använda samma binära nummer för exempel (rolig tecknet "|" är eller, ibland ovanför "\" på tangentbordet):
01001011 |
10001101
är lika med
11001111
Hmm, som vände på alla platser där det var saknat dem! Det är där magiskt händer. Ja, det höll de i det första numret och där det finns sådana i andra binärt tal, men inte först, det ändrade de till sådana. Mycket enkel. INTE bara tar alla bitar och vänder dem. Till exempel för denna binärt tal: 01001101 kommer att förvandlas till 10110010. Det visade 0 till 1 och 1 till 0 är, men får inte detta ihop med XOR.
XOR liknar OR men "1" XOR "1" är faktiskt "0". Jag ska bara Visa exemplet och du kan räkna ut vad happenes.
01001011 ^
10001101
är lika med
11000110
Japp, du gissade det, den "^" ovan "6" är symbolen för XOR. Hmmm... Den "|" och den "^" i programmet. Cool. Tja, eftersom vi är tänkande program, låt oss disect grejer vi vet inte ännu!
#include < util/delay.h >
Du vet redan vad den < avr/io.h > gör, så jag inte kommer slösa din tid med det, men det finns ett nytt #include uttalande. Delay.h kommer att ge oss ett par bekväma metoder för oss att använda. Precis som namnet antyder, kommer att delay.h ge oss ett sätt att skapa förseningar i vårt program.
Hoppa över "main" eftersom vi vet att redan, ser vi den DDRB förändrats. Bli inte rädd! Här är processen från där vi var dit vi är:
Detta är vad vi hade innan. Detta är inte ett mycket bra sätt av minipulating stiften eftersom vi bara bytt alla stiften från 1 till 7 som indata, men "what if" vi hade ett större program som används dessa pins för andra saker, som till exempel, stift 2 allpies broms tryckkontroll för antilåsningssystemet. Du skulle inte bara godtyckligt sätta så pass som indata. Som skulle göra din bromsar värdelös (som skulle vara riktigt illa).
DDRB = 0b00000001;
Vi behöver ett sätt att bara påverka en bit, pin 0 bit. Tja, om du tittar ovan på "Eller", kan vi göra detta med en mask (inte karneval masken du tänker, men en binär mask.
DDRB = DDRB | 0b00000001;
Detta kommer att tar sin forna jag och "Eller" det till en mask. Masken är: 0b00000001. Ja det ser ut som den faktiska binärt tal, men om den tidigare DDRB var, säga, 0b01001010, sedan göra ett eller som med vår mask skulle vara: 0b01001010 | 0b00000001 = 0b01001011. Vad är annorlunda i resultatet. Just det, bara pin 0 bit ändras!
Denna statememt kan komprimeras ytterligare i C++:
DDRB | = 0b00000001;
Men det är inte vad som finns i programmet. Även om detta är helt giltiga, varför inte vi dra nytta av några av definitionerna i huvudfilen io.h. Jag menar, det är där för vår bekvämlighet, inte är det? Märka min användning av sammandragningar! Detta är samma i C++: "det är" är verkligen "det", precis som "DDRB | = 0b00000001" är samma som "DDRB = DDRB | 0b00000001 ". Jag sjunka i min stol med den dåliga analogin. Whataver, hjälper till!
Så varför "DDRB | = 1 << PINB0"?
1 << PINB0 är handlingen att skapa masken. "1" representerar vad kommer att införas i masken, den << är en vänster SKIFT operatör. Den gör exakt vad det står, och PINB0 är ett antal positioner som "1" kommer att flytta vänster. PINB0 är i huvudsak bara lika med 0. Så du börjar med en 0b00000000, och du lägger till "1" för att göra 0b00000001 och sedan du flytta den till vänster 0 positioner. Så är du kvar med 0b00000001, lika många från ovan. Så, Tänk om det var PINB4? Uttalandet skulle vara: 1 << PINB4. "1" skulle skiftas vänster 4 gånger resulterar i: 0b00010000. Kom ihåg att vi använder ett noll index, så finns det fyra 0s efter 1.
Låt oss gå vidare till While loop. Du har rätt, vi hade inte något i "oändlig loop" innan. Tja, nu behöver vi mikrokontroller att visa några åtgärder. Detta är endast möjligt i slingan. Slingan är där åtgärden upprepas om och om igen. Om åtgärden var ligger före öglan, skulle sedan åtgärden bara ske en gång, som att sätta riktningen av PIN-koden, som är lämplig för detta program. Men för att skapa för alltid blinka, vi måste vända PINB0 på och av i slingan. Här finns också där förseningarna kommer in. Om vi inte hade förseningar, vi skulle inte se lysdioden blinkar alls, det skulle se ut som det är bara å sedan blinkandet skulle uppstå snabbare än vad ögat kan uppfatta, så vi måste sakta ner.
Vi vet hur man ställer en viss bit i det binära talet, men vi vet inte hur man gör lite specifika "0" om det är "1" ännu. Följande kod gör just detta, men du kommer att märka att det är inte vad programmet visar. Första par linjer vänder lite till "1" (5 volt, ljus), och pausar för 100 millisekunder (Förresten, kan du använda mikrosekunder genom att ändra "ms" till "oss"). De andra två raderna visar PINB0 lite till "0" (0 volt, inget ljus). Nej, och jämförelsen kan inte bara göra en "0" från lite, men om du inte "~" den binära tal masken, det kommer att vända alla av 0s till 1s och alla 1s till 0s. Detta gör att du kan bara påverka den PINB0 biten och förvandla det till "0". Jag la parentesen bara för att innehålla maskering funktion så inte kunde inte hela maks och inte bara "1" innan det vänster skiftet "<<".
PORTB | = 1 << PINB0;
_delay_ms(100);
PORTB & = ~ (1 << PINB0);
_delay_ms(100);
Om förseningen kommer att vara samma för på och av, kunde vi förkorta de föregående fyra raderna till endast två och dra nytta av funktionen XOR. Kom ihåg att XOR stänger vår specifika stift till 1 om det är 0 och vice versa. Denna anvisning påverkar endast PINB0. Varje gång som instruktionen körs, kommer det knäppa lite till motsatsen.
PORTB ^ = 1 << PINB0;
_delay_ms(100);
Det var allt. Se det inte var smärtsamt alls.