Advertisement
Guest User

Untitled

a guest
Mar 31st, 2020
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.67 KB | None | 0 0
  1. // CW1: FLASH CONFIGURATION WORD 1 (see PIC24 Family Reference Manual 24.1)
  2. #pragma config ICS = PGx1 // Comm Channel Select (Emulator EMUC1/EMUD1 pins are shared with PGC1/PGD1)
  3. #pragma config FWDTEN = OFF // Watchdog Timer Enable (Watchdog Timer is disabled)
  4. #pragma config GWRP = OFF // General Code Segment Write Protect (Writes to program memory are allowed)
  5. #pragma config GCP = OFF // General Code Segment Code Protect (Code protection is disabled)
  6. #pragma config JTAGEN = OFF // JTAG Port Enable (JTAG port is disabled)
  7. // CW2: FLASH CONFIGURATION WORD 2 (see PIC24 Family Reference Manual 24.1)
  8. #pragma config I2C1SEL = PRI // I2C1 Pin Location Select (Use default SCL1/SDA1 pins)
  9. #pragma config IOL1WAY = OFF // IOLOCK Protection (IOLOCK may be changed via unlocking seq)
  10. #pragma config OSCIOFNC = ON // Primary Oscillator I/O Function (CLKO/RC15 functions as I/O pin)
  11. #pragma config FCKSM = CSECME // Clock Switching and Monitor (Clock switching is enabled,
  12. // Fail-Safe Clock Monitor is enabled)
  13. #pragma config FNOSC = FRCPLL // Oscillator Select (Fast RC Oscillator with PLL module (FRCPLL))
  14.  
  15. #include <xc.h>
  16. #include <stdlib.h>
  17. #define BUFFSIZE 2
  18.  
  19.  
  20. volatile long int overflow = 0;
  21. int high = 0;
  22. int low = 0;
  23. long int duration = 0; //Once the button is pressed, the TMR3 value is stored here to be compared against 0.25ms and 2s
  24. unsigned long int curBUF = 0;
  25. unsigned long int prevBUF = 0;
  26. unsigned long int curEdge = 0;
  27. unsigned long int prevEdge = 0;
  28. unsigned long int period = 0;
  29. volatile unsigned long globalperiod = 0;
  30.  
  31. int servoflag = 0;
  32. int trackperiod = 0;
  33. unsigned long int clear = 0;
  34. int idle = 0;
  35.  
  36. long int circleBuf [BUFFSIZE] = {0};
  37. int write = 0;
  38.  
  39.  
  40. void initServo(void) /*utilize PPS to bind output compare 1 to RP6/RB6 and
  41. * standard register writes to initialize Timer 3 to have a period
  42. * of 20ms (calculate TCKPS and R3 as well set up the OC1 registers)
  43. * Set AD1PCFG and TRIS bits */
  44. {
  45. __builtin_write_OSCCONL (OSCCON & 0xbf); //unlock PPS
  46. RPINR7bits.IC1R = 8; // Use Pin RP8 = "8" for input capture 1 (table 10-2)). Input capture on button
  47. RPOR3bits.RP6R = 18; //use Pin RP6 for output compare 1 = "18" Table (10-3)). Sends a signal to the servo
  48. __builtin_write_OSCCONL (OSCCON | 0x40); //lock PPS
  49.  
  50. /*Timer 3: For Output Compare setup*/
  51. CLKDIVbits.RCDIV = 0; //Set clock speed to 16Mhz
  52. T3CON = 0x0010 ; //PRE 1:8
  53. TMR3 = 0; //Initialize to zero
  54. PR3 = 40000; //set period to be larger than max external sig duration: PR * 62.5ns = 20ms Period for servo
  55. T3CONbits.TON = 1; //start with timer on
  56. _T3IF = 0;
  57.  
  58. /*Input Capture 1 Setup*/
  59. IFS0bits.IC1IF = 0; //Clear IC1 interrupt flag
  60. IEC0bits.IC1IE = 1; //IMPORTANT: Enable IC1 interrupts
  61. IC1CONbits.ICTMR = 1; //IC1 configured to TMR2. Section 15. Input Capture
  62. IC1CONbits.ICM = 0b010; //Capture mode, every falling
  63.  
  64. //Output compare
  65. OC1CON = 0; //turn off OC1 for now
  66. OC1R = 0; //servo start position. We won't touch OC1R again. OC1R: Count when output state is changed (inPWM mode pin is forced LOW)
  67. OC1RS = 3000; //We will only change this once PWM is turned on. OC1RS: Count when output state is changed (in PWM mode acts as a shadow reg). This value is 30000 for the LED tests
  68. OC1CONbits.OCTSEL = 1; //Use timer 3 for compare sources. OCTSEL: 1 = Timer3 is the clock source
  69. OC1CONbits.OCM = 0b110; //Output compare PWM w/o faults. OCM: 110= PWM mode on OC1, fault pin, OCFx, disabled
  70.  
  71. AD1PCFG = 0x9fff; //sets all pins to digital I/O
  72. TRISA = 0b0000000100000000; //set port A to inputs, where 1 is input. This means that RP8 is an input (IC1R) which is connected to the button
  73. TRISB = 0b0000000000000000; //and port B to outputs
  74. LATB = 0b0000000000000000; // where 1 is low
  75. LATA = 0b0000000000000000;
  76.  
  77. }
  78.  
  79. void setServo(int Val) //set output
  80. {
  81. int dutycycle = Val;
  82. OC1RS = dutycycle;
  83. // _T3IF = 0;
  84. }
  85.  
  86. void initPushButton(void)
  87. {
  88. //setup TMR2 to have a period of 1 sec
  89. AD1PCFG = 0x9FFF; // set all pins to digital
  90. TRISB = 0b1111111111001111; //set input and output pins, where 0 is output.
  91. CNPU2bits.CN22PUE = 1;
  92. /* Enable the pull-up resistor on the input pins so that they default to HIGH.
  93. * Important because this makes the button value a logic 1, once the button is pressed
  94. * it turns into logic 0.
  95. */
  96.  
  97. //Timer 2
  98. T2CON = 0x0010;
  99. PR2 = 65535; //Period of about 1 sec for TMR2
  100. _T2IF = 0; //Initialize TMR2 interrupt flag to be zero
  101. TMR2 = 0;
  102. T2CONbits.TCKPS = 0b11; //Pre scalar to 256
  103. T2CONbits.TON = 1; //Turn timer 2 on
  104. _T2IE = 1; //Enables TMR2 interrupt
  105.  
  106. }
  107.  
  108. void __attribute__((__interrupt__,__auto_psv__)) _T2Interrupt(void)
  109. {
  110. IFS0bits.T2IF = 0;
  111. overflow++; //increment the overflow every time that Timer2 completes a full loop
  112. }
  113.  
  114. void storePeriod(unsigned long int localperiod) //This function stores the falling edges
  115. {
  116. circleBuf [write] = localperiod;
  117. write++;
  118. write %= BUFFSIZE; //Once write is incremented to 3, start over at index 0
  119. trackperiod++; //for any 'n' amount of clicks
  120. }
  121.  
  122.  
  123. int newPeriod(void)
  124. {
  125. if (trackperiod > 0)
  126. {
  127. return 1; //a new period has been introduced in the circleBuf array
  128. }
  129.  
  130. else
  131. {
  132. return 0;
  133. }
  134.  
  135. }
  136.  
  137.  
  138.  
  139. void __attribute__((__interrupt__,__auto_psv__)) _IC1Interrupt(void)
  140. {
  141. IFS0bits.IC1IF = 0; //Reset the IC1 flag
  142. curBUF = IC1BUF; //store value of TMR2 at falling edge
  143. curEdge = curBUF + (overflow *65535); //To get the actual value of instruction cycles, must account for the previous cycles (overflow*PR2)
  144. period = curEdge;
  145.  
  146. if(period > 125) //serves as a de-bounce
  147. {
  148. //setServo(2400); //2400, move to the right
  149. TMR2 = 0; //By setting TMR2 = 0, I do not need to do curEdge-prevEdge.
  150. overflow = 0;
  151. storePeriod(period);
  152. }
  153.  
  154. while(IC1CONbits.ICBNE) //ICBNE = 0 means input capture Buffer is empty.
  155. {
  156. clear = IC1BUF;
  157. }
  158.  
  159. }
  160.  
  161.  
  162. int main(void) {
  163. initServo();
  164. initPushButton();
  165.  
  166. while(1)
  167. {
  168. int i = 0;
  169.  
  170. if(newPeriod()) //If a new value is in the array, then check that value. Once this is zero, we have gone through all elements
  171. {
  172. while(i< BUFFSIZE) //Iterate through the entire circleBuf array
  173. {
  174. if(circleBuf[i] > 15625)
  175. {
  176. servoflag = 0; //if flag is zero, choose to stay in the left position
  177. break; //If any click was long, do not cycle through the rest of the array
  178. }
  179.  
  180. else
  181. {
  182. servoflag = 1; //If all periods were short then we have a triple click.
  183. }
  184. i++;
  185. }
  186.  
  187. trackperiod = 0; //This will make the newperiod() false, meaning there no new periods to check
  188. }
  189.  
  190. if (overflow >= 2 || servoflag == 0) //overflow statement is used if we have been idle for a long time. servoflag also used to determine position
  191. {
  192. setServo(3600); //Left
  193. servoflag = 0;
  194. }
  195.  
  196. else if(servoflag == 1) //If all clicks were short, move to the right
  197. {
  198. setServo(2400); //Right
  199.  
  200. }
  201. }
  202. return (0);
  203. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement