Lab 9: Async IO and I2C

This lab has you explore Asynchronous serial I/O and I2C operation.

Prelab (20)

2. 42 us

2. one bit time: 42 us

Using the baud rate that you commonly use for your PIC24 breadboard and BullyCPP connection, compute the following values concerning asynchronous I/O:

Prelab Checkoff

Pins 7 and 8 are not connected to anything (0) 

Wires looping off board, untrimmed resistors, or jumper wires (anywhere on board). (0)

You connected pins 1-4 like the below picture, but your student ID doesn't end in 0 or 8. (0)

Example of wiring that will earn prelab credit. (This is for a digit of 8 or 0 -your connections may differ.)

Task 1 - Overflow without ISR (10)

Open the MPLAB X project lab9/uart_test project, compile it, and program your PIC24 with it. This program measures the PIC24 UART overflow time by having the user input a character string, followed by a loop that only reads the first character and ignores the rest of them. The PIC24 timer3 is started after the first character is read, and the loop is exited if either UART1 overflows or the timer overflows (the timer overflow period is much greater than the UART overflow time). Recall that the UART1 overflows when its internal buffer is full (5 characters) and the 6th character is fully received.

Test the program by typing the number "1" into the BullyCPP window. You should get a message saying that "UART overflow did not occur". Next, copy (Ctrl-C) and paste (Ctrl-V) progressively larger strings into the BullyCPP window ("12", "123", etc) until you find the first one that overflows. Call this the "overflow string". Take a screenshot of BullyCPP showing the overflow.

(If you cannot trigger an overflow because BullyCPP reads the Ctrl key as a separate keypress, you will need to download an older version of BullyCPP from the Github page. See Lab 0 for link.)

When the UART overflows, a timer tick value is printed out corresponds to the number of timer ticks after the arrival of the first character (which is read by the program) and UART overflow. Test the program with a few times with your overflow string and take an average of the last three timer tick values you see. The program also uses a GPIO pin to measure UART overflow time by setting RB14 high after receipt of the first character, and then back low when UART overflow occurs.

TA Checkoff

You have taken a VirtualBench screenshot showing your overflow string. Should show UART RX and RB14, and measure from where RB14 goes high to where overflow occurs.

Task 2 - Overflow with ISR (10)

This task assumes that you have the VirtualBench connections from Task #1 still connected. Open the lab9/uart_test_interrupt project. This project is the same as uart_test except that it has the compiler flag -DUART1_RX_INTERRUPT defined during compilation, which enables interrupt-driven UART code in the my_pic24_uart.c file (the screenshot below shows how this compile flag is turned on in the project; to reach this, right-click on uart_test_interrupt in the Project panel and select Properties from the pop-up menu). Interrupt-driven I/O uses a software FIFO to store incoming UART receive bytes in order to give a larger number of characters before receive overflow.

1. Open the file my_pic24_uart.c file and find the UART1_RX_FIFO_SIZE #define statement; note that this size is set to 32.

2. Find the UART1 RX interrupt service routine (_U1RXInterrupt) in the my_pic24_uart.c file, and add the line _LATB2 = ~_LATB2; as the first line in this function. This toggles the RB2 pin each time the interrupt is called and a serial character is stored in the software buffer.

3. Compile the program, and download it to your PIC24. Send your overflow string found for Task 1, and you will find that the UART software buffer does not overflow. Keep sending successively larger strings until you find the first one that causes overflow (you will get a software reset, and a report of 'UART1 RX Interrupt FIFO overrun' in BullyCPP). Capture a screenshot of the overflow in BullyCPP and include it in your report.

4. Open the VirtualBench software, and configure it the same way as for task 1 (double check your settings since zoom in/out will change them). Connect one more wire - locate the wire D2 on the logic analyzer connector and plug this wire into the RB2 pin of your PIC24. Label this RB2 in the VirtualBench logic analyzer setup.

5. Configure the VirtualBench for single shot trigger, falling edge and send the same string you found in step 3 that caused overflow. Zoom out on the VirtualBench display until you see all of the characters that were sent, and verify that the RB2 trace toggled for each character that was received. Take a screenshot.

TA Checkoff

You have taken a VirtualBench screenshot showing your overflow string using software FIFO. Should show UART RX, RB14, and RB2. You don't need to measure anything.

Task 3 -- EEPROM (40)

1. Open the MPLAB project lab9/i2c_eeprom. Edit the i2c_eeprom.c file, and change the #define EEPROM 0xA0 statement to the following:

#define READ 0x??

#define WRITE 0x??

These macros define the control byte to send to your EEPROM. The ?? should be replaced by two hexadecimal characters as follows:

Control byte is between the dark lines. Control Code 1010 is for the 24XX512. From Microchip DS20001754Q

Change the line in readOneByteCurrentAddress that says putI2C1(EEPROM | 0x01); to putI2C1(READ);

Compile the program, and then program your PIC24 with the hex file. When run, this program displays three menu options. Option 1 reads a byte from the current address location in the EEPROM, option 2 reads a byte from a specific address, and option 3 writes a byte to a specific address and reads that byte back to verify that the write operation was performed correctly. Take a screenshot of BullyCPP showing option 1 being performed. Option 1 has been implemented for you, while options 2 and 3 need to be completed for this task. 

2. Menu option #2 calls a function named uint8 readOneByteSpecificAddress(uint16 u16_address) that reads one byte from location u16_address and returns it. This function is currently empty. Write a series of I2C function calls that implements this functionality. Use the primitive functions listed below (all of them may not be needed):

void startI2C1(void);

void rstartI2C1(void);

void stopI2C1(void);

void putI2C1(uint8_t u8_val);

uint8_t getI2C1(uint8_t u8_ack2Send);

Test your implementation with the address of the last four digits of your student ID number and take a screenshot of BullyCPP.

Hints

To extract the most significant byte of a 16-bit number into an 8-bit variable, you can do:

u8_msb = (u16_r >> 8) & 0xFF;

To extract the least significant byte of a 16-bit number into an 8-bit variable, you can do:

u8_lsb = (u16_r & 0xFF);

3. Menu option #3 calls a function named void writeOneByteSpecificAddress(uint16 u16_address, uint8 u8_byte); that writes the u8_byte byte value to location u16_address. This function is currently empty. Based on the EEPROM datasheet and the lecture notes, write a series of I2C function calls that implement this functionality. Use the primitive functions listed below (all of them may not be needed):

void startI2C1(void);

void rstartI2C1(void);

void stopI2C1(void);

void putI2C1(uint8_t u8_val);

uint8_t getI2C1(uint8_t u8_ack2Send);

Test your implementation with the address of the last four digits of your student ID number. Write the ASCII code of the first (capital) letter of your name. Take a screenshot of BullyCPP.

4. Remove the RB14, RB2, and UART RX wires, and clear them from the VirtualBench setup. Connect the red VirtualBench wire D3 to the SCL pin on the LC512 EEPROM. Label this SCLK in the VirtualBench setup.

5. Connect the red VirtualBench wire D4 to the SDA pin on the LC512 EEPROM. Label this SDA in the VirtualBench setup. Add an I2C interpreter using these two pins to the VirtualBench logic analyzer setup, as shown in the image below:

6. Set up the VirtualBench software for single shot execution, with trigger on the falling edge of the SDA trace. Set the starting period to 10 us. Start the VirtualBench running -- it should wait for a trigger on the SDA trace. Execute menu option 1 within BullyCPP for the i2c_eeprom program, readOneByteCurrentAddress. You should get a string back indicating that some byte was read from your EEPROM (we don't care what the byte value is). If you get a Watchdog timer timeout with an I2C error message, this means that either your #define READ address is incorrect, or your EEPROM is wired incorrectly (SDA/SCLK lines reversed, no pullup resistors on I2C lines, etc), or both! To debug this, look at the I2C trace that was captured in the VirtualBench software, and see if the correct first byte is being sent to the EEPROM. Take a VirtualBench screenshot.

7. Take a VirtualBench screenshot of readOneByteSpecificAddress in action.

8.  Take a VirtualBench screenshot of writeOneByteSpecificAddress in action.

TA Checkoff:

A read of the address of the last 4 digits of your student ID number produces the first letter of your name. You have taken VirtualBench screenshots showing your I2C transactions. Each should show SCLK, SDA, and BUS1.

Report

Grading

If you do not successfully complete a task and your report fails to mention or glosses over this fact, you will receive a zero for the report portion of your grade as well as for the task. If you attempt to deceive the grader, e.g. by including screenshots not generated by the code you submitted, your instructor will be notified and you will be recommended for an Honor Code violation.

The report is worth 20 points for neatly and coherently presenting your information to a reader. The following non-exhaustive list of errors will result in losing credit from the report portion of the lab grade:

The tasks are worth 60 points. If your report indicates that you did not successfully complete or do not understand a task, you will lose credit, even if you performed it during the lab. The same is true for tasks performed during the prelab. There are three tasks. The first task is worth 10 points. The second task is worth 10 points.  The third task is worth 40 points. (Task 3a is worth 10, and 3b and 3c are each worth 15 points.) The following non-exhaustive list of errors will result in losing credit from a task:

Lab reports that flagrantly violate submission policy (wrong lab, no screenshots, no title page, no text besides headings/labels, mostly blank, code pasted into pdf, paragraphs of lab text pasted in, extremely sloppy/unprofessional, missing code etc.) will not be accepted. The student will receive a zero for the lab and may resubmit with late penalty.