ECE 376 - Homework #4
C Programming and LCD Displays. Due Wednesday, February 17th
Please make the subject "ECE 376 HW#4" if submitting homework electronically to [email protected] (or on blackboard)
1) Determine how many clocks the following C code takes to execute
Compile and download the code (modify working code and replace the main loop)
Measure the frequency you see on RC0 (toggles every loop).
- Use an osiclloscope - or -
- Connect a speaker to RC0 with a 200 Ohm resistor and measure the frequency with a cell phone app
like Piano Tuner
- RC1 is 1/2 the frequency of RC0, RC2 is 1/4th, RC3 = 1/8th, etc
The number of clocks it takes to execute each loop is
N =
10,000,0002⋅Hz
1a) Counting mod 64
- note: if using your cell phone to measure the frequency, you might have to try different pins on
PORTC until you get one in the audio range. Each pin is 1/2 the frequency of the previous pin
unsigned char i while(1) { i = (i + 1)% 64; if(i == 0) PORTC += 1; }
RC0 = 4890Hz
N
64=
10,000,000 2⋅4890
= 1022.49
Each loop takes about 16 clocks
N
1=
1022.491b) Counting mod 63
unsigned char i while(1) { i = (i + 1)% 63; if(i == 0) PORTC += 1; }RC0 = 140.6Hz
Each loop now takes about 564 clocks (vs 16). Mod 63 is a lot harder than mod 64.
N
63=
10,000,000 2⋅140.6
= 35, 561.88
N
1=
35,561.88 63
= 564.47
1c) Integer Multiply
unsigned int A, B, C; unsigned char i; : A = 1234; B = 5678; while(1) { i = (i + 1)% 64; if(i == 0) PORTC += 1; C = A*B; } }RC0 = 192.2Hz. Each loop takes about 406 clocks
N
64=
10,000,000 2⋅192.2
= 26, 014.57
N
1=
26.014.57 64
= 406.48
1d) Floating point multiply
float A, B; A = 1.00001; B = 0.02; while(1) { i = (i + 1)% 64; if(i == 0) PORTC += 1; B = B * A; }RC0 = 66.1Hz
Each loop takes about 1182 clocks.
N
64=
10,000,000 2⋅66.1
= 75, 642.97
N
1=
75,642.97 64
= 1181.92
16 clocks are due to the looping and counting mod 64 (part a). The remaining 1166 clocks is due to the
floating point multiply.
$65 Chess Clock
2) Write a C program which turns your PIC into a chess clock with a resolution of 100ms
Display the time for player A and player B on the LCD display to 100ms
RB4: Resets the time to 15.0 seconds for both players (both timers stopped)
RB0: Stop player A's clock, start player B's clock
RB7: Stop player B's clock, start player A's clock
When a player's clock is running, time decrements down to 00.0 and stops at zero.
C Code
// Global Variables
const unsigned char MSG0[20] = "HW4 Chess Clock "; // Subroutine Declarations #include <pic18.h> // Subroutines #include "lcd_portd.c" // Main Routine void main(void) {
unsigned int SEC; unsigned int i;
unsigned int TIME1, TIME2, TURN; TRISA = 0; TRISB = 0xFF; TRISC = 0; TRISD = 0; TRISE = 0; PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; ADCON1 = 0x0F;
SEC = 0;
LCD_Move(0,0); for (i=0; i<20; i++) LCD_Write(MSG0[i]); Wait_ms(100); TIME1 = 500; TIME2 = 500; TURN = 0; while(1) { if(RB0) TURN = 2; if(RB7) TURN = 1; if(TURN == 1) if(TIME1) TIME1 -= 1; if(TURN == 2) if(TIME2) TIME2 -= 1; LCD_Move(1,0); LCD_Out(TIME1, 3, 1); LCD_Move(1,8); LCD_Out(TIME2, 3, 1); Wait_ms(70); } }
3) How many lines of assembler does your code compile into?
Memory Summary:
Program space used 9BEh ( 2494) of 10000h bytes ( 3.8%) Data space used 2Dh ( 45) of F80h bytes ( 1.1%) EEPROM space used 0h ( 0) of 400h bytes ( 0.0%) ID Location space used 0h ( 0) of 8h nibbles ( 0.0%) Configuration bits used 0h ( 0) of 7h words ( 0.0%)
4) Collect data to determine how accurate your program is (one count = 100ms ideally)
Using a hand stopwatch
20.0 seconds on the chess clock was
20.17 seconds on the stopwatch
$65 Banjo - 20 Sided Die - Roulette Wheel - Other
Design an embedded system which uses the LCD display and C programming. Some suggestions are
PIC Banjo. Play notes (G4, C3, G3, B4, D4) when you press buttons RB0..RB4. Display the note
you're playing on the LCD display.
20-Sided Die: Roll a d20 every time you press RB0 with the roll displayed on the LCD display.
When you roll a 20, play 220Hz on RC0 for 1/2 second.
Roulette Wheel: Roll an 8-sided die when you press RB0. Have a light on PORTC shift left
32+N times at a speed of 100ms/step when you press the button. Beep at 220Hz for 1/10 second
each step on RA1. Display the winning number on the LCD display.
Door Lock: Unlock a door (PORTA turns on for 1 second) when you input the correct key: RB0
-RB1 - RB2 - RB3.
Other
PIC Banjo
5) Requirements: Specify the inputs / outputs / how they relate.
Inputs: Buttone RB0 .. RB3
Outputs: RC0
Relationship
Play the following notes when a button is pressed
RB0: C4 (261.63Hz)
RB1: G4 (392.00Hz)
RB2: B3 (246.94Hz)
RB3: D4 (293.66Hz)
Tolerance: +/- 1%
6) C code, flow chart, and resulting number of lines of assembler
To generate a note, the following test code was used
void main(void) { unsigned int i; TRISA = 0; TRISB = 0xFF; TRISC = 0; TRISD = 0; TRISE = 0; ADCON1 = 0x0F; while(1) { if(RB0) { RC0 = !RC0;
for(i=0; i<1000; i++); }
} }
The results was a 312.2Hz square wave.
To output different freuqencies, change the count:
RB0: C4 (261.63Hz)
N =
261.63Hz312.2Hz
1000 = 1193
RB1: G4 (392.00Hz)
N =
392.00Hz312.2Hz
1000 = 796
RB2: B3 (246.94Hz)
N =
246.94Hz312.2Hz
1000 = 1264
RB3: D4 (293.66Hz)
N =
293.66Hz312.2Hz
1000 = 1063
Flow Chart
PORTB = Input Start PORTC = Output no yes Button Pressed? Toggle RC0 Wait N counts// --- Banjo.C ---// Global Variables
unsigned char MSG0[16] = "Electronic Banjo"; unsigned char MSG1[16] = "C4 (261.63Hz) "; unsigned char MSG2[16] = "G4 (392.00Hz) "; unsigned char MSG3[16] = "B3 (246.94Hz) "; unsigned char MSG4[16] = "D4 (293.66Hz) "; // Subroutine Declarations #include <pic18.h> #include "LCD_PortD.c" // Main Routine void main(void) { unsigned int i; TRISA = 0; TRISB = 0xFF; TRISC = 0; TRISD = 0; TRISE = 0; ADCON1 = 0x0F; LCD_Init(); LCD_Move(0,0);
for(i=0; i<16; i++) LCD_Write(MSG0[i]); while(1) {
if(RB0) { // 261.63Hz LCD_Move(1,0);
for(i=0; i<16; i++) LCD_Write(MSG1[i]); while(RB0) {
RC0 = !RC0;
for(i=0; i<1193; i++); }
}
if(RB1) { // 392.00Hz LCD_Move(1,0);
for(i=0; i<16; i++) LCD_Write(MSG2[i]); while(RB1) {
RC0 = !RC0;
for(i=0; i<796; i++); }
}
if(RB2) { // 246.94Hz LCD_Move(1,0);
for(i=0; i<16; i++) LCD_Write(MSG3[i]); while(RB2) {
RC0 = !RC0;
for(i=0; i<1264; i++); }
}
if(RB3) { // 293.66Hz LCD_Move(1,0);
for(i=0; i<16; i++) LCD_Write(MSG4[i]); while(RB3) {
RC0 = !RC0;
for(i=0; i<1063; i++); }
} } }