00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "pic24_all.h"
00030 #include <stdio.h>
00031
00041 #define PWM_PERIOD 12000 //in microseconds
00042
00043 void configTimer2(void) {
00044 T2CON = T2_OFF | T2_IDLE_CON | T2_GATE_OFF
00045 | T2_32BIT_MODE_OFF
00046 | T2_SOURCE_INT
00047 | T2_PS_1_256 ;
00048 PR2 = usToU16Ticks(PWM_PERIOD, getTimerPrescale(T2CONbits)) - 1;
00049 TMR2 = 0;
00050 }
00051
00052
00053 #define NUM_SERVOS 4
00054 #define SERVO0 _LATB2
00055 #define SERVO1 _LATB3
00056 #define SERVO2 _LATB13
00057 #define SERVO3 _LATB14
00058
00059 #define MIN_PW 600 //minimum pulse width, in us
00060 #define MAX_PW 2400 //minimum pulse width, in us
00061 #define SLOT_WIDTH 2800 //slot width, in us
00062
00063 volatile uint16 au16_servoPWidths[NUM_SERVOS];
00064 volatile uint8 u8_currentServo =0;
00065 volatile uint8 u8_servoEdge = 1;
00066 volatile uint16 u16_slotWidthTicks = 0;
00067
00068 void initServos(void) {
00069 uint8 u8_i;
00070 uint16 u16_initPW;
00071
00072 u8_currentServo = 0;
00073 CONFIG_RB2_AS_DIG_OUTPUT();
00074 CONFIG_RB3_AS_DIG_OUTPUT();
00075 CONFIG_RB13_AS_DIG_OUTPUT();
00076 CONFIG_RB14_AS_DIG_OUTPUT();
00077 u16_initPW = usToU16Ticks(MIN_PW + (MAX_PW-MIN_PW)/2, getTimerPrescale(T2CONbits));
00078
00079
00080 for (u8_i=0; u8_i<NUM_SERVOS; u8_i++) au16_servoPWidths[u8_i]=u16_initPW;
00081 SERVO0 = 0;
00082 SERVO1 = 0;
00083 SERVO2 = 0;
00084 SERVO3 = 0;
00085 u16_slotWidthTicks = usToU16Ticks(SLOT_WIDTH, getTimerPrescale(T2CONbits));
00086 }
00087
00088
00089
00090 void setServoOutput (uint8 u8_servo, uint8 u8_val) {
00091 switch (u8_servo) {
00092 case 0:
00093 SERVO0 = u8_val;
00094 break;
00095 case 1:
00096 SERVO1 = u8_val;
00097 break;
00098 case 2:
00099 SERVO2 = u8_val;
00100 break;
00101 case 3:
00102 SERVO3 = u8_val;
00103 break;
00104 default:
00105 break;
00106 }
00107 }
00108
00109 void _ISR _OC1Interrupt(void) {
00110 _OC1IF = 0;
00111
00112 setServoOutput(u8_currentServo, u8_servoEdge);
00113
00114 if (u8_servoEdge == 1) {
00115
00116 OC1R = OC1R + au16_servoPWidths[u8_currentServo];
00117 u8_servoEdge = 0;
00118 } else {
00119
00120 if (u8_currentServo != NUM_SERVOS -1)
00121 OC1R = u16_slotWidthTicks*(u8_currentServo+1);
00122 else
00123 OC1R = 0;
00124 u8_servoEdge = 1;
00125 u8_currentServo++;
00126 if (u8_currentServo == NUM_SERVOS) u8_currentServo = 0;
00127 }
00128 }
00129
00130
00131 void configOutputCapture1(void) {
00132 T2CONbits.TON = 0;
00133 OC1R = 0;
00134
00135 OC1CON = OC_TIMER2_SRC |
00136 OC_TOGGLE_PULSE;
00137 _OC1IF = 0;
00138 _OC1IP = 1;
00139 _OC1IE = 1;
00140 }
00141
00142 char sz_buf[32];
00143
00144 void getServoValue(void) {
00145 int16 u16_servo;
00146 int16 u16_pw;
00147 printf("Choose servo (1,2,3,4): ");
00148 inStringEcho(sz_buf,31);
00149 sscanf(sz_buf,"%d",(int *) &u16_servo);
00150 if ((u16_servo > 4) || (u16_servo < 1)) {
00151 printf("Invalid servo..\n");
00152 return;
00153 }
00154 printf("Enter pulse width (min 600, max 2400): ");
00155 inStringEcho(sz_buf,31);
00156 sscanf(sz_buf,"%d",(int *) &u16_pw);
00157 if ((u16_pw > 2400) || (u16_pw < 600)) {
00158 printf("Invalid pulse width..\n");
00159 return;
00160 }
00161
00162 _OC1IE = 0;
00163 au16_servoPWidths[u16_servo-1]=usToU16Ticks(u16_pw, getTimerPrescale(T2CONbits));
00164 _OC1IE = 1;
00165 }
00166
00167 int main(void) {
00168 configBasic(HELLO_MSG);
00169 configTimer2();
00170 initServos();
00171 configOutputCapture1();
00172 T2CONbits.TON = 1;
00173 while (1) {
00174 getServoValue();
00175 }
00176 }