Applied mechatronics, Lab project Embedded programming, AVR intro Sven Gestegård Robertz Department of Computer Science, Lund University 2014 Microcontrollers I A complete computer system in a single package I I Processor Memory I I I I RAM Flash ROM EEPROM Peripherals I I I I Communication modules Timers / PWM A/D converters General purpose digital I/O Microcontrollers : Introduction Embedded programming, AVR intro 2/34 Microcontrollers I Used in automatically controlled products I I I I I I I engine control systems implantable medical devices office machines appliances toys ... Reduces size, cost and complexity compared to using a separate CPU, memory and peripherals Microcontrollers : Introduction Embedded programming, AVR intro 3/34 Microcontroller families I Microcontrollers come in families I I I I Same (or similar) instruction set different memory configurations different peripherals different packages I Facilitates reuse of code and board designs I Newer versions often pin compatible I Examples: Atmel AVR, Microchip PIC Microcontrollers : Introduction Embedded programming, AVR intro 4/34 AVR ATMega88 Block diagram Block diagram. GND Figure 2-1. VCC 2.1 The Atmel ATmega48/88/168 is a low-power CMOS 8-bit microcontroller based on the AVR enhanced RISC architecture. By executing powerful instructions in a single clock cycle, the ATmega48/88/168 achieves throughputs approaching 1 MIPS per MHz allowing the system designer to optimize power consumption versus processing speed. Watchdog timer Watchdog oscillator I 8 bit RISC CPU I 8k flash ROM Oscillator circuits / clock generation Power supervision POR / BOD & RESET debugWIRE Flash SRAM PROGRAM LOGIC CPU EEPROM I 1k RAM I 512 bytes EEPROM I ≤ 20 MIPS @ 20M Hz I In-system programmable (ISP) AVCC AREF DATABUS GND 8bit T/C 0 16bit T/C 1 A/D conv. 8bit T/C 2 Analog comp. Internal bandgap USART 0 SPI TWI PORT D (8) PORT B (8) PORT C (7) 2 6 RESET XTAL[1..2] PD[0..7] Microcontrollers : Atmel AVR PB[0..7] PC[0..6] ADC[6..7] The AVR core combines a rich instruction set with 32 general purpose working registers. All the Embedded programming, AVR intro 5/34 AVR ATMega88 pin-out I General Purpose digital I/O (GPIO) I Pin change interrupt I Alternative function (peripherals) Microcontrollers : Atmel AVR Embedded programming, AVR intro 6/34 AVR documentation I Data sheets and application notes at http://www.atmel/com/ I I AVR042: Hardware design considerations Articles, guides, forums http://www.avrfreaks.net/ Microcontrollers : Atmel AVR Embedded programming, AVR intro 7/34 A minimal AVR board I Few external components needed I I I Built-in oscillator (no crystal required) Built-in pull-up resistors on I/O pins ISP connector And then it is always useful to add a power LED and a reset button. Microcontrollers : A minimal AVR board Embedded programming, AVR intro 8/34 AVR ISP connectors Microcontrollers : A minimal AVR board Embedded programming, AVR intro 9/34 Microcontroller programming I Tool chain I I I Cross compiler/linker Object file translation Programmer I Interrupt handling I Memory mapped registers Microcontrollers : Microcontroller programming Embedded programming, AVR intro 10/34 AVR studio I Free tool available from Atmel I Integrated assembler I Integrated simulator I gcc plug-in I Supports programming for all AVR devices Microcontrollers : Microcontroller programming Embedded programming, AVR intro 11/34 Task: Build an AVR board I Read data sheets / application notes I Keep it simple I Use the six-pole programming connector Include some status LEDs I I I I Check output current ratings Outputs can sink more current than they can source Include a reset button (or jumper) Microcontrollers : Microcontroller programming Embedded programming, AVR intro 12/34 Boolean and bitwise operators I Boolean operators (evaluate to true or false) ! not && and || or I Bitwise operators (evaluate to a number) ˜ not & and | or ˆ exclusive or (xor) Low-level programming : Logical operators Embedded programming, AVR intro 13/34 Boolean expressions I I evaluate to true or false same syntax as in Java but there is no boolean type in C I I I I instead, any integer (and hence any type) can be used zero is interpreted as false non-zero is interpreted as true Example: infinite loop w h i l e ( 1 ) { // c o r r e s p o n d s t o w h i l e ( t r u e ) i n J a v a printf (" . " ); } Low-level programming : Logical operators Embedded programming, AVR intro 14/34 Bitwise operators? bits??? I A number can be represented in binary (base 2) i.e. ”ones and zeroes” I I each binary digit is called a bit Why is that interesting to us? I In (low-level) programming, an integer variable or regsister is often used to represent a set of “flags” I I I I Small sets of bits can represent small numbers I I Each bit in a variable has a distinct meaning . . . and is either on (1, true, high, set) . . . or off (0, false, low, cleared) I.e., a few small numbers can fit into one variable or register. Often used in combination to attach a set of flags to a number Low-level programming : Logical operators Embedded programming, AVR intro 15/34 Representation of numbers Positional number systems I The decimal system: multiples of 10. (“Base 10”) Example : 150210 = 1 · 103 + 5 · 102 + 0 · 101 + 2 · 100 digits: {0, 1} I base 2: binary I base 16: hexadecimal digits: {0 . . . 9, a . . . f } Low-level programming : Hexadecimal and binary representation Embedded programming, AVR intro 16/34 Convert to hexadecimal from binary Convert 0101 11002 to hex: bits 0 . . . 3 : 11002 = = 0 · 20 + 0 · 21 + 1 · 22 + 1 · 23 = 1210 = c16 bits 4 . . . 7 : 01012 = = 1 · 24 + 0 · 25 + 1 · 26 + 0 · 27 = 16 + 64 = 8010 = 5016 which gives the result (in hex) : 50 + c = 5c (= 9210 ) Observation: I Each hexadecimal digit corresponds to 4 bits I One byte is two 4 bit “nibbles”, i.e., hex digits Low-level programming : Hexadecimal and binary representation Embedded programming, AVR intro 17/34 Hexadecimal to binary Convert 5a (0x5a) to binary: I the value of each nibble can be calculated independently I i.e., you only need to use the values {1, 2, 4, 8} for each hexadecimal digit regardless of how big the number is high nibble: low nibble: 5 a = = 4 + 1 = 01012 8 + 2 = 10102 which gives the result: 5a = 0101 1010 Low-level programming : Hexadecimal and binary representation Embedded programming, AVR intro 18/34 Converting to decimal The hexadecimal number 0x73 (= 3 ∗ 160 + 7 ∗ 161 = 3 + 112 = 115) corresponds to the binary representation 0111 0011 which has the decimal value 1 · 20 + 1 · 21 + 0 · 22 + 0 · 23 + 1 · 24 + 1 · 25 + 1 · 26 + 0 · 27 = 1 · 1 + 1 · 2 + 1 · 16 + 1 · 32 + 1 · 64 = 115 Low-level programming : Hexadecimal and binary representation Embedded programming, AVR intro 19/34 Representation of numbers I Binary (base 2) and hexadecimal (base 16) representations are more convenient than decimal for doing bit operations I In binary, each bit is directly represented I In hex, each digit corresponds to 4 bits (a “nibble”) I Converting to/from decimal is tedious; there is no simple way to find the value(s) of a (set of) bit(s) Low-level programming : Hexadecimal and binary representation Embedded programming, AVR intro 20/34 Constants in C and Java I Binary I I I digits: 0 1 constants in gcc and Java 7 are prefixed by 0b e.g., 0b0001101011110100 Hexadecimal I I digits: 0 1 2 3 4 5 6 7 8 9 a b c d e f constants in C and Java are prefixed by 0x e.g., 0x1af4 Hexadecimal notation is much more readable Low-level programming : Hexadecimal and binary representation Embedded programming, AVR intro 21/34 Bitwise operators I Bitwise operators evaluate to a number I Works on the binary representation of the operand(s) Example: bitwise not I I ˜x - in the binary representation of x, invert each bit u n s i g n e d c h a r x , y ; // 8 b i t s l o n g x = 10; y = ~x ; x = 10 = 0x0a = 0000 1010 y = 1111 0101 = 0xf5 = 245 Low-level programming : Bitwise operators Embedded programming, AVR intro 22/34 Bitwise operators ˜x I x & y I x | y I x ˆ y I not the result is x with each bit inverted and the result has a 1 (one) in each bit position where the bit value of both x and y ==1 (inclusive) or the result has a 1 (one) in each bit position where the bit value of either x or y ==1 exclusive or the result has a 1 (one) in each bit position where the bit value of exactly one of x or y ==1 Low-level programming : Bitwise operators Embedded programming, AVR intro 23/34 Bitwise operators, examples ˜ = 1111 0101 0000 1010 & = 1110 0111 0111 1100 0110 0100 | = 0010 1010 1100 0001 1110 1011 I & is used for bit masking and for clearing bits I | is used for setting bits I ˆ is used for toggling bits Low-level programming : Bitwise operators Embedded programming, AVR intro 24/34 Shift operators I In addition to the bitwise logical operators, C and Java has operators for shifting the bits in a number I x << n shifts x n steps to the left I x >> n shifts x n steps to the right Example: I I I 2 << 2 == 8 (0b0010 << 2 == 0b1000) Shifting can be viewed as multiplication or division by powers of two. Low-level programming : Masking and shifting Embedded programming, AVR intro 25/34 Masking and shifting I I Low level drivers often access hardware registers where a single, or a few, bits control something Example: motor servo control word (16 bits) - - - posref[8] velref[4] enable I Reading and writing posref: u n s i g n e d s h o r t c r ; // t e m p o r a r y f o r r e g i s t e r v a l u e u n s i g n e d c h a r p r ; // t e m p o r a r y f o r p o s R e f v a l u e c r= r e a d _ c t r l _ r e g ( ) ; pr cr pr cr = = = = ( c r >> 5 ) & 0 x f f ; // s h i f t and mask c r & ~(0 x f f << 5 ) ; // c l e a r p o s R e f b i t s pr + 10; c r | ( p r << 5 ) ; // new v a l u e f o r r e g i s t e r write_ctrl_reg ( cr ); Low-level programming : Masking and shifting Embedded programming, AVR intro 26/34 Unsigned integer types unsigned char unsigned short unsigned int I avoids sign extension char x = unsigned short ix short iy 0xff ; char y = 0 x f f ; = x ; // i x = −1 : 0 x f f f f f f f f f f f f f f f f = y ; // i y = 255 : 0 x 0 0 0 0 0 0 0 0 0 0 0 0 0 0 f f I On unsigned types, the shift operators always shift in zeroes. I NB! On signed types, >> preserves the sign bit I Always use unsigned types for bit operations etc. I Or: always use unsigned types as default Low-level programming : More on data types Embedded programming, AVR intro 27/34 Byte order I Data types larger than one byte are often represented (in memory) and sent (on communication channels) as a sequence of bytes I The byte order is different in different architectures/systems The two most common variants I I Little endian: least significant byte first I I Used by, e.g., Intel processors Big endian: most significant byte first I Used by, e.g., Motorola processors, Java, “network byte order” I More on this later I Don’t confuse with bit order on serial lines Low-level programming : More on data types Embedded programming, AVR intro 28/34 Accessing the GPIO pins I Two concepts, three registers: data direction and data registers DDRx The Data Direction Register for port x PORTx The Output Register for port x PINx The Input Register for port x x ∈ {B, C, D} Example #i n c l u d e <a v r / i o . h> main ( ) { DDRB = 0xFF ; PORTB = 0 x55 ; w h i l e ( 1 ) ; // don ’ t e x i t from main ( ) } AVR programming Embedded programming, AVR intro 29/34 Accessing the GPIO pins I Using pin name macros #i n c l u d e <a v r / i o . h> main ( ) { DDRB = ( 1 << PB7 ) | ( 1 << PB2 ) | ( 1 << PB0 ) ; PORTB = ( 1 << PB7 ) | ( 1 << PB2 ) | ( 1 << PB0 ) ; while (1); } AVR programming Embedded programming, AVR intro 30/34 Accessing the GPIO pins I Reading and writing #i n c l u d e <a v r / i o . h> main ( ) { DDRB=0xF0 ; while (1){ u n s i g n e d c h a r tmp = ( PINB & 0 x0F ) ; PORTB = ( tmp << 4 ) ; } } I NB! When a pin is configured as an input, writing to PORTx controls the pull-up resistors on that pin. See data sheet for details. AVR programming Embedded programming, AVR intro 31/34 Use “shadow” registers I Sometimes you need to do more complex operations on a port (or control register) value and still write it atomically. I You cannot write individual bits in a register, the entire register is always overwritten. I Some registers are write-only. To modify their value, a local copy is useful. A common idiom is to use a variable in memory that is used as a “shadow register”. I I I AVR programming all bit operations are done on the shadow variable then the value of the shadow variable is written to the register Embedded programming, AVR intro 32/34 Shadow variable example u n s i g n e d c h a r val_b ; // shadow v a r i a b l e f o r PORTB void setup () { DDRB = 0 x f 0 ; val_b = 0 x05 ) ; // t u r n on two p u l l −ups PORTB = val_b ; } main ( ) { setup ( ) ; while (1){ u n s i g n e d c h a r tmp = ( PINB & 0 x 0 f ) ; val_b = ( val_b & 0 x 0 f ) | ( tmp << 4 ) ; PORTB = val_b ; } } AVR programming Embedded programming, AVR intro 33/34