Blinky, a simple LED blinker
From MARS Wiki
Contents |
Introduction
Blinky is a simple LED blinker circuit to introduce members to fundamentals of microcontrollers and assembly programming, a metaphorical "Hello World" of microcontrollers, if you will.
Blinky makes use of the PIC16F628A microcontroller, manufactured by microchip. Purchasing and sampling information on the 16F628A can be found here.
Before begininng the Blinky Project, the following things are needed:
- 1) 5mm LEDs (1 for most basic application, more for more advanced light sequencers)
- 2) A Breadboard
- 3) 5 Jumper Wires
- 4) A Microcontroller Programmer (The PicKit2 is ideal)
- 5) PIC Microcontroller Development environment (MPLAB IDE)
- 6) A Laptop running Windows
Got all those? Great, let's get started!
Starting a New Project
To set up a new project, follow these steps:
- Open MPLAB IDE.
- From the top bar, select Project -> Project Wizard...
- On the device selection screen, type in PIC16F628A.
- On the language toolsuite page, select Microchip MPASM Toolsuite as the active toolsuite.
- When prompted to create a new project file, create a folder under your local (C:\) drive. Inside of this folder, create blinky.mcp (or something similarly named).
- Click through the rest of the screens, then click finish.
Congratulations, you have created your first PIC Assembly project. To view the workspace, select View -> Project.
Adding Source Files
Now that you have the basic project ready to go, it's time to add some code. You will need to open the folder you created for the project with Windows Explorer, right-click in it, and create a new text document. Immediately rename the text document to something descriptive (we chose blinky.asm). Make sure the file extension is .asm.
Next, add this file to your project. From the View menu, choose Project. In the ensuing window, right-click on Source Files and choose Add File. Navigate to where you created the .asm file and add it to the project.
Writing Code
Now let's write some code! Here's the source code for this project broken down with line-by-line explanation.
This line tells MPASM which processor we will use (p=16f628a) and that we want to use decimal as our default numbering system (r=d). We also need to include a file that tells the assembler program where to find various registers in RAM, which is what the include file does.
list p=16f628a, r=d #include <p16f628a.inc>
Next, we set up a couple variables in memory. The cblock directive is a good way to do this efficiently. This directive assigns sequential memory addresses starting with the value given; here, 20 hex or 32 decimal. An 'endc' ends the memory definition.
cblock 20h counter1, counter2 endc
We want to start our code at the first memory location, which is address 0. Note that RAM, which is where our variables went, is an entirely different kind of memory than the flash program memory. This means that we need to keep track of two different address, one for the executable code in program memory and another for the variables in RAM.
org 0
The first action our code takes is to configure Port B as all outputs. On the PIC, this is accomplished by writing a '0' to each tristate bit on Port B. A simple way to do this without switching memory banks is to load W (the accumulator) with 0, then execute a TRIS instruction.
movlw 0 tris portb
We then load Port B with its initial value of 255, which is the same as saying "just turn all the outputs on."
movlw 255 movwf portb
Our main loop, for no apparent reason, was called 'Fred.' We could have picked any other name we wanted. A more conventional choice would have been the oh-so-clever 'loop.' The loop loads the accumulator W with 255 (all ones, you will recall) and then XORs it with Port B. The XOR, or exclusive OR operation, compares two bits and sets the output to '1' if the two bits were different or to '0' if the two bits were the same. By XORing with '1', we essentially invert all the bits of Port B. After doing so, we call a short delay routine to make the LED blinking perceptible to the human eye.
Fred movlw 255 xorwf portb,f call delay goto Fred
The delay loop is essential to make the LED blinking slow enough to actually see. If we did not include this, the LEDs would blink at approximately 250kHz, or 250,000 times per second. Since the human eye cannot see blinking at rates greater than about 25Hz, or 25 times per second, we clearly need to slow things down. To that end, we wrote a delay routine.
The delay routine is a nested loop that simply wastes a couple hundred thousand clock cycles of CPU time. We first clear the two counters we will use.
delay clrf counter1 clrf counter2
Inside the loop, we decrement (subtract 1 from) the first counter until it reaches zero. When this happens, we decrement the second counter once and then repeat the cycle with the first counter. This goes on and on until the program has essentially counted backward from 65536 to 0.
delayloop decfsz counter1,f goto delayloop decfsz counter2,f goto delayloop return
Finally, we need to end the file so that MPASM knows to stop assembling.
end
The entire file is available here.
A couple more things need to be tweaked before we can download to the chip. First, we need to set our configuration options. These options include such things as what oscillator to use, whether to enable brownout reset, and other such important attributes. To access these, choose Configuration Bits from the Configuration menu. Turn off Low Voltage Programming, disable the Watchdog Timer, enable the Power Up Timer, and select the INTOSC: I/O oscillator. The other settings should be alright with their defaults.
Wiring It Up
Having this code is all well and good, but it's useless without programming the chip. To do so, You need to connect a few jumper wires as follows.
| Signal Name | PIC KIT 2 | PIC16F628A |
|---|---|---|
| \MCLR | 1 | 4 |
| Vdd | 2 | 14 |
| Vss | 3 | 5 |
| PGD | 4 | 13 |
| PGC | 5 | 12 |
Also connect an LED between any Port B pin and ground. Port B makes up pins 6 through 13 of the chip, inclusive. Connect the LED such that its anode is connected to the port pin and its cathode is connected to ground. Don't forget a series current limiting resistor if the LED does not have one built in. If you're not sure if a resistor is included or not, go ahead and add one -- it won't hurt anything.
Your Turn
What if I want to make the LEDs blink twice as fast? What if I want them to not blink all at the same time? What if, instead of blinking, I want to make a binary counter? All these are possible by changing less than two lines of code in the above program. One of the best ways to learn about microcontrollers is to experiment. Learn what does work and what doesn't. Play around with the code. Don't be afraid to break things. Let us know what you come up with.
