Lab: Blinking Lights

Wednesday, Oct 4, 2017
Monday, Oct 9, 2017 (by 5pm)
Work with your assigned partner for this lab. You may use your classmates as a resource, but please cite them. Sharing of complete or nearly-complete answers is not permitted. If you do not know whether it is acceptable use a specific resource you should ask.


In this lab, you will use the protoboard’s switches to blink LEDs in two or more different patterns. Along the way, you will write assembly code to call functions, read input, isolate bit fields, and perform conditional execution.


  • An, Reilly, and Matt
  • Aditi and Nick
  • Paps and Nripesh
  • Hoang and Andrew
  • John and Ryan
  • Clara and Prabir
  • Rojina and Faizaan
  • Lex and Jimin
  • Dennis and Greyson
  • Zachary and Bazil



Before starting the lab, study the following assembly procedure and be able to explain how it works.

  beq $a0, $zero, delayloopend
  addi $a0, $a0, -1
  j delayloop
  jr $ra

Questions to ask yourself:

  • What does the procedure do?
  • How many arguments does this procedure take? What is their use?
  • Is there a return value from this procedure? If so, what is it? If not, why not?
  • This procedure doesn’t need to use the stack. Why not?

Part A: Blinking slowly

Our first task is to write a program that will blink the LEDs slowly enough for us to see. Start by launching MPLAB:

$ /home/curtsinger/bin/mplab_ide &

Create a new project named blinky. In that project, create a file named blinky.S (note capitalization) and copy the following code:

  # blinky.S
  # Written by Janet Davis, 13 October 2013

.set noreorder  # Avoid reordering instructions
.text           # Start generating instructions
.globl main     # The label should be globally known
.ent main       # The label marks an entry point

#define ON  0x1
#define OFF 0x0

  beq    $a0, $zero, delayloopend
  addi    $a0, $a0, -1
  j     delayloop
  jr    $ra

  la $s0, TRISA   # Load the address mapped to the TRISA control register
  li $t0, 0    
  sw $t0, 0($s0)  # Store the value 0 to all bits of the TRISA register,
                  # setting all bits of Port A as output
  la $s0, LATA    # Load the address mapped to the LATA control register
  li $t0, ON        
  sw $t0, 0($s0)  # Write to LATA, turning the LED on
  li $t0, OFF    
  sw $t0, 0($s0)  # Write to LATA, turning the LED off
  j loop          # Infinite loop
  nop             # Do nothing
.end main         # Marks the end of the program

This should be similar to a program you wrote in the previous lab. Verify that stepping through the code with the debugger blinks the onboard LED on and off. Where the program says # YOUR CODE HERE #, add instructions to call the given delayloop procedure.

You will need to decide what number to pass as an argument to delayloop. My advice is to blink the LED at a rate of about 1Hz, or once per second - not too fast and not too slow. By default, the PIC32 MX110F016B runs at 4MHz, executing one instruction per cycle. Given this information, the code for the delay loop, and the classic CPU perfomance equation, you should be able to estimate an appropriate number of loop iterations. If you are not sure of your calculation, check with me.

Next, we will use a protoboard switch to control the blink rate of the LED. Our goal: If the switch is off, the LED will continue to blink at a slow rate of 1Hz. If the switch is on, it will blink faster.

Hardware setup

In the PIC32MX1XX/2XX Family Data Sheet, find the pin diagram for the 28-pin SPDIP package on page 4. Focus at the diagram on the top of the page, which is for the PIC32MX1XX product series. Observe that pin 14, which corresponds to RB5, is 5V-tolerant (meaning it can accept a 5V input from the protoboard).

Wire one of the protoboard logic switches to pin 14. Turn the protoboard on.

Assembly code

Before the loop, add code to configure Port B as input (at least the lower 8 bits). Store the address of PORTB in a register.

At the start of the loop, read the value of PORTB into an unused register. Use logic operations to isolate bit 5 of the register value, so that the register contains 1 (true) if the switch is on and 0 (false) if the switch is off. You may find it helpful to use the debugger and its view of CPU register values to make sure you are doing this correctly.

Then, add a conditional to choose between two different delay values: the one you computed before, and one that is somewhat smaller. Pass the chosen value as an argument to the delayloop procedure.

Finally, test your code. Have you met your goal? Show me when you are done with this part!

Part C: More choices

Wire a second protoboard switch to pin 15 (also 5V-tolerant, and wired to RB6). With two input switches, you should be able to choose from four different blink patterns by using more complex conditionals. You are free to choose the four distinct blink patterns. Here are some suggestions:

  • Blink the LEDs at four different speeds.
  • Independently vary the amount of time the LED is on and the amount of time it is off, to create different “rhythms.”
  • Wire up four LEDS to RA0, RA1, RA2, and RA3. Create different combinations of which LEDs are on and which are off. For example, each of the four LEDs could light up in sequence. Or the odd ones could turn on together, then the even ones.

Use your imagination and have fun!


This lab was developed by Janet Davis for CSC 211L in 2013. Parts of the lab were inspired by exercises written by Marge Coahran.

license This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.