Atmel start 4: Blinky två-växlar, Pull-Up motstånd och Bit Ops (9 / 11 steg)
Steg 9: Blinky två-innebörden av uttalanden
Den övergripande idén för Blinky två program: först ställa in B0 som en utgång och B1 (och övriga) som indata. B0 drivar LED och B1 är en ingång för växeln. Vi vill ha lampan att blinka, vilket innebär B0 måste ständigt växla stater om indata B1 när logik 0 (dvs stift på marken). För LED blinkar måste vi växelvis skriva 0 och 1 till exakt ett stift, nämligen B0 utan att det påverkar eventuella andra pin. Vi gör detta genom att använda bitvis operationer på ett sådant sätt att den påverkar endast B0. För att avgöra om indata på B1 är logik 0, använder vi en mask (och en bitvis drift) för att välja ut den B1 lite och testa om det är noll, som motsvarar till lampan i en blinkande läge. Normalt vill man inte använda sådant komplicerat arrangemang om det inte fanns något annat val. Växeln skulle sannolikt placeras på en annan tillgänglig port separat från lampan.
För vissa av diskussionen nedan, kanske du vill skriva ut den Blinky två kodning för att enkelt jämföra med förklaringen.
#include, #define F_CPU 8000000UL och #include inte har ändrats från Blinky One, eller har uttalandena som DDRB = 0b00000001, while(1), och _delay_ms uttalanden.
Märker att DDRB = 0b00000001 ställer B0 som en utgång medan alla andra B fysiska stiften är ingångar till MCU. B1 är särskilt indata. B0 drivar LED och B1 känner av växeln.
PORTB = 0b00000010: här, eftersom B0 är en utgång, högra 0 i PORTB tilldelningen anger pin B0 till noll volt (LED "av"). Nästa, eftersom B1 är en ingång, 1 PORTB uppdraget skriver en 1 till en ingång (B1) som aktiverar B1 pull-up resistor.
uint8_t: Osignerat 8-bitars heltal som brukar kallas en "byte". Här variabeltypen hålla tal bestående av högst 8 bitar. Denna variabel kan variera från 0 till 11111111 som är 255 (eller 0 till 0xFF). Uint8_t är en "definierad typ" och är inte hemma i C/C++ även dessa språk har "röding" och "unsigned char". Observera att en "signerat" byte som int8_t också skulle ha ett värde 0 till 0xFF men den mest signifikanta biten (dvs z i 0bzxxxxxxx) är 1 för negativ och 0 för positiva tal.
uint8_t Mask = 0b00000010: definierar en 8-bitars variabel Mask som ges värdet av 0b00000010. Masken kommer att användas för att eliminera bitarna 0 och 2-7 från behandling.
Uint8_t MaskL = 0b00000001: definierar en 8 bitars maskering variabel MaskL med ett värde av 0b00000001. L i MaskL tjänar som en påminnelse om att det gäller för LED. MaskL används för att ta bort bitar B1 genom B7 från behandling och påverkar endast lite B0.
uint8_t Test = 1: en 8-bitars variabel med tanke på det ursprungliga värdet av 0b00000001. I det här fallet spelar det initiala värdet ingen roll eftersom variabeln Test kommer att ges ett värde före kontroll av dess värde. Den '= 1' delen kunde har lämnats av; Semikolonet krävs dock fortfarande.
Test = PINB & Mask: The PINB uttalande kommer att läsa bitarna i registret som motsvarar bitarna B7 genom B0. Den "&" föreställer en bit-för-bit logiskt och (se tabell 2). Bara lite #1 i testvariabeln (dvs lite motsvarar B1) kommer att behålla det ursprungliga PINB värdet efter Maskeringen (dvs & Mask) [16]. Följaktligen per tabell 2, lite variabeln Test kommer att ha alla nollorna utom möjligen för B1 som kan vara antingen 0 eller 1.
När slutet av kabeln är ansluten till 0v järnväg, pin B1 blir noll och så PINB & Mask kommer att producera alla noll för alla bitar och Test måste därför värdet 0. MCU kommer sedan att köra LED "på". Om du tar bort i slutet av kabeln placerar pull-up resistor Vcc på B1 PIN-koden så att värdet av PINB & Mask har värdet 0b00000010. MCU kommer att se ett annat värde för testet och det kommer att inaktivera LED.
IF(x): en flödeskontroll som utför uttalanden mellan två följande hängslen {} när uttrycket x är sant. I det här fallet uttalande x har formuläret Test == 0. Dubbel likhetstecknet "==" frågar om variabeln "Test" är samma som "noll" (dvs 0x00). I C/C++, det logiska 'falskt' är motsvarande värdet '0', men den logiska 'true' är något inte '0' som '1' eller ' 5' och så vidare. För Blinky två, variabeln "Test" är noll när växeln är stängd och som har när vi vill att lampan blinka. Så vi använder uttrycket "om (Test == 0)".
PORTB | = MaskL: allmänt, den vertikala linjen | innebär att bitvis eller [16]. Uttalandet är en genväg för
PORTB = PORTB | MaskL
Högra PORTB läser det föregående värdet skickas till portB. Vänstra PORTB skriver sedan resultaten av bitvis eller tillbaka till portB. Maskeringen använder MaskL = 0b00000001 med 1 endast i #0-läge (motsvarande B0), som styr LED. Eller kommer då endast påverka lite B0 genom att ställa det till logik 1 (stift 12 kommer att Vcc) som diskuteras i samband med tabell 3. De andra bitarna i portB skriva kommer att vara samma som de var när först läste. Så när PORTB skrivs, kommer att ingen av Pull-Up motstånd aktiveras eller inaktiveras! Endast den minst signifikanta biten (dvs B0) skrivs till 1 som kommer att placera 5v på det fysiska B0 stiftet och som kommer att aktivera LED.
PORTB & = ~ MaskL: detta uttalande är genvägen för PORTB = PORTB & ~ MaskL där & är bitvis AND-operationen (jfr, tabell 4). Högra PORTB läser värdena tidigare skrivit till portB. Vänstra PORTB skriver resultatet av och tillbaka till portB. Givet det MaskL = 0b00000001 sedan ~ MaskL = 11111110. OCH att ange bit #0 i PORTB logik 0. De återstående bitarna från PORTB kommer inte att påverkas och de ursprungliga värdena skrivs tillbaka till portB. Anslutning av pull-up motstånd kommer därför inte att påverkas. PIN-koden B0, som driver LED, sätts till noll och LED kommer att vara "off".