Professional Documents
Culture Documents
V 0.2
Luc BIENSTMAN, ZHANG Lin, Supinya PIAMPONGSANT
Chapter 5 Peripherals in C
PIC18F2550 is equipped with a number of peripheral modules, including the Timer Modules, the Capture/ Compare/PWM (CCP) Module, the Comparator Module, the Master Synchronous Serial Port (MSSP) Module, and the Analog-to-Digital Converter (ADC) Module. This chapter serves as an introduction to, and a guide for, using two of these modules: the ADC and the PWM. By configuring the PIC to perform ADC and DAC functions, you will learn to initialize the PIC for peripheral module usage and handling of interrupts.
1. Initialization
Before using the peripheral modules, you need to initialize the PIC. Initialization is the process of resetting variables or special function registers in order to prevent calculating errors or unpredictable behavior due to leftover values in these registers. The initialization will force the device to a ready-to-start state regardless of how many times the program has been looped. In template.c, initialization is done in the function initChip(), take a look at this function.
/************************************************* Initialize the CHIP **************************************************/ void initChip(){ PORTA = 0x00; TRISA = 0x00; ADCON1 = 0x0f; //Turn off ADcon CMCON = 0x07; //Turn off Comparator PORTB = 0x00; TRISB = 0xFF; PORTC = 0x00; TRISC = 0x00; INTCONbits.GIE = 0; // Turn Off global interrupt } To understand what this function does, consult the datasheet. For example, to understand what ADCON1 = 0x0f does, search for information on register ADCON1 in the datasheet. You should come across this page:
This page gives the name of the register, the name of each bit, and the significance of each bit in special function register ADCON1. The row of boxes under the register name gives the name of each bit. For example, bit0 is PCFG0, bit1 is PCFG1, bit5 is VCFG1, etc. If you wish to set only bit0 without affecting other bits, you can code in the following way: ADCON1bits.PCFG0 = 1; Or you can assign value to the whole register. For example, if you wish to use Vdd and Vss as reference voltages and to set AN0 as the only analog pin, you should type the following: ADCON1 = 0x0E;
Figure 1 (Figure 15-2 in datasheet) shows how the comparator module works with Timers 1 and 3 to generate a Special Event Trigger
To start the A/D conversion, the Special Event Trigger of the CCP2 module should be activated. This requires the CCP2CON register to be set to value 0x0B. This setup will cause the A/D to execute a non-stop periodic conversion. The start of the A/D should not be controlled by the GO bit. The functionality of the CCP2 module will activate the GO bit periodically as the TMR1 value equals to the compare preset value in CCPR2H:CCPR2L. The output of the comparator between TMR1 and the preset value CCPR2H:CCPR2L will generate an interrupt flag CCP2IF which will automatically restart the A/D conversion. No interrupt routine is needed to deal with this CCP2 interrupt. (See Fig. 15.2 on the datasheet) Thus the CCP2IF should not be enabled to generate an interrupt, because we dont need it. When the A/D conversion is finished, an interrupt will be generated. This interrupt should be enabled. The A/D conversion results are stored in special function registers ADRESH and ADRESL. To use these values, configure the interrupt routine to copy them to a different memory location. Summary: automatic A/D conversion can be configured using registers associated with PORTA, A/D, Luc BIENSTMAN, ZHANG Lin, Supinya PIAMPONGSANT 4
TMR2, CCP2 as well as an interrupt routine. Once initialized, A/D conversion is executed repeatedly and automatically without software intervention. Overall software execution suffers from one overhead: when a conversion is finished, the A/D result should be copied to a register. This is done via the A/D interrupt routine. Assignment: Read in an analog signal via AN0 and display the most significant bits on PORTB using LEDs. Test your program with a potentiometer (any value between 1k - 100k) connected between power supply and ground. The sliders pin should be connected to analog input AN0. Adjust the voltage on the slider. You should observe changes on PORTB values.
Apply an RC filter after the pulsed PWM output will generate a smooth signal. Goal: learn to generate analog signals from a PIC using PWM. Optional warm up: Create a simple PWM of a square wave at 10kHz. Check your result on an oscilloscope. Assignment: You should have been assigned a team number. Please generate a function accordingly. Team 1 2 3 4 5 6 7 8 9 10 Waveform Triangular 20kHz Sinusoidal 10kHz Sawtooth 30kHz Triangular 30kHz Sinusoidal 5kHz Sawtooth 20kHz Triangular 15kHz Sinusoidal 8kHz Sawtooth 15kHz Sinusoidal 2kHz 5
For the triangular waveforms, the PWM duty cycle should change automatically and smoothly from 100% to 0% and back to 100%. For the sinusoidal waveforms, the PWM duty cycles can be stored in advance in a lookup table. These values should then be fed to the PWM module at the appropriate time.
For the sawtooth waveforms, the PWM duty cycle should change automatically and smoothly from 100% to 0% then go abruptly back to 100%. Optional bonus: Combine your A/D and D/A programs so that the PIC reads in an analog signal via ADC and generates the same signal back on a different pin by PWM. If you finish this, also turn it in for extra points.
MPLABs simulation tool, however, is not aware of the bootloaders presence and assumes that program memory begins at address 0x000 and that high and low interrupt vectors are at 0x008 and 0x018. When an interrupt event occurs in simulation, the counter thus jumps to the wrong place. To correct this, you can change the template so that it ignores the presence of a bootloader in simulation. Follow the steps below. Notice the following lines in the program.
#pragma code _HIGH_INTERRUPT_VECTOR = 0x000808 #pragma code _LOW_INTERRUPT_VECTOR = 0x000818 Luc BIENSTMAN, ZHANG Lin, Supinya PIAMPONGSANT
Run your program, then simulate an interrupt event using Stimulus tool. Use the Step Into tool to observe your program pointer go into the correct interrupt routine. Once you are satisfied with the program and want to load it onto the board, change the addresses back to:
#pragma code _HIGH_INTERRUPT_VECTOR = 0x000808 #pragma code _LOW_INTERRUPT_VECTOR = 0x000818