PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
outputcompare_oneservo.c
Go to the documentation of this file.
1 /*
2  * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
3  * All rights reserved.
4  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
5  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
6  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation for any purpose, without fee, and without written agreement is
10  * hereby granted, provided that the above copyright notice, the following
11  * two paragraphs and the authors appear in all copies of this software.
12  *
13  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
15  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
16  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17  *
18  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
23  *
24  * Please maintain this header in its entirety when copying/modifying
25  * these files.
26  *
27  *
28  */
29 #include "pic24_all.h"
30 #include <stdio.h>
31 
32 /** \file
33 Demonstrates pulse width modulation using the OC1 output to control a
34 hobby servo. The ADC input value on AN0 is used to
35 vary the pulse width between its min and maximum values.
36 For additional accuracy, use an external crystal and define the following
37 CLOCK_CONFIG=PRIPLL_8MHzCrystal_40MHzFCY in the MPLAB project.
38 Remove this macro if you wish to use the internal oscillator.
39 */
40 
41 #ifndef PWM_PERIOD
42 #define PWM_PERIOD 20000 // desired period, in us
43 #endif
44 #define MIN_PW 600 //minimum pulse width, in us
45 #define MAX_PW 2400 //maximum pulse width, in us
46 
47 void configTimer2(void) {
48  T2CON = T2_OFF | T2_IDLE_CON | T2_GATE_OFF
49  | T2_32BIT_MODE_OFF
50  | T2_SOURCE_INT
51  | T2_PS_1_64 ; //1 tick = 1.6 us at FCY=40 MHz
52  PR2 = usToU16Ticks(PWM_PERIOD, getTimerPrescale(T2CONbits));
53  TMR2 = 0; //clear timer2 value
54  _T2IF = 0;
55  _T2IP = 1;
56  _T2IE = 1; //enable the Timer2 interrupt
57 }
58 
59 uint16_t u16_minPWTicks;
60 uint16_t u16_maxPWTicks;
61 void configOutputCompare1(void) {
62  u16_minPWTicks = usToU16Ticks(MIN_PW, getTimerPrescale(T2CONbits));
63  u16_maxPWTicks = usToU16Ticks(MAX_PW, getTimerPrescale(T2CONbits));
64  T2CONbits.TON = 0; //disable Timer when configuring Output compare
65  CONFIG_RB3_AS_DIG_OUTPUT();
66 #if (defined(__dsPIC33E__) || defined(__PIC24E__))
67  CONFIG_OC1_TO_RP(35); //map OC1 to RP35/RB3
68 #else
69  CONFIG_OC1_TO_RP(3); //map OC1 to RP3/RB3
70 #endif
71 //assumes TIMER2 initialized before OC1 so PRE bits are set
72  OC1RS = 0; //initially off
73 //turn on the compare toggle mode using Timer2
74 #if (defined(__dsPIC33E__) || defined(__PIC24E__))
75 //turn on the compare toggle mode using Timer2
76  OC1CON1 = OC_TIMER2_SRC | //Timer2 source
77  OC_PWM_CENTER_ALIGN; //PWM
78  OC1CON2 = 0x000C; //sync source is Timer2.
79 #else
80  OC1CON = OC_TIMER2_SRC | //Timer2 source
81  OC_PWM_FAULT_PIN_DISABLE; //PWM, no fault detection
82 #endif
83 }
84 
85 
86 
87 void _ISR _T2Interrupt(void) {
88  uint32_t u32_temp;
89  _T2IF = 0; //clear the timer interrupt bit
90  //update the PWM duty cycle from the ADC value
91  u32_temp = ADC1BUF0; //use 32-bit value for range
92  //compute new pulse width using ADC value
93  // (max - min) * ADC/1024 + min
94  u32_temp = ((u32_temp * (u16_maxPWTicks-u16_minPWTicks))>> 10) + u16_minPWTicks; // >>10 is same as divide/1024
95  OC1RS = u32_temp; //update pulse width value
96  AD1CON1bits.SAMP = 1; //start next ADC conversion for next interrupt
97 }
98 
99 int main(void) {
100  uint32_t u32_pw;
101  configBasic(HELLO_MSG);
102  configTimer2();
103  configOutputCompare1();
104  CONFIG_AN0_AS_ANALOG();
105  configADC1_ManualCH0(ADC_CH0_POS_SAMPLEA_AN0, 31, 1);
106  SET_SAMP_BIT_ADC1(); //start sampling and conversion
107  T2CONbits.TON = 1; //turn on Timer2 to start PWM
108  while (1) {
109  u32_pw = ticksToUs(OC1RS, getTimerPrescale(T2CONbits));
110  printf("PWM PW (us): %ld \n",u32_pw);
111  DELAY_MS(100);
112  }
113 }