/* MAIN.
1. #define CO_FCY 24000 /* (8MHz Quartz used) */
2.
3.
4. #include "CANopen.h"
5. /* (not implemented) #include "eeprom.h" */
6.
7.
8. /* Configuration bits */
9. _FOSCSEL(FNOSC_PRIPLL); /* Primary (XT, HS, EC) Oscillator / PLL enabled / */
10. _FOSC(FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMD_XT);
11. /* Clock Switching and Fail Safe Clock Monitor is disabled */
12. /* OSC2 Pin Function: OSC2 is Clock Output */
13. /* Primary Oscillator Mode: XT Crystal */
14.
15.
16. /* macros */
17. #define CO_TIMER_ISR() void __attribute__((interrupt, auto_psv)) _T2Interrupt (void)
18. #define CO_TMR_TMR TMR2 /* TMR register */
19. #define CO_TMR_PR PR2 /* Period register */
20. #define CO_TMR_CON T2CON /* Control register */
21. #define CO_TMR_ISR_FLAG IFS0bits.T2IF /* Interrupt Flag bit */
22. #define CO_TMR_ISR_PRIORITY IPC1bits.T2IP /* Interrupt Priority */
23. #define CO_TMR_ISR_ENABLE IEC0bits.T2IE /* Interrupt Enable bit */
24.
25. #define CO_CAN_ISR() void __attribute__((interrupt, auto_psv)) _C1Interrupt (void)
26. #define CO_CAN_ISR_FLAG IFS2bits.C1IF /* Interrupt Flag bit */
27. #define CO_CAN_ISR_PRIORITY IPC8bits.C1IP /* Interrupt Priority */
28. #define CO_CAN_ISR_ENABLE IEC2bits.C1IE /* Interrupt Enable bit */
29.
30.
31. /* Global variables and objects */
32. volatile uint16_t CO_timer1ms = 0U; /* variable increments each millisecond */
33. const CO_CANbitRateData_t CO_CANbitRateData[8] = {CO_CANbitRateDataInitializers};
34. /* (not implemented) eeprom_t eeprom; */
35.
36.
37. /* main ***********************************************************************/
38. int main (void){
39. CO_NMT_reset_cmd_t reset = CO_RESET_NOT;
40.
41. /* Initialize two CAN led diodes */
42. TRISAbits.TRISA0 = 0; LATAbits.LATA0 = 0;
43. TRISAbits.TRISA1 = 0; LATAbits.LATA1 = 1;
44. #define CAN_RUN_LED LATAbits.LATA0
45. #define CAN_ERROR_LED LATAbits.LATA1
46.
47. /* Initialize other LED diodes for RPDO */
48. TRISAbits.TRISA2 = 0; LATAbits.LATA2 = 0;
49. TRISAbits.TRISA3 = 0; LATAbits.LATA3 = 0;
50. TRISAbits.TRISA4 = 0; LATAbits.LATA4 = 0;
51. TRISAbits.TRISA5 = 0; LATAbits.LATA5 = 0;
52. TRISAbits.TRISA6 = 0; LATAbits.LATA6 = 0;
53. TRISAbits.TRISA7 = 0; LATAbits.LATA7 = 0;
54.
55.
56. /* Configure Oscillator */
57. /* Fosc = Fin*M/(N1*N2), Fcy=Fosc/2 */
58. /* Fosc = 8M*24(2*2) = 48MHz -> Fcy = 24MHz */
59. PLLFBD=22; /* M=24 */
60. CLKDIVbits.PLLPOST=0; /* N1=2 */
61. CLKDIVbits.PLLPRE=0; /* N2=2 */
62. OSCTUN=0; /* Tune FRC oscillator, if FRC is used */
63. while(OSCCONbits.LOCK!=1) ClrWdt(); /* wait for PLL to lock */
64.
65.
66. /* Verify, if OD structures have proper alignment of initial values */
67. if(CO_OD_RAM.FirstWord != CO_OD_RAM.LastWord) while(1) ClrWdt();
68. if(CO_OD_EEPROM.FirstWord != CO_OD_EEPROM.LastWord) while(1) ClrWdt();
69. if(CO_OD_ROM.FirstWord != CO_OD_ROM.LastWord) while(1) ClrWdt();
70.
71.
72. /* initialize EEPROM */
73. /* (not implemented) */
74.
75. /* increase variable each startup. Variable is stored in eeprom. */
76. OD_powerOnCounter++;
77.
78. while(reset != CO_RESET_APP){
79. /* CANopen communication reset - initialize CANopen objects *******************/
80. static uint16_t timer1msPrevious;
81. CO_ReturnError_t err;
82.
83. /* disable timer and CAN interrupts, turn on red LED */
84. CO_TMR_ISR_ENABLE = 0;
85. CO_CAN_ISR_ENABLE = 0;
86. CAN_RUN_LED = 0;
87. CAN_ERROR_LED = 1;
88.
89. /* Initialize digital outputs */
90. TRISAbits.TRISA2 = 0; LATAbits.LATA2 = 0;
91. TRISAbits.TRISA3 = 0; LATAbits.LATA3 = 0;
92. TRISAbits.TRISA4 = 0; LATAbits.LATA4 = 0;
93. TRISAbits.TRISA5 = 0; LATAbits.LATA5 = 0;
94. TRISAbits.TRISA6 = 0; LATAbits.LATA6 = 0;
95. TRISAbits.TRISA7 = 0; LATAbits.LATA7 = 0;
96. OD_writeOutput8Bit[0] = 0;
97. OD_writeOutput8Bit[1] = 0;
98.
99.
100. /* initialize CANopen */
101. err = CO_init();
102. if(err != CO_ERROR_NO){
103. while(1) ClrWdt();
104. /* CO_errorReport(CO-
>em, CO_EM_MEMORY_ALLOCATION_ERROR, CO_EMC_SOFTWARE_INTERNAL, err); */
105. }
106.
107. /* start CAN */
108. CO_CANsetNormalMode(ADDR_CAN1);
109.
110.
111. /* Configure Timer interrupt function for execution every 1 millisecond */
112. CO_TMR_CON = 0;
113. CO_TMR_TMR = 0;
114. CO_TMR_PR = CO_FCY - 1; /* Period register */
115. CO_TMR_CON = 0x8000; /* start timer (TON=1) */
116. CO_timer1ms = 0;
117. CO_TMR_ISR_FLAG = 0; /* clear interrupt flag */
118. CO_TMR_ISR_PRIORITY = 3; /* interrupt - set lower priority than CAN */
119. CO_TMR_ISR_ENABLE = 1; /* enable interrupt */
120. /* Configure CAN1 Interrupt (Combined) */
121. CO_CAN_ISR_FLAG = 0; /* CAN1 Interrupt - Clear flag */
122. CO_CAN_ISR_PRIORITY = 5; /* CAN1 Interrupt - Set higher priority than timer */
123. CO_CAN_ISR_ENABLE = 1; /* CAN1 Interrupt - Enable interrupt */
124.
125. reset = CO_RESET_NOT;
126. timer1msPrevious = CO_timer1ms;
127.
128. while(reset == CO_RESET_NOT){
129. /* loop for normal program execution ******************************************/
130. uint16_t timer1msCopy, timer1msDiff;
131. static uint16_t TMR_TMR_PREV = 0;
132.
133. timer1msCopy = CO_timer1ms;
134. timer1msDiff = timer1msCopy - timer1msPrevious;
135. timer1msPrevious = timer1msCopy;
136.
137. ClrWdt();
138.
139. /* calculate cycle time for performance measurement */
140. uint16_t t0 = CO_TMR_TMR;
141. uint16_t t = t0;
142. if(t >= TMR_TMR_PREV){
143. t = t - TMR_TMR_PREV;
144. t = (timer1msDiff * 100) + (t / (CO_FCY / 100));
145. }
146. else if(timer1msDiff){
147. t = TMR_TMR_PREV - t;
148. t = (timer1msDiff * 100) - (t / (CO_FCY / 100));
149. }
150. else t = 0;
151. OD_performance[ODA_performance_mainCycleTime] = t;
152. if(t > OD_performance[ODA_performance_mainCycleMaxTime])
153. OD_performance[ODA_performance_mainCycleMaxTime] = t;
154. TMR_TMR_PREV = t0;
155.
156. /* CANopen process */
157. reset = CO_process(CO, timer1msDiff);
158.
159. CAN_RUN_LED = LED_GREEN_RUN(CO->NMT);
160. CAN_ERROR_LED = LED_RED_ERROR(CO->NMT);
161.
162. ClrWdt();
163.
164. /* (not implemented) eeprom_process(&eeprom); */
165. }
166. }
167. /* program exit ***************************************************************/
168. /* save variables to eeprom */
169. RESTORE_CPU_IPL(7); /* disable interrupts */
170. CAN_RUN_LED = 0;
171. /* CAN_ERROR_LED = 0; */
172. /* (not implemented) eeprom_saveAll(&eeprom); */
173. CAN_ERROR_LED = 1;
174.
175. /* delete CANopen object from memory */
176. CO_delete();
177.
178. /* reset */
179. return 0;
180. }
181.
182.
183. /* timer interrupt function executes every millisecond ************************/
184. CO_TIMER_ISR(){
185. /* clear interrupt flag bit */
186. CO_TMR_ISR_FLAG = 0;
187.
188. CO_timer1ms++;
189.
190. CO_process_RPDO(CO);
191.
192.
193. /* read RPDO and show it on example LEDS on Explorer16 */
194. uint8_t leds = OD_writeOutput8Bit[0];
195. LATAbits.LATA2 = (leds&0x04) ? 1 : 0;
196. LATAbits.LATA3 = (leds&0x08) ? 1 : 0;
197. LATAbits.LATA4 = (leds&0x10) ? 1 : 0;
198. LATAbits.LATA5 = (leds&0x20) ? 1 : 0;
199. LATAbits.LATA6 = (leds&0x40) ? 1 : 0;
200. LATAbits.LATA7 = (leds&0x80) ? 1 : 0;
201.
202. /* prepare TPDO from example buttons on Explorer16 */
203. uint8_t but = 0;
204. if(!PORTDbits.RD6) but |= 0x08;
205. if(!PORTDbits.RD7) but |= 0x04;
206. if(!PORTDbits.RD13) but |= 0x01;
207. OD_readInput8Bit[0] = but;
208.
209.
210. CO_process_TPDO(CO);
211.
212. /* verify timer overflow */
213. if(CO_TMR_ISR_FLAG == 1){
214. CO_errorReport(CO->em, CO_EM_ISR_TIMER_OVERFLOW, CO_EMC_SOFTWARE_INTERNAL, 0);
215. CO_TMR_ISR_FLAG = 0;
216. }
217.
218. /* calculate cycle time for performance measurement */
219. uint16_t t = CO_TMR_TMR / (CO_FCY / 100);
220. OD_performance[ODA_performance_timerCycleTime] = t;
221. if(t > OD_performance[ODA_performance_timerCycleMaxTime])
222. OD_performance[ODA_performance_timerCycleMaxTime] = t;
223. }
224.
225.
226. /* CAN interrupt function *****************************************************/
227. CO_CAN_ISR(){
228. CO_CANinterrupt(CO->CANmodule[0]);
229. /* Clear combined Interrupt flag */
230. CO_CAN_ISR_FLAG = 0;
231. }