You are on page 1of 7

APSC 1299 Test 2

Use of a calculator and your lab notebook is permitted. Pin-out diagram on last page.

1. [10] Show calculations and write a short complete main.c source file to program pin 16
for a continuous PWM on an MCU operating at 8 MHz. The LED should be on 0.2350
ms and off for 0.1720 ms. What are the percent differences between the programmed
period and duty cycle and the required values?

MCU
VDD
16

Look at the circuit. The LED is on when Pin 16 is low and off when Pin 16 is high.
Therefore the PWM signal needs to be on for 0.1720 ms and off for 0.2350 ms.

TPWM = (period + 1) * prescaler * TCY = (0.2350 + 0.1720) ms = 0.4070 ms

TCY = 4/(8 MHz) = 5 × 10-7 s = 5 × 10-4 ms

So (period + 1) * prescaler = (0.4070 ms)/( 5 × 10-4 ms) = 814

Now (period + 1) cannot exceed 256 and prescaler can only be 1, 4, or 16

Using prescaler = 4, period = 814/4 – 1 = 202.5 (we can use either 202 or 203 with the
same precision). %discrepancy = (204*4 - 814)*100%/814 = 0.25%.

Off time TDC = dutycycle * prescaler * ¼TCY = 0.1720 ms

So dutycycle = 0.1720 ms / 4 / ¼(5 × 10-4 ms) = 344 which is exact.

Or using presclaer = 16, period = 814/16 – 1 = 49.9. So period = 50. %discrepancy =


(51*16 - 814)*100%/814 = 0.25%.

So dutycycle = 0.1720 ms / 16 / ¼(5 × 10-4 ms) = 86 which is exact.


#include <p18f4525>
#include <pwm.h>
#include “../Functions/configuration_bits.h”
void main(void)
{
set_osc_8MHz(); //TCY = 4/8MHz = 5 × 10-4 ms
OpenTimer2(TIMER2_INT_OFF & T2_POST_1_1 & T2_PS_1_4);
OpenPWM1(203); // period is 203+1 * 4 * 5 × 10-4 ms = 0.4080 ms
SetDCPWM1(344); //on time is 344 * 4 * ¼(5 × 10-4 ms) = 0.1720 ms.
while(1); //run forever
}
2. [10] A bi-colour LED, shown as two separate LEDs below, is connected to the CCP1 and
CCP2 pins of the MCU. The code snippet sets both pins to send out PWM signals with
different duty cycles. Neatly and accurately sketch three cycles of the PWM signal
(voltage versus time marked in TCY). Have one signal vertically offset against the other.
Assume that the green LED is on the outside and the red LED is closest to the MCU. On
your sketch indicate when the bi-colour LED is off, red, or green.

void main(void)
CCP1 {
set_osc_1MHz();
OpenTimer2(TIMER2_INT_OFF & T2_POST_1_1 & T2_PS_1_1);
OpenPWM1(99);
MCU OpenPWM2(99);
SetDCPWM1(300);
Delay1TCYx(50);
SetDCPWM2(200);
while(1);
CCP2
}

Green on when CCP1 (PWM1 or pin 17) is low and CCP2 (PWM2 or pin 16) high.
Red on when CCP1 (PWM1 or pin 17) is high and CCP2 (PWM2 or pin 16) low.

Period = (99 + 1) * (prescaler = 1) * TCy = 100 TCY


Pin 17 on time TDC1 = 300 * (prescaler = 1) ) * ¼TCy = 75 TCY
Pin 16 on time TDC2 = 200 * (prescaler = 1) ) * ¼TCy = 50 TCY

The delay of 50 TCY implies we wait 50 TCY before the second signal comes on.

PWM1 5 V
(17)
0
t

PWM2 5 V
(16) delay

0
t

Red
LED Off
t
Grn
100 200 300

This will receive full marks but isn’t actually right. The PWM signals have the same period and
will start on the same signal from Timer2. The actual graph is
PWM1 5 V
(17)
0
t

PWM2 5 V
(16) delay

0
t

Red
LED Off
t
Grn
100 200 300

You would need to discuss the effect of the delay to get full marks.
3. [6] Consider an 11-bit A-to-D Converter with reference voltages from 0.75 V to 4.25 V.
What is the precision of any voltage measurement? Complete the following table (give
correct significant figures).

ADC value Voltage


1450
430
1.38713 V
3.08512 V

Vref+ = 4.25 and Vref– = 0.75. The conversion formula is

V = (b + ½)(Vref+ – Vref–)/211 + Vref–  ½(Vref+ – Vref–)/211

= (b + ½)(3.5)/211 + 0.75  ½(3.5)/211

V1 = (1450 + ½)(3.5)/211 + 0.75  ½(3.5)/211 = 3.2289  0.0009 volts

V2 = (430 + ½)(3.5)/211 + 0.75  ½(3.5)/211 = 1.4857  0.0009 volts

We can use the same formula to find b but ignore the ½, that is for the middle of the bin.

V = b (Vref+ – Vref–)/211 + Vref– = b (3.5)/211 + 0.75

So b = (V – 0.75)* 211/3.5.

Hence b1 = (1.38713 – 0.75)* 211/3.5 = 372.8 = 372 (since b is an integer).

And b2 = (3.08512 – 0.75)* 211/3.5 = 1366.4 = 1366 (since b is an integer).


4. [20] Imagine a period square wave is connected to pin 22 of the MCU as shown in the
diagram below. We want to use a timer functions to measure the “on time” and then
immediately measure the “off time”. It should display these results on your LCD in
milliseconds and repeat for the next cycle. We will use the MCU running at 32 MHz.
The maximum time reading, either on or off, is 700 ms. Your program should produce an
error message if the timer times out. We want the greatest precision possible in our
results. Show calculations. Write a complete main.c source file to do this.

Start Start again


On time
V

Off time
t
V
Need to configure pin 22 (RD3) as input – one time only.
Need to configure timer – one time only.
TCY = 4/32 MHz = 125 × 10-9 s
Therefore Tmax = (0.700 ms)/(125 × 10-9 s) = 5 600 000 TCY
The timer counter maximum is only 65536 so this determines the prescaler value we use

5600000/65536 = 85.4

The appropriate prescaler is 128 (T0_PS_1_128).

The program is

#include <p18f4525> //our MCU


#include <timers.h>
#include <stdio.h> // has printf()
#include “../Functions/configuration_bits.h”
#include “../Functions/osc.h” //set_osc speeds.
#include “../Functions/LCD.h” // LCD commands

void main(void)
{
unsigned int on_time_ms = 0; int off_time_ms = 0;
unsigned char timer_error = 0;
set_osc_32MHz(); //operate at 32 MHz
TRISDbits.TRISD3 = 1; // pin 22 as input (our signal)
OpenTimer0(.. T0_16BIT & T0_PS_1_128);
LCD_Initialize();
LCD_ClearDisplay();
printf(“ Ready “);
while(1)
{
INTCONbits.TMR0IF = 0; // clear timer0 flag
while(!PORTDbits.RD3); wait until the signal goes high
//now the signal is high so we should start timing
WriteTimer0(0); // start timing
while(PORTDbits.RD3 && !INTCONbits.TMR0IF&& !error_timer); //wait for timer
//overflow or signal goes low
if (INTCONbits.TMR0IF) //has the timer timed out?
{//yes – exceeded 0.700 ms
timer_error = 1;
}
else
{//no – successfully timed on signal
on_time_ms = (float)ReadTimer0()*128.*0.125 //convert time to millisec
}
//signal will now have gone low so we time the off time
INTCONbits.TMR0IF = 0; // clear timer0 flag
WriteTimer0(0); // start timing
while(!PORTDbits.RD3 && !INTCONbits.TMR0IF && !error_timer); //wait for timer
//overflow or signal goes high
if (INTCONbits.TMR0IF) //has the timer timed out?
{//yes – exceeded 0.700 ms
timer_error = 1;
}
else
{//no – successfully timed on signal
off_time_ms = (float)ReadTimer0()*128.*0.125 //convert time to millisec
}
//we can now print out the results. Printing takes time so we don’t do in
//while trying to time signal. Signal is now high but we don’t want to time it
if( timer_error ) //time_out happened
{
LCD_ClearDisplay();
printf(“ Timed out! “);
error_timer = 0;
}
else // good timing
{
LCD_ClearDisplay();
printf(“High t = %u (ms)”, on_time_ms);
LCD_MoveTo(1,0); //start of next line
printf(“Low t = %u (ms)”, off_time_ms);
}
while(PORTDbits.RD3); //wait until the signal goes low so we can start over again

}
}

Note: Printing takes time so only print results after you have times both on and off times. You
cannot easily print and monitor signal at same time. Also I can’t give you marks for code I can’t
understand. Comments are vital.
5.[10] Your MCU is connected as in the diagram below. Resistor R = 1000 . A code snippet is supplied. (a) W
answer to correct significant figures and include the precision.

VDD
void main (void)
R {
int ADCvalue;
Voltage LCD_Initalize();
probe PIC18F452 set_osc_32MHz();
5 REF+ R OpenADC( ADC_FOSC_32 & ADC_2_TAD &
2 V
AN0 ADC_RIGHT_JUST,ADC_CH0 & ADC_VREFPLUS_EXT &
470  AN0 ADC_VREFMINUS_EXT, 14);
R Delay10TCYx(5); // Delay 50TCY to stabilize
while(1)
{
R SetChanADC(ADC_CH0);
VREF– ConvertADC();
+AN0 while( BusyADC() );
R ADCvalue = ReadADC();
LCD_CLearDisplay();
printf(“ADC value %u”, ADCvalue);
VSS }
}

We are using reference voltages to do ADC and a voltage divider circuit to get the
reference voltage values.

Vref+ = 4/5 * 5Volts = 4 Volts and Vref– = 1/5 * 5 Volts = 1 volt.

The conversion formula is

V = (b + ½)(Vref+ – Vref–)/210 + Vref–  ½(Vref+ – Vref–)/210

= (b + ½)(3)/210 + 1  ½(3)/210

= (472 + ½)(3)/210 + 1  ½(3)/210 = 2.3843  0.0015 volts

We can use the same formula to find b but ignore the ½, that is for the middle of the bin.

V = b (Vref+ – Vref–)/210 + Vref– = b (3)/210 + 1

So b = (V – 1)* 210/3 = (2.52 – 1)* 210/3 = 518.8 = 518 since b is an integer.

You might also like