Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Lecture 4

Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 35

BM-305

Mikrodenetleyiciler
Güz 2019
(4. Sunu)
(Dr. Öğr. Üyesi Deniz Dal)
Mikrodenetleyici/Mikrokontrolör
Von Neumann Architecture Harvard Architecture (AVR)

ANALOG
INPUTS
Atmel AVR ATMega328P Mikrodenetleyicisi
The ATmega328 is a single chip microcontroller created by Atmel (acquired by Microchip
in 2016) and belongs to the megaAVR series.
• 8-bit AVR RISC-based microcontroller,
• 32 KB flash memory with read-while-write capabilities,
• 2 KB SRAM,
• 1 KB EEPROM,
• 23 general purpose I/O pins,
• 32 general purpose registers,
• three flexible timers/counters with compare modes,
• internal and external interrupts,
• serial programmable USART,
• SPI serial port,
• 6-channel 10-bit A/D converter,
• programmable watchdog timer with internal oscillator
Atmel AVR ATMega328P Mikrodenetleyicisi
Atmel AVR ATMega328P Mikrodenetleyicisinin
Pinout Diyagramı
Atmel AVR
ATMega328P
Mikrodenetleyicisini
n
Blok Diyagramı
AVR CPU
Atmel AVR ATMega328P Mikrodenetleyicisinin Bellekleri
(http://blog.jcole.us/category/electronics/)
Flash Memory (32 KB)
Flash memory, or just flash, is erasable, non-volatile storage used for program storage. When
you have compiled a program and you upload it to the device, this is where it’s stored. When
your program runs, it is run directly from the flash memory (it is not copied into RAM as most
PCs would do).
SRAM Memory (2 KB)
Static RAM (SRAM) is used for transient program state (such as variables) as well as the
program stack and any allocations made by the program. When the program starts, all global
variables are initialized in SRAM by a special routine generated automatically by the compiler.
EEPROM Memory (1 KB)
EEPROM (electrically erasable, programmable, read-only memory) is used for non-volatile
persistent storage. It is a good place to write configuration values (such as baud rates, unique
IDs, etc.), to keep track of counters over a long term, and to keep static data that isn’t needed
frequently.
Atmel AVR ATMega328P Mikrodenetleyicisinin
Zamanlayıcıları/Sayıcıları (Timers/Counters)
8 Bit Timer/Counter 0
Timer0 is an 8-bit timer, meaning its counter register can record a maximum value
of 255 (the same as an unsigned 8-bit byte). Timer0 is used by native Arduino
timing functions such as delay() and millis().
16 Bit T/C 1
Timer1 is a 16-bit timer, with a maximum counter value of 65535 (an unsigned 16-
bit integer). The Arduino Servo library uses this timer.
8 Bit T/C 2
Timer2 is an 8-bit timer that is very similar to Timer0. It is used by the Arduino
tone() function.
http://arduinodiy.wordpress.com/2012/02/28/timer-interrupts/
Atmel AVR ATMega328P Mikrodenetleyicisinin
Bekçi Köpeği/Koruma Zamanlayıcısı (Watchdog
Timer)
This device monitors CPU activity and sends reset signals on a
periodic basis. This feature becomes useful when the
microcontroller is employed in embedded application: if some
unexpected situation leads the CPU to get stuck in an infinite
cycle, after a short period the watchdog will issue a reset signal
so the CPU can recover and resume normal operation.

http://www.cs.jhu.edu/~jorgev/cs333/usbkey/guide.htm
Atmel AVR ATMega328P Mikrodenetleyicisinin
Genel Amaçlı I/O Portları

A port is a group of 8 pins or set of pins used for exchanging data


with the external World.
The Atmel AVR ATMega328P microcontroller has three ports:
• PORT B (Digital pins 8 to 13)
• PORT C (Analog input pins)
• PORT D (Digital pins 0 to 7)
Atmel AVR ATMega328P Mikrodenetleyicisinin
Port Saklayıcıları (Registers)
• 8-bit port registers allow for lower-level and faster manipulation of
the I/O pins of the microcontroller on an Arduino board. (Each bit
of a register corresponds to a particular pin.)
• Each port (B, C and D) is controlled by three registers, which are
also defined variables in the Arduino language.
• The DDR (Data Direction Register) determines whether the pin is
an INPUT (0) or OUTPUT (1).
• The PORT register controls whether the pin is LOW (0) or HIGH(1).
• The PIN register reads the state of INPUT pins set to input with
pinMode().
Atmel AVR ATMega328P Mikrodenetleyicisinin
Port Saklayıcıları (Registers)
PORT D MAPS TO ARDUINO DIGITAL PINS 0 TO 7
DDRD - The PORT D Data Direction Register - read/write Each bit of these
PORTD - The PORT D Data Register - read/write registers corresponds to
PIND - The PORT D Input Pins Register - read only a single pin; e.g. the low
PORT B MAPS TO ARDUINO DIGITAL PINS 8 TO 13 bit of DDRB, PORTB, and
DDRB - The PORT B Data Direction Register - read/write PINB refers to pin PB0.
PORTB - The PORT B Data Register - read/write (Digital pin 8)
PINB - The PORT B Input Pins Register - read only

PORT C MAPS TO ARDUINO ANALOG PINS 0 TO 5 If the low bit of DDRB is 0,


DDRC - The PORT C Data Direction Register - read/write Pin 8 is INPUT. Similarly, if
PORTC - The PORT C Data Register - read/write the low bit of DDRB is 1, Pin
PINC - The PORT C Input Pins Register - read only 8 is OUTPUT.
Bitwise AND
The bitwise AND operator in C++ is a single ampersand, &, used between two other integer expressions. Bitwise
AND operates on each bit position of the surrounding expressions independently, according to this rule: if both
input bits are 1, the resulting output is 1, otherwise the output is 0. Another way of expressing this is:

0 & 0 == 0
0 & 1 == 0
1 & 0 == 0
1 & 1 == 1

In Arduino, the type int is a 16-bit value, so using & between two int expressions causes 16 simultaneous AND
operations to occur. In a code fragment like:

int a = 92; // in binary: 0000000001011100


int b = 101; // in binary: 0000000001100101
int c = a & b; // result: 0000000001000100, or 68 in decimal.

Each of the 16 bits in a and b are processed by using the bitwise AND, and all 16 resulting bits are stored in c,
resulting in the value 01000100 in binary, which is 68 in decimal.
Bitwise AND
One of the most common uses of bitwise AND is to select a particular bit (or bits) from an
integer value, often called masking. For example, if you wanted to access the least significant
bit in a variable x, and store the bit in another variable y, you could use the following code:

int x = 5; // binary: 101


int y = x & 1; // now y is 1
x = 4; // binary: 100 Bir sayının tek mi çift mi olduğu bu
y = x & 1; // now y is 0 test ile öğrenilebilir.
İPUCU
Bit bazında VE operatörü ve ilgili maske sayesinde:
-Bir grup bit içerisindeki belirli bir biti SIFIR yapabilirsiniz.
-Bir grup bit içerisindeki belirli bir bitin değerini öğrenebilirsiniz.
Bitwise OR
The bitwise OR operator in C++ is the vertical bar symbol, |. Like the & operator, | operates
independently each bit in its two surrounding integer expressions, but what it does is different
(of course). The bitwise OR of two bits is 1 if either or both of the input bits is 1, otherwise it is
0. In other words:
0 | 0 == 0
0 | 1 == 1
1 | 0 == 1
1 | 1 == 1
Here is an example of the bitwise OR used in a snippet of C++ code:
int a = 92; // in binary: 0000000001011100
int b = 101; // in binary: 0000000001100101
int c = a | b; // result: 0000000001111101, or 125 in decimal.
Bitwise OR is often used to make sure that a given bit is turned on (set to 1) in a given
expression. For example, to copy the bits from a into b, while making sure the lowest bit is set
to 1, use the following code:
b = a | 1;
İPUCU
Bit bazında VEYA operatörü ve ilgili maske sayesinde:
-Bir grup bit içerisindeki belirli bir biti BİR yapabilirsiniz.
Bitwise XOR
There is a somewhat unusual operator in C++ called bitwise exclusive OR, also known as bitwise XOR.
(In English this is usually pronounced "eks-or".) The bitwise XOR operator is written using the caret
symbol ^. This operator is similar to the bitwise OR operator |, except that it evaluates to 1 for a given
position when exactly one of the input bits for that position is 1. If both are 0 or both are 1, the XOR
operator evaluates to 0:
0 ^ 0 == 0
0 ^ 1 == 1
1 ^ 0 == 1
1 ^ 1 == 0
Another way to look at bitwise XOR is that each bit in the result is a 1 if the input bits are different, or 0
if they are the same.
Here is a simple code example:
int x = 12; // binary: 1100
int y = 10; // binary: 1010
int z = x ^ y; // binary: 0110, or decimal 6
The ^ operator is often used to toggle (i.e. change from 0 to 1, or 1 to 0) some of the bits in an integer
expression while leaving others alone. For example:
y = x ^ 1; // toggle the lowest bit in x, and store the result in y.
İPUCU
Bit bazında ÖZEL VEYA operatörü ve ilgili maske sayesinde:
-Bir grup bit içerisindeki belirli bir bitin DEĞİLİNİ elde edebilirsiniz.
Bitwise NOT
The bitwise NOT operator in C++ is the tilde character ~. Unlike & and |, the bitwise NOT
operator is applied to a single operand to its right. Bitwise NOT changes each bit to its
opposite: 0 becomes 1, and 1 becomes 0. For example:

int a = 103; // binary: 0000000001100111


int b = ~a; // binary: 1111111110011000 = -104

You might be surprised to see a negative number like -104 as the result of this operation. This
is because the highest bit in an int variable is the so-called sign bit. If the highest bit is 1, the
number is interpreted as negative. This encoding of positive and negative numbers is referred
to as two's complement.

As an aside, it is interesting to note that for any integer x, ~x is the same as -x-1.
Bitshift Operators (Left Shift and Right Shift)
There are two bit shift operators in C++: the left shift operator << and the right shift operator
>>. These operators cause the bits in the left operand to be shifted left or right by the number
of positions specified by the right operand.
For example:

int a = 5; // binary: 0000000000000101


int b = a << 3; // binary: 0000000000101000, or 40 in decimal
int c = b >> 3; // binary: 0000000000000101, or back to 5 like we started with

When you shift a value x by y bits (x << y), the leftmost y bits in x are lost, literally shifted out
of existence:

int a = 5; // binary: 0000000000000101


int b = a << 14; // binary: 0100000000000000 - the first 1 in 101 was discarded
Bitshift Operators (Left Shift and Right Shift)
If you are certain that none of the ones in a value are being shifted into oblivion, a simple way
to think of the left-shift operator is that it multiplies the left operand by 2 raised to the right
operand power. For example, to generate powers of 2, the following expressions can be
employed:

1 << 0 == 1
1 << 1 == 2
1 << 2 == 4
1 << 3 == 8
...
1 << 8 == 256
1 << 9 == 512
1 << 10 == 1024
...
Bitshift Operators (Left Shift and Right Shift)
When you shift x right by y bits (x >> y), and the highest bit in x is a 1, the behavior depends on
the exact data type of x. If x is of type int, the highest bit is the sign bit, determining whether x
is negative or not, as we have discussed above. In that case, the sign bit is copied into lower
bits, for esoteric historical reasons:
int x = -16; // binary: 1111111111110000
int y = x >> 3; // binary: 1111111111111110
This behavior, called sign extension, is often not the behavior you want. Instead, you may wish
zeros to be shifted in from the left. It turns out that the right shift rules are different for
unsigned int expressions, so you can use a typecast to suppress ones being copied from the
left:
int x = -16; // binary: 1111111111110000
int y = unsigned(x) >> 3; // binary: 0001111111111110
If you are careful to avoid sign extension, you can use the right-shift operator >> as a way to
divide by powers of 2. For example:
int x = 1000;
int y = x >> 3; // integer division of 1000 by 8, causing y = 125.
Shorthand (Compound) Assignment Operators
Often in programming, you want to operate on the value of a variable x and store the modified value back
into x. In most programming languages, for example, you can increase the value of a variable x by 7 using
the following code:
x = x + 7; // increase x by 7
Because this kind of thing occurs so frequently in programming, C++ provides a shorthand notation in the
form of specialized assignment operators. The above code fragment can be written more concisely as:
x += 7; // increase x by 7
It turns out that bitwise AND, bitwise OR, left shift, and right shift, all have shorthand assignment operators.
Here is an example:
int x = 1; // binary: 0000000000000001
x <<= 3; // binary: 0000000000001000
x |= 3; // binary: 0000000000001011 - because 3 is 11 in binary
x &= 1; // binary: 0000000000000001
x ^= 4; // binary: 0000000000000101 - toggle using binary mask 100
x ^= 4; // binary: 0000000000000001 - toggle with mask 100 again
There is no shorthand assignment operator for the bitwise NOT operator ~; if you want to toggle all the bits
in x, you need to do this:
x = ~x; // toggle all bits in x and store back in x
Bitwise Operators vs Boolean Operators
It is very easy to confuse the bitwise operators in C++ with the boolean operators.

For instance, the bitwise AND operator & is not the same as the boolean AND operator &&, for
the following reason:

They don't calculate numbers the same way. Bitwise & operates independently on each bit in
its operands, whereas && converts both of its operands to a boolean value (true==1 or
false==0), then returns either a single true or false value.

For example, 4 & 2 == 0, because 4 is 100 in binary and 2 is 010 in binary, and none of the bits
are 1 in both integers.

However, 4 && 2 == true, and true numerically is equal to 1. This is because 4 is not 0, and 2 is
not 0, so both are considered as boolean true values.
Neresi setup,
neresi loop?Merhaba Dünya (AVR C Versiyonu)
#define F_CPU 16000000UL // Gecikmenin Doğru Üretilmesi İçin
#include <avr/io.h> // DDRB ve PORTB Tanımlamaları İçin
#include <util/delay.h> // _delay_ms İçin PORTB |= 0x20; veya PORTB |= 0b00100000
int main() deyimi de kullanılabilir mi?
{
DDRB |= (1<<5);//Define digital pin13/PORTB5 as an output so we can blink our led
while(1)//for(;;)//Infinite loop Arduino IDE bu kodu derleyebilir mi?
{
PORTB |= (1<<5);//Turn led on (the led included in the Arduino (digital pin 13))
_delay_ms(1000);//Wait 1 second
Herhangi bir giriş pininin değeri PINX
ile nasıl öğrenilebilir?
PORTB &= ~(1<<5);//Turn led off
_delay_ms(1000);//Wait another second
} PORTB &= 0xDF; PORTB ^= (1<<5);
return 0; deyimi de kullanılabilir mi? deyimi de kullanılabilir mi?
Dijital Giriş ve Dijital Çıkış Örneği (AVR C
Versiyonu)
2 numaralı dijital girişe bağlı bir geçici anahtara basıldığında 13 numaralı dijital
çıkışa bağlı ledi yakan, aksi takdirde söndüren AVR C programını Arduino IDE
üzerinde yazınız, derleyiniz ve çalıştırınız.
Birkaç Hafta Sonrası İçin… #include <Arduino.h>
void setup();//prototip
(Zamanlayıcılardan ve Kesmelerden Sonra) void loop();//prototip
int main()
{
init();
void setup() setup();
{ for(;;)
//Deyimler; {
main.cpp is defined in loop();
} }
void loop() hardware/arduino/avr/cores/arduino return 0;
{ }
//Deyimler; void setup()//tanım
} {
//Deyimler;
}
void loop()//tanım
{
//Deyimler;
}
Arduino kodunuz derleme öncesi bu hale dönüşür.
init()
The init() initializes the timer counter, AD converter and serial communication of ATmega328P.

The init() function is called before any of your code runs. It is defined in wiring.c
(hardware/arduino/avr/cores/arduino/wiring.c) and sets up some of the microcontroller’s
hardware peripherals.

Included among these tasks on the AVR platform is configuring the hardware timers for the
milliseconds tick and PWM functions, initializing the ADC section (analogWrite, analogRead)
and initializing the serial port.

The setup() function is called, and in an endless for loop, the loop() function is continually
called. That’s it, and it’s the same code you’d write in C/C++ for any other microcontroller on
the planet. That’s the magic Arduino setup() and loop().
init()
void init()
{
// this needs to be called before setup() or some functions won't
// work there
sei();//it enables the interruption.

// on the ATmega168, timer 0 is also used for fast hardware pwm


// (using phase-correct PWM would mean that timer 0 overflowed half as often
// resulting in different millis() behavior on the ATmega8 and ATmega168)
sbi(TCCR0A, WGM01);
sbi(TCCR0A, WGM00);

// set timer 0 prescale factor to 64


// this combination is for the standard 168/328/1280/2560
sbi(TCCR0B, CS01);
sbi(TCCR0B, CS00);
init()
// enable timer 0 overflow interrupt
sbi(TIMSK0, TOIE0);

// timers 1 and 2 are used for phase-correct hardware pwm


// this is better for motors as it ensures an even waveform
// note, however, that fast pwm mode can achieve a frequency of up
// 8 MHz (with a 16 MHz clock) at 50% duty cycle

TCCR1B = 0;

// set timer 1 prescale factor to 64


sbi(TCCR1B, CS11);
sbi(TCCR1B, CS10);

// put timer 1 in 8-bit phase correct pwm mode


sbi(TCCR1A, WGM10);
init()
// set timer 2 prescale factor to 64
sbi(TCCR2B, CS22);

// configure timer 2 for phase correct pwm (8-bit)


sbi(TCCR2A, WGM20);

// set a2d prescale factor to 128


// 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range.
// XXX: this will not work properly for other clock speeds, and
// this code should use F_CPU to determine the prescale factor.
sbi(ADCSRA, ADPS2);
sbi(ADCSRA, ADPS1);
sbi(ADCSRA, ADPS0);

// enable a2d conversions


sbi(ADCSRA, ADEN);
init()
// the bootloader connects pins 0 and 1 to the USART; disconnect them
// here so they can be used as normal digital i/o; they will be
// reconnected in Serial.begin()
UCSR0B = 0;
}
…Sözün Özü…

AVR C ve Arduino Karışımı Programlar


Yazarken Dikkatli Olmalısınız!!!

You can provide a custom int main() function to be used in place of the default
which is provided by the Arduino API, however providing your own in the sketch
will override the built in version.

You might also like