EEE305 Microcontroller Systems Lecture 5: Embedded C using PIC microcontrollers Simple I/O and XC8 (last changed 23/3/13) Teaching resources are at www.eej.ulst.ac.uk My office 5B18, telephone 028 90 366364 My email IJ.McCrum@ulster.ac.uk http://www.eej.ulst.ac.uk/~ian/modules/EEE305 1/ Microchip Inc • Ranked number 4 (after Renesas, Freescale and Atmel) • Atmel make the chips that are in arduino boards. • Microchip make nearly 3000 different types of MCU • Make microcontrollers/MCUs in 5 families (as well as serial memory and analogue products, sensors etc.,) • Families include 10F,12F,16F,18F and then the 24F,30F and 33F as well as the 32F parts. • We will use the 16F877A • This is available to us in a 40 pin DIP package. • Its datasheet is 234 pages long, and worth reading – we will select relevant chapters. http://www.eej.ulst.ac.uk/~ian/modules/EEE305 3 Start up MPLAB X It is very important you use the “projects”way of working - Create a new project -> Microchip Embedded ->standalone Project - Select Device -> Mid Range… ->PIC16F877A (but check your board) - Hardware tools ->Pickit 2 or 3 (the 2 is black, the 3 is red) - Select Compiler – XC8 - Give the project a name and make a new folder. One folder per program! - To get started; under the project window on the top left hand side - Right click on sources and select a NEW – C Main File, name it sensibly .c (we will try and stick to single file C programs) You need to include the special header file <xc.h> - it loads PIC16F877A.h MPLAB infers this from the project file. It is better to use XC.h as it is more portable. You need to #define _XTAL_FREQ 4000000 // or whatever you board has You need to find and load up the datasheet for the PIC16F877A and possibly look at The device specific header file PIC16F877A, this allows you to use predefined names Such as PORTB and TRISB http://www.eej.ulst.ac.uk/~ian/modules/EEE305 4 I/O pins; PORTS A-E Similar but different http://www.eej.ulst.ac.uk/~ian/modules/EEE305 5 Accessing special function registers (SFRs) in XC8 The Special Function Registers (SFRs) are registers which control aspects of the MCU operation or that of peripheral modules on the device. Memory-mapped SFRs are accessed by special C variables that are placed at the address of the register. (Variables that are placed at specific addresses are called absolute variables). These variables can be accessed like any ordinary C variable so that no special syntax is required to access SFRs. The names of the structures that hold the bit-fields will typically be those of the corresponding register followed by bits. For example, the following shows code that includes the generic header file, clears PORTA as a whole, sets bit 0 of PORTA using a bit variable and sets bit 2 of PORTA using the structure/bit-field definitions. #include <xc.h> void main(void) { PORTA = 0x00; // how we access alll 8 bits RA0 = 1; // how we could access one bit PORTAbits.RA2 = 1; // an alternative way of accessing a bit } http://www.eej.ulst.ac.uk/~ian/modules/EEE305 6 Internally we need to configure the PIC This used to use the __CONFIG macro but the modern way is to use #pragma keyword To get the PIC to work correctly we must plant a pattern of ‘1’s and ‘0’s in a special register on powerup. This is the CONFIG register (there can be more than one of these depending on the PIC) Examine chapter 14 of the datasheet; http://www.eej.ulst.ac.uk/~ian/modules/EEE305 7 The XC8 compiler documents in the folder C:/Program Files (x86)/Microchip/xc8/v1.11/docs/pic_chipinfo.html #pragma config CP=OFF, DEBUG=OFF, PWRTE=OFF http://www.eej.ulst.ac.uk/~ian/modules/EEE305 8 #pragma config CPD=OFF, LVP=OFF #pragma config BOREN=OFF #pragma config WRT=OFF #pragma config WDTE=OFF #pragma config FOSC=HS http://www.eej.ulst.ac.uk/~ian/modules/EEE305 9 Important CONFIG fuses; Oscillator Type and Watchdog disable The config fuse setting for the oscillator affects the bias current applied to the oscillator circuitry within the PIC http://www.eej.ulst.ac.uk/~ian/modules/EEE305 10 Important CONFIG fuses; Watchdog A watchdog circuit forces reset active unless activated every so often, e.g every 20 seconds. Some systems are unsafe if a microprocessor “hangs” so it may be better to force a reset if a hardware failure occurs. The designer should ensure that the system is safe in the reset state – relays, motors, heaters, solenoids all in a safe state. Watchdogs should only be added near the end of the system design, when a complete study of failure mechanisms is undertaken. It also confuses things if the PIC could reset at any time. You have to add code to every loop to reset the watchdog counter, it must be sent to zero before it reaches its trigger level. Hence it is best to disable it. http://www.eej.ulst.ac.uk/~ian/modules/EEE305 11 http://www.eej.ulst.ac.uk/~ian/modules/EEE305 12 http://www.eej.ulst.ac.uk/~ian/modules/EEE305 13 PORTB: typical input or output port (like A,C,D and E though A is 6 bits and E 3bits) The top 4 bits of PORT B are special in that they have extra circuitry to cause and “interrupt on change” – we can use that to wake up the MCU from low power sleep mode or use it for high priority inputs; In addition RB6 and RB7 should NOT be used by the user – they are used by the PICKIT programmer. http://www.eej.ulst.ac.uk/~ian/modules/EEE305 14 http://www.eej.ulst.ac.uk/~ian/modules/EEE305 15 Electrical details: chapter 17 of datasheet http://www.eej.ulst.ac.uk/~ian/modules/EEE305 16 http://www.eej.ulst.ac.uk/~ian/modules/EEE305 17 http://www.eej.ulst.ac.uk/~ian/modules/EEE305 18 http://www.eej.ulst.ac.uk/~ian/modules/EEE305 19 Simple output: LEDs Look up a datasheet from farnell.co.uk ->products->Optoelectronics->LEDs Standard Farnell have 4062 different LEDS! Select green (545) Show All and click on price ascending (the orange triangle) The first non surface mount device is FEC 1652494 http://www.eej.ulst.ac.uk/~ian/modules/EEE305 20 An output pin driving an LED When the output is low it is maybe at 0.6V, the LED will require 2.1Volts across it and a current of 20,A to light. Hence the resistor must drop 5-2.1-0.6 = 2.3 volts across it, which if it is carrying 20mA means its value is V/I = 2.3/20 kOhms = 0.115 or Roughly 120 Ohms, What value should it be for 10mA to flow (still a reasonably bright LED) http://www.eej.ulst.ac.uk/~ian/modules/EEE305 21 Multiple LEDs Bar Graphs 7 seg displays – either Alphanumeric – smart – serial in, serial out Starburst displays (14 segment) 5x7 Dot Matrix - common cathode common anodes also available or 8x8 http://www.eej.ulst.ac.uk/~ian/modules/EEE305 22 An output pin driving a Relay Some 12 Volt relay might have a coil resistance of 300 Ohms. This means 40mA. We could parallel port pins, but it is easy to use a transistor to carry the higher current. Cheaper relays need more current. The power dissipated in the transistor is Vcesat * 40mA – quite low. If the Beta of the transistor is 40 then 1ma will flow, the pin output is maybe 4 volt, and the Base emitter is at 0.6v so R should drop 3.4 volts at 1ma = 3k3 Look at farnell.co.uk and search for farnell parts FEC1455510 and FEC1094428 read the datasheets. http://www.eej.ulst.ac.uk/~ian/modules/EEE305 23 Typical Relays: (Use www.farnell.co.uk, ww.maplin.co.uk or RS) E.G Enter relays into the search box on the Farnell website, (7,014 products) Pick Power-General purpose or Automotive as a category. http://www.eej.ulst.ac.uk/~ian/modules/EEE305 24 Note ticked blue triangle and PDF icons below part photo http://www.eej.ulst.ac.uk/~ian/modules/EEE305 25 Driving multiple outputs – many relays or 7 segment displays http://www.eej.ulst.ac.uk/~ian/modules/EEE305 26 Multiplexed output One output to feed 1 Led or Relay is easy. You may run out of pins! You can either add extra devices or sometimes multiplex the outputs. Multiplex means to make a pin do two different things From http://embedded-lab.com/blog/?p=2086 on 26/3/13 http://www.eej.ulst.ac.uk/~ian/modules/EEE305 27 Be careful, use NPN transistors if common cathode displays. From http://www.electronicsblog.net/4-digits-7-segments-led-display-multiplexing-with-arduino/ on 26/3/13 http://www.eej.ulst.ac.uk/~ian/modules/EEE305 28 Problems with multiplexing displays Humans have persistence of vision, but only up to a point. Peak currents need to be high to avoid splitting the perceived brightness Processor has little time to do other things. It needs to “update” the display (move to next digit) every 20 milliseconds) We can use hardware timers and interrupts to help with this but it complicates code. There are special interface chips – display drivers that will do the multiplexing for us. E.g using the SPI or IIC (I2C or I2C) interfaces – these save lots of pins! (c.f later) Or we can use ways of increasing the number of i/o pins and effectively avoid multiplexing. Still makes PCB and wiring a nuisance though… http://www.eej.ulst.ac.uk/~ian/modules/EEE305 29 Expanding I/O There are specialist chips to do this – using SPI or IIC, you can even send a RS232 message to a second or third PIC to achieve the same overall effect. – master-slave PICs But we can use simple 8 bit latches or shift registers (c.f EEE324!) e.g Look at the datasheets for a 74AC573 (£0.22). Also a ‘595 , ‘165 and ‘164 (any prefix) http://www.eej.ulst.ac.uk/~ian/modules/EEE305 30 Using 11 lines to give 24 outputs From http://www.dtvt-ictu.info/t1058-topic on 26/3/13 http://www.eej.ulst.ac.uk/~ian/modules/EEE305 31 Shift registers – output using 74HC595 http://www.eej.ulst.ac.uk/~ian/modules/EEE305 32 Example- 4 digit 7-segment display using 74595 shift registers From http://www.reflow-kit.com/download/rk/RK-10122_104.pdf on 26/3/13 http://www.eej.ulst.ac.uk/~ian/modules/EEE305 33 Shift registers – input using 74HC165 (£0.31) http://www.eej.ulst.ac.uk/~ian/modules/EEE305 34 Datasheet Software should keep CE low, put PL low then high and read Q7, bring clock (CP) high then low, read Q7 and repeat. As each bit is read it should be shifted into a byte you receive the most significant bit first. After 8 shifts the 8 inputs are in the 8 bit variable (an unsigned char in C) From http://www.ti.com/lit/ds/symlink/cd74hc165.pdf on 26/3/13 http://www.eej.ulst.ac.uk/~ian/modules/EEE305 35 Reading 8 inputs using 3 lines from a micro 1. pulse LOAD low then high to load parallel inputs. 2. read Q7’ (pin 7) and store data bit. (you can also use Pin 9 instead) 3. pulse CP high then low to shift next data bit out. 4. go back to Step 2 and repeat until 8 bits are read This works with any simple digital i/o lines. You can also use the built in USART peripheral in a PIC is synchronous mode – when it outputs its clock. With a 74HC165 and 74HC164 you can do 8 bit i/o over 2 lines. (c.f book by Han-Way Huang/ “Pic Microcontroller: An Introduction to Software and Hardware interfacing” ) From http://forums.parallax.com/showthread.php/115628-74hc164-Schematic-amp-Sample-Code on 26/3/13 http://www.eej.ulst.ac.uk/~ian/modules/EEE305 36 Using digital inputs If you need to read the logic state of a chip and it has the same power supply as the PIC then you just read a ‘1’ or a ‘0’. The PIC will require very little current and has voltage thresholds given in the datasheet. Chips that use 3.3V are becoming common, this can just about drive a PIC input to a readable value – if the current from the 3.3V output only drives the PIC input. You can add a buffer chip to ensure this, or you can add a 3.3 to 5 volt translator chip. If you choose to run the PIC itself from 3.3V then you need to ensure you do not damage the PIC, check if you have 5V tolerant pins (some are some aren’t), use translator chips, use a potential divider (this wastes current) You can use a transistor or mosfet. This is the reverse of the open collector circuit you used to drive a 12 volt relay, in this case use a pullup to VDD of the PIC. You can use opto-isolators (opto-couplers) to avoid electric shock or to deal with voltages that might damage the PIC or are too low or where the “earth” or zero volts of two circuits are not common. http://www.eej.ulst.ac.uk/~ian/modules/EEE305 37 Optocoupler (£0.42p from Farnell) The LED should have nearly 10mA through it to illuminate the phototransistor sufficiently; Datasheet states Vf is 1.5V max so if the driving voltage is 4.5 Volts we need 330 Ohms. Use the next bigger in case the 330 is 5% too low. The current transfer ratio tells us that we can draw up to 10mA from the collector , 10k is ok as a pull up. – we will draw 0.5mA when switched on. Note these can be slow devices. From http://www.analog.com/library/analogDialogue/Anniversary/20.html on 26/3/13 http://www.eej.ulst.ac.uk/~ian/modules/EEE305 38 Multiplexing inputs Ironically we use outputs to read inputs. If the output port outputs the patterns {1110, 1101, 1011, 0111} repetitively and checks on the input port that the 4 inputs are all still 1111 then no key has been hit Read in 1 1 0 1 Having Output 1 1 1 0 i.e We know COL1 was active when ROW3 went low – tells us which switch is depressed If a low is read then this gives us a ROW where a key has been hit. Since the software knows which COLUMN is has outputted low then the combination of the ROW and COLUMN tells us which key has been hit. We need to scan reasonably quickly and this puts restraints on what else the software can do. There are also special key encoder chips that you can add – extra facilities such as debounce http://www.eej.ulst.ac.uk/~ian/modules/EEE305 39 Lab exercise HW1 1. Examine the circuit diagram of the millenium board and the board itself to look at ports, LEDs D1-D3 and pushbuttons Sw1-3 2. Wire up an LED to RB0 and get it flashing twice a second 3. Read (and use) the code on OHP 15 4. Wire up a pushbutton switch to RD0 and read it, if it is ‘1’ light the LED, else do not light the LED (and repeat for ever) 5. Wire up three LEDs and three pushbutton switches, create an infinite loop that lights each LED if the corresponding switch http://www.eej.ulst.ac.uk/~ian/modules/EEE305 is depressed 40