Applied mechatronics, Lab project Embedded programming, AVR intro Sven Gestegård Robertz Department of Computer Science, Lund University 2017
Outline 1 Low-level programming Bitwise operators Masking and shifting Data types and representation 2 Microcontrollers Introduction Atmel AVR A minimal AVR board Microcontroller programming 3 AVR programming Accessing GPIO pins 4 More on low-level programming Logical operators Hexadecimal and binary representation Bitwise operators
Outline 1 Low-level programming Bitwise operators Masking and shifting Data types and representation 2 Microcontrollers Introduction Atmel AVR A minimal AVR board Microcontroller programming 3 AVR programming Accessing GPIO pins 4 More on low-level programming Logical operators Hexadecimal and binary representation Bitwise operators Embedded programming, AVR intro 2/26
Boolean and bitwise operators Boolean operators (evaluate to true or false)! not && and or Bitwise operators (evaluate to a number) not & and or ˆ exclusive or (xor) Low-level programming Embedded programming, AVR intro 3/26
Bitwise operators, examples 1111 0101 = 0000 1010 1110 0111 & 0111 1100 = 0110 0100 0010 1010 1100 0001 = 1110 1011 & is used for bit masking and for clearing bits is used for setting bits ˆ is used for toggling bits Low-level programming : Bitwise operators Embedded programming, AVR intro 4/26
Masking and setting bits Example: A register : CTRL_REG A bitmask : FLAGS Named bits : ENABLE_X, ENABLE_Y,... Clear the bits specified by FLAGS and set individual bits. // clear FLAGS using bitmask CTRL_REG = CTRL_REG & ~ FLAGS ; // set individual bits CTRL_REG = CTRL_REG ENABLE_X ENABLE_Y ; Can also be written: CTRL_REG &= ~ FLAGS ; CTRL_REG = ENABLE_X ENABLE_Y ; Low-level programming : Masking and shifting Embedded programming, AVR intro 5/26
Shift operators In addition to the bitwise logical operators, C and Java has operators for shifting the bits in a number x << n shifts x n steps to the left x >> n shifts x n steps to the right Example: 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 6/26
Masking and shifting 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 Reading and writing posref: # define POS_OFF 5 # define POS_MSK 0 xff unsigned short cr;// temporary for register value unsigned char pr; // temporary for posref value cr= read_ctrl_reg (); pr = ( cr >> POS_OFF ) & POS_MSK ; // shift and mask cr &= ~( POS_MSK << POS_OFF ); // clear posref bits pr = pr + 10; cr = ( pr << POS_OFF ); // new value for register write_ctrl_reg ( cr ); Low-level programming : Masking and shifting Embedded programming, AVR intro 7/26
Unsigned integer types unsigned char unsigned short unsigned int avoids sign extension char x = 0 xff ; unsigned char y = 0 xff ; int ix = x; // ix = -1 : 0 xffffffff int iy = y; // iy = 255 : 0 x000000ff On unsigned types, the shift operators always shift in zeroes. NB! On signed types, >> is implementation-defined. Typically preserves the sign bit Always use unsigned types for bit operations etc. Or: always use unsigned types as default Low-level programming : Data types and representation Embedded programming, AVR intro 8/26
Byte order Data types larger than one byte are often represented (in memory) and sent (on communication channels) as a sequence of bytes The byte order is different in different architectures/systems The two most common variants Little endian: least significant byte first Used by, e.g., Intel processors, 8-bit AVR Big endian: most significant byte first Used by, e.g., Motorola processors, Java, network byte order Don t confuse with bit order on serial lines Low-level programming : Data types and representation Embedded programming, AVR intro 9/26
Example: Little endian memory In a byte-addressed memory, byte order must be defined for larger values First byte means lowest address Example: *a = 0x0A0B0C0D; Low-level programming : Data types and representation Embedded programming, AVR intro 10/26
Microcontrollers A complete computer system in a single package Processor Memory RAM Flash ROM EEPROM Peripherals Communication modules Timers / PWM A/D converters General purpose digital I/O Microcontrollers : Introduction Embedded programming, AVR intro 11/26
Microcontroller families Microcontrollers come in families Same (or similar) instruction set different memory configurations different peripherals different packages Facilitates reuse of code and board designs Newer versions often pin compatible Examples: Atmel AVR, Microchip PIC Microcontrollers : Introduction Embedded programming, AVR intro 12/26
AVR ATMega88 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. 2.1 Block diagram Figure 2-1. Block diagram. GND VCC Watchdog timer Watchdog oscillator Power supervision POR / BOD & RESET debugwire PROGRAM LOGIC 8 bit RISC CPU 8k flash ROM Oscillator circuits / clock generation Flash SRAM CPU 1k RAM EEPROM AVCC 512 bytes EEPROM 20 MIPS @ 20MHz In-system programmable (ISP) DATABUS 8bit T/C 0 8bit T/C 2 USART 0 16bit T/C 1 Analog comp. SPI A/D conv. Internal bandgap TWI 6 2 AREF GND PORT D (8) PORT B (8) PORT C (7) RESET XTAL[1..2] PD[0..7] 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 Microcontrollers : Atmel AVR Embedded programming, AVR intro 13/26
AVR ATMega88 pin-out Each pin can be used as either General Purpose digital I/O (GPIO) Pin change interrupt Alternative function (peripherals) Peripherals you need: ISP / SPI (PB3--5) USART (PD01) OCny (i.e., PWM) ADCn Microcontrollers : Atmel AVR Embedded programming, AVR intro 14/26
AVR documentation Data sheets and application notes at http://www.atmel/com/ AVR042: Hardware design considerations Articles, guides, forums http://www.avrfreaks.net/ Microcontrollers : Atmel AVR Embedded programming, AVR intro 15/26
A minimal AVR board Few external components needed Built-in oscillator (no crystal required) Built-in pull-up resistors on I/O pins Power supply Reset signal ISP connector it is always useful to add a power LED and a reset button. Microcontrollers : A minimal AVR board Embedded programming, AVR intro 16/26
AVR ISP connectors Microcontrollers : A minimal AVR board Embedded programming, AVR intro 17/26
Microcontroller programming Tool chain Cross compiler/linker Object file translation Programmer Interrupt handling Memory mapped registers Microcontrollers : Microcontroller programming Embedded programming, AVR intro 18/26
AVR studio Free tool available from Atmel Integrated assembler Integrated simulator gcc plug-in Supports programming for all AVR devices Microcontrollers : Microcontroller programming Embedded programming, AVR intro 19/26
Task: Build an AVR board Read data sheets / application notes Keep it simple Use the six-pole programming connector Include some status LEDs 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 20/26
Accessing the GPIO pins Two concepts, three registers: data direction and data registers Example # include <avr / io.h> 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} main () { DDRB = 0 xff ; // set all pins as outputs PORTB = 0 x55 ; // write 0101 0101 to pins while (1); // don t exit from main () } AVR programming : Accessing GPIO pins Embedded programming, AVR intro 21/26
Accessing the GPIO pins Using pin name macros # include <avr / io.h> main () { DDRB = ( 1 << PB7 ) (1 << PB2 ) (1 << PB0 ); PORTB = ( 1 << PB7 ) (1 << PB2 ) (1 << PB0 ); while (1); } AVR programming : Accessing GPIO pins Embedded programming, AVR intro 22/26
Accessing the GPIO pins Reading and writing # include <avr / io.h> main () /* A 4- bit buffer example */ { DDRB =0 xf0 ; while (1){ unsigned char tmp = ( PINB & 0x0F ); PORTB = ( tmp << 4); } } 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 : Accessing GPIO pins Embedded programming, AVR intro 23/26
Use shadow registers Sometimes you need to do more complex operations on a port (or control register) value and still write it atomically. You cannot write individual bits in a register, the entire register is always overwritten. 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. all bit operations are done on the shadow variable changes can be made in multiple steps inconsistent temporary values are not written to the register then the value of the shadow variable is written to the register AVR programming : Accessing GPIO pins Embedded programming, AVR intro 24/26
Shadow variable example unsigned char val_b ; // shadow variable for PORTB void setup () { DDRB = 0 xf0 ; val_b = 0x05 ); // turn on two pull - ups PORTB = val_b ; } main () { setup (); while (1){ unsigned char tmp = ( PINB & 0x0f ); val_b = ( val_b & 0 x0f ) ( tmp << 4); PORTB = val_b ; } } AVR programming : Accessing GPIO pins Embedded programming, AVR intro 25/26
Suggested excercise if you haven t already, include a few LEDs on your AVR board connect a button to one of the GPIO pins write a small program that changes the pattern on the LEDs when the button is pressed, e.g. counting up/down shifting left/right... AVR programming : Accessing GPIO pins Embedded programming, AVR intro 26/26
Boolean and bitwise operators Boolean operators (evaluate to true or false)! not && and or Bitwise operators (evaluate to a number) not & and or ˆ exclusive or (xor) More on low-level programming : Logical operators Embedded programming, AVR intro 27/26
Boolean expressions evaluate to true or false same syntax as in Java but there is no boolean type in C instead, any integer (and hence any type) can be used zero is interpreted as false non-zero is interpreted as true Example: infinite loop while (1) { // corresponds to while ( true ) in Java printf ("."); } More on low-level programming : Logical operators Embedded programming, AVR intro 28/26
Bitwise operators? bits??? A number can be represented in binary (base 2) i.e. ones and zeroes each binary digit is called a bit Why is that interesting to us? In (low-level) programming, an integer variable or regsister is often used to represent a set of flags Each bit in a variable has a distinct meaning... and is either on (1, true, high, set)... or off (0, false, low, cleared) Small sets of bits can represent small numbers 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 More on low-level programming : Logical operators Embedded programming, AVR intro 29/26
Representation of numbers Positional number systems The decimal system: multiples of 10. ( Base 10 ) Example : 1502 10 = 1 10 3 + 5 10 2 + 0 10 1 + 2 10 0 base 2: binary digits: {0, 1} base 16: hexadecimal digits: {0... 9, a... f} More on low-level programming : Hexadecimal and binary representation Embedded programming, AVR intro 30/26
Convert to hexadecimal from binary Convert 0101 1100 2 to hex: bits 0... 3 : 1100 2 = 0 2 0 + 0 2 1 + 1 2 2 + 1 2 3 = = 12 10 = c 16 bits 4... 7 : 0101 2 = 1 2 4 + 0 2 5 + 1 2 6 + 0 2 7 = = 16 + 64 = 5 16 = 50 16 which gives the result (in hex) : 50 + c = 5c (= 92 10 ) Observation: Each hexadecimal digit corresponds to 4 bits One byte is two 4 bit nibbles, i.e., hex digits More on low-level programming : Hexadecimal and binary representation Embedded programming, AVR intro 31/26
Hexadecimal to binary Convert 5a (0x5a) to binary: the value of each nibble can be calculated independently 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: 5 = 4 + 1 = 0101 2 low nibble: a = 8 + 2 = 1010 2 which gives the result: 5a = 0101 1010 More on low-level programming : Hexadecimal and binary representation Embedded programming, AVR intro 32/26
Converting to decimal The hexadecimal number 0x73 (= 3 16 0 + 7 16 1 = 3 + 112 = 115) corresponds to the binary representation 0111 0011 which has the decimal value 1 2 0 + 1 2 1 + 0 2 2 + 0 2 3 + 1 2 4 + 1 2 5 + 1 2 6 + 0 2 7 = 1 1 + 1 2 + 1 16 + 1 32 + 1 64 = 115 More on low-level programming : Hexadecimal and binary representation Embedded programming, AVR intro 33/26
Representation of numbers Binary (base 2) and hexadecimal (base 16) representations are more convenient than decimal for doing bit operations In binary, each bit is directly represented In hex, each digit corresponds to 4 bits (a nibble ) Converting to/from decimal is tedious; there is no simple way to find the value(s) of a (set of) bit(s) More on low-level programming : Hexadecimal and binary representation Embedded programming, AVR intro 34/26
Constants in C and Java Binary digits: 0 1 constants in gcc and Java 7 are prefixed by 0b e.g., 0b0001101011110100 Hexadecimal 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 More on low-level programming : Hexadecimal and binary representation Embedded programming, AVR intro 35/26
Bitwise operators x - not x & y - and the result is x with each bit inverted the result has a 1 (one) in each bit position where the bit value of both x and y ==1 x y - (inclusive) or the result has a 1 (one) in each bit position where the bit value of either x or y ==1 x ˆ y - exclusive or the result has a 1 (one) in each bit position where the bit value of exactly one of x or y ==1 More on low-level programming : Bitwise operators Embedded programming, AVR intro 36/26
Bitwise operators Bitwise operators evaluate to a number Works on the binary representation of the operand(s) Example: bitwise not x - in the binary representation of x, invert each bit unsigned char x,y; // 8 bits long x = 10; y = ~x; x = 10 = 0x0a = 0000 1010 y = 1111 0101 = 0xf5 = 245 More on low-level programming : Bitwise operators Embedded programming, AVR intro 37/26