PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pwm_dac.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 a PWM DAC - connect an RC filter on the OC1
34 output and vary the pulse width of the PWM signal, and monitor
35 the DC value on the capacitor. The RC time constant should
36 be at least 10x greater than the PWM period. Examples values
37 used for testing were R=6.8k, C = 1.0u, PWM period= 500 us
38 For better accuracy, use an external crystal and define
39 CLOCK_CONFIG=PRIPLL_8MHzCrystal_40MHzFCY in the MPLAB project.
40 Remove this macro if you wish to use the internal oscillator.
41 */
42 
43 #ifndef PWM_PERIOD
44 #define PWM_PERIOD 500 // desired period, in us
45 #endif
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_8 ; //1 tick = 1.6 us at FCY=40 MHz
52  PR2 = usToU16Ticks(PWM_PERIOD, getTimerPrescale(T2CONbits)) - 1;
53  TMR2 = 0; //clear timer2 value
54  _T2IF = 0;
55  _T2IP = 1;
56  _T2IE = 1; //enable the Timer2 interrupt
57 }
58 
59 void configOutputCompare1(void) {
60  T2CONbits.TON = 0; //disable Timer when configuring Output compare
61  OC1R = 0;
62  OC1RS = 0; //initially off
63 //assumes TIMER2 initialized before OC1 so PRE bits are set
64 #if (defined(__dsPIC33E__) || defined(__PIC24E__))
65  CONFIG_OC1_TO_RP(35); //map OC1 to RP35/RB3
66 //turn on the compare toggle mode using Timer2
67  OC1CON1 = OC_TIMER2_SRC | //Timer2 source
68  OC_PWM_CENTER_ALIGN; //PWM
69  OC1CON2 = 0x000C; //sync source is Timer2.
70 #else
71  CONFIG_RB3_AS_DIG_OUTPUT();
72  CONFIG_OC1_TO_RP(3); //map OC1 to RP3/RB3
73 //turn on the compare toggle mode using Timer2
74  OC1CON = OC_TIMER2_SRC | //Timer2 source
75  OC_PWM_FAULT_PIN_DISABLE; //PWM, no fault detection
76 #endif
77 }
78 
79 void _ISR _T2Interrupt(void) {
80  uint32_t u32_temp;
81  _T2IF = 0; //clear the timer interrupt bit
82  //update the PWM duty cycle from the ADC value
83  u32_temp = ADC1BUF0; //use 32-bit value for range
84  //compute new pulse width that is 0 to 99% of PR2
85  // pulse width (PR2) * ADC/1024
86  u32_temp = (u32_temp * (PR2))>> 10 ; // >>10 is same as divide/1024
87  OC1RS = u32_temp; //update pulse width value
88  AD1CON1bits.SAMP = 1; //start next ADC conversion for next interrupt
89 }
90 
91 int main(void) {
92  uint16_t u16_oc1rs;
93  uint32_t u32_pw;
94  float f_dacV;
95  configBasic(HELLO_MSG);
96  configTimer2();
97  configOutputCompare1();
98  CONFIG_AN0_AS_ANALOG();
99  configADC1_ManualCH0( ADC_CH0_POS_SAMPLEA_AN0, 31, 0 );
100  SET_SAMP_BIT_ADC1(); //start sampling and conversion
101  T2CONbits.TON = 1; //turn on Timer2 to start PWM
102  while (1) {
103  u16_oc1rs = OC1RS;
104  u32_pw= ticksToUs(u16_oc1rs, getTimerPrescale(T2CONbits));
105  f_dacV = u16_oc1rs;
106  f_dacV = f_dacV * 3.3/(PR2+1);
107 #ifdef SMALLRAM
108  {
109  uint16_t ui16_dacValmv;
110  ui16_dacValmv = f_dacV * 1000;
111  printf("PWM PW (us): %ld, PWM DAC voltage: %d\n",u32_pw, ui16_dacValmv);
112  }
113 #else
114  printf("PWM PW (us): %ld, PWM DAC voltage: %4.2f\n",u32_pw, (double) f_dacV);
115 #endif
116  DELAY_MS(100);
117  }
118 }