CAN总线硬件连接及程序
1. / F04x_CAN1.c 2. /- 3. / 4. / 5. / DEVICE: C8051F040 6. / 7. / AUTHOR: LS 8. / 9. / TOOLS: Keil C-compiler and Silicon Labs IDE 10. / 11. / 12. / CAN1.c and CAN2.c are a simple example of configuring a CAN network to 13. / transmit and receive data on a CAN network, and how to move information to 14. / and from CAN RAM message objects. Each C8051F040-TB CAN node is configured 15. / to send a message when it's P3.7 button is depressed/released, with a 0x11 16. / to indicate the button is pushed, and 0x00 when released. Each node also has 17. / a message object configured to receive messages. The C8051 tests the 18. / received data and will turn on/off the target board's LED. When one target 19. / is loaded with CAN2.c and the other is loaded with CAN1.c, one target 20. / board's push-button will control the other target board's LED, establishing 21. / a simple control link via the CAN bus and can be observed directly on the 22. / target boards. 23. / 24. 25. / 26. / Includes 27. / 28. 29. #include <c8051f040.h> / SFR declarations 30. 31. / CAN Protocol Register Index for CAN0ADR, from TABLE 18.1 of the C8051F040 32. / datasheet 33. / 34. #define CANCTRL 0x00 /Control Register 35. #define CANSTAT 0x01 /Status register 36. #define ERRCNT 0x02 /Error Counter Register 37. #define BITREG 0x03 /Bit Timing Register 38. #define INTREG 0x04 /Interrupt Low Byte Register 39. #define CANTSTR 0x05 /Test register 40. #define BRPEXT 0x06 /BRP Extension Register 41. / 42. /IF1 Interface Registers 43. / 44. #define IF1CMDRQST 0x08 /IF1 Command Rest Register 45. #define IF1CMDMSK 0x09 /IF1 Command Mask Register 46. #define IF1MSK1 0x0A /IF1 Mask1 Register 47. #define IF1MSK2 0x0B /IF1 Mask2 Register 48. #define IF1ARB1 0x0C /IF1 Arbitration 1 Register 49. #define IF1ARB2 0x0D /IF1 Arbitration 2 Register 50. #define IF1MSGC 0x0E /IF1 Message Control Register 51. #define IF1DATA1 0x0F /IF1 Data A1 Register 52. #define IF1DATA2 0x10 /IF1 Data A2 Register 53. #define IF1DATB1 0x11 /IF1 Data B1 Register 54. #define IF1DATB2 0x12 /IF1 Data B2 Register 55. / 56. /IF2 Interface Registers 57. / 58. #define IF2CMDRQST 0x20 /IF2 Command Rest Register 59. #define IF2CMDMSK 0x21 /IF2 Command Mask Register 60. #define IF2MSK1 0x22 /IF2 Mask1 Register 61. #define IF2MSK2 0x23 /IF2 Mask2 Register 62. #define IF2ARB1 0x24 /IF2 Arbitration 1 Register 63. #define IF2ARB2 0x25 /IF2 Arbitration 2 Register 64. #define IF2MSGC 0x26 /IF2 Message Control Register 65. #define IF2DATA1 0x27 /IF2 Data A1 Register 66. #define IF2DATA2 0x28 /IF2 Data A2 Register 67. #define IF2DATB1 0x29 /IF2 Data B1 Register 68. #define IF2DATB2 0x2A /IF2 Data B2 Register 69. / 70. /Message Handler Registers 71. / 72. #define TRANSREQ1 0x40 /Transmission Rest1 Register 73. #define TRANSREQ2 0x41 /Transmission Rest2 Register 74. 75. #define NEWDAT1 0x48 /New Data 1 Register 76. #define NEWDAT2 0x49 /New Data 2 Register 77. 78. #define INTPEND1 0x50 /Interrupt Pending 1 Register 79. #define INTPEND2 0x51 /Interrupt Pending 2 Register 80. 81. #define MSGVAL1 0x58 /Message Valid 1 Register 82. #define MSGVAL2 0x59 /Message Valid 2 Register 83. 84. / 85. /Global Variables 86. / 87. char MsgNum; 88. char status; 89. int i; 90. int MOTwoIndex = 0; 91. int MOOneIndex = 0; 92. int StatusCopy; 93. int RXbuffer 4; 94. int TXbuffer 8; 95. int MsgIntNum; 96. int Temperature; 97. sbit BUTTON = P37; 98. sbit LED = P16; 99. sfr16 CAN0DAT = 0xD8; 100. 101. 102. 103. / 104. / Function PROTOTYPES 105. / 106. 107. / Initialize Message Object 108. void clear_msg_objects (void); 109. void init_msg_object_TX (char MsgNum); 110. void init_msg_object_RX (char MsgNum); 111. void start_CAN (void); 112. void transmit_turn_LED_ON (char MsgNum); 113. void transmit_turn_LED_OFF (char MsgNum); 114. void receive_data (char MsgNum); 115. void external_osc (void); 116. void config_IO (void); 117. void flash_LED (void); 118. void test_reg_write (char test); 119. void stop_CAN (void); 120. 121. 122. / 123. / MAIN Routine 124. / 125. void main (void) 126. 127. / disable watchdog timer 128. WDTCN = 0xde; 129. WDTCN = 0xad; 130. 131. /configure Port I/O 132. config_IO(); 133. 134. / switch to external oscillator 135. external_osc(); 136. 137. 138. / 139. / Configure CAN communications 140. / 141. / IF1 used for procedures calles by main program 142. / IF2 used for interrupt service procedure receive_data 143. / 144. / Message Object assignments: 145. / 0x02: Used to transmit commands to toggle its LED, arbitration number 1 146. / 147. / 148. 149. / Clear CAN RAM 150. clear_msg_objects(); 151. 152. / Initialize message object to transmit data 153. init_msg_object_TX (0x02); 154. 155. / Initialize message object to receive data 156. init_msg_object_RX (0x01); 157. 158. / Enable CAN interrupts in CIP-51 159. EIE2 = 0x20; 160. 161. /Function call to start CAN 162. start_CAN(); 163. 164. /Global enable 8051 interrupts 165. EA = 1; 166. 167. /Loop and wait for interrupts 168. while (1) 169. 170. if (BUTTON = 0) 171. while (BUTTON = 0) 172. transmit_turn_LED_OFF(0x02); 173. else 174. while (BUTTON = 1) 175. transmit_turn_LED_ON(0x02); 176. 177. 178. 179. 180. / 181. / Set up C8051F040 182. / 183. 184. / Switch to external oscillator 185. void external_osc (void) 186. 187. int n; / local variable used in delay FOR loop. 188. SFRPAGE = CONFIG_PAGE; / switch to config page to config oscillator 189. OSCXCN = 0x77; / start external oscillator; 22.1 MHz Crystal 190. / system clock is 22.1 MHz / 2 = 11.05 MHz 191. for (n=0;n<255;n+); / delay about 1ms 192. while (OSCXCN & 0x80) = 0); / wait for oscillator to stabilize 193. CLKSEL |= 0x01; / switch to external oscillator 194. 195. 196. void config_IO (void) 197. 198. SFRPAGE = CONFIG_PAGE; /Port SFR's on Configuration page 199. XBR3 = 0x80; / Configure CAN TX pin (CTX) as push-pull digital output 200. P1MDOUT |= 0x40; / Configure P1.6 as push-pull to drive LED 201. XBR2 = 0x40; / Enable Crossbar/low ports 202. 203. 204. / 205. /CAN Functions 206. / 207. 208. 209. /Clear Message Objects 210. void clear_msg_objects (void) 211. 212. SFRPAGE = CAN0_PAGE; 213. CAN0ADR = IF1CMDMSK; / Point to Command Mask Register 1 214. CAN0DATL = 0xFF; / Set direction to WRITE all IF registers to Msg Obj 215. for (i=1;i<33;i+) 216. 217. CAN0ADR = IF1CMDRQST; / Write blank (reset) IF registers to each msg obj 218. CAN0DATL = i; 219. 220. 221. 222. /Initialize Message Object for RX 223. void init_msg_object_RX (char MsgNum) 224. 225. SFRPAGE = CAN0_PAGE; 226. CAN0ADR = IF1CMDMSK; / Point to Command Mask 1 227. CAN0DAT = 0x00B8; / Set to WRITE, and alter all Msg Obj except ID MASK 228. / and data bits 229. CAN0ADR = IF1ARB1; / Point to arbitration1 register 230. CAN0DAT = 0x0000; / Set arbitration1 ID to "0" 231. CAN0DAT = 0x8004; / Arb2 high byte:Set MsgVal bit, no extended ID, 232. / Dir = RECEIVE 233. CAN0DAT = 0x0480; / Msg Cntrl: set RXIE, remote frame function disabled 234. CAN0ADR = IF1CMDRQST; / Point to Command Request reg. 235. CAN0DATL = MsgNum; / Select Msg Obj passed into function parameter list 236. / -initiates write to Msg Obj 237. / 3-6 CAN clock cycles to move IF register contents to the Msg Obj in CAN RAM 238. 239. 240. /Initialize Message Object for TX 241. void init_msg_object_TX (char MsgNum) 242. 243. SFRPAGE = CAN0_PAGE; 244. CAN0ADR = IF1CMDMSK; / Point to Command Mask 1 245. CAN0DAT = 0x00B2; / Set to WRITE, & alter all Msg Obj except ID MASK bits 246. CAN0ADR = IF1ARB1; / Point to arbitration1 register 247. CAN0DAT = 0x0000; / Set arbitration1 ID to highest priority 248. CAN0DAT = 0xA000; / Autoincrement to Arb2 high byte: 249. / Set MsgVal bit, no extended ID, Dir = WRITE 250. CAN0DAT = 0x0081; / Msg Cntrl: DLC = 1, remote frame function not enabled 251. CAN0ADR = IF1CMDRQST; / Point to Command Request reg. 252. CAN0DAT = MsgNum; / Select Msg Obj passed into function parameter list 253. / -initiates write to Msg Obj 254. / 3-6 CAN clock cycles to move IF reg contents to the Msg Obj in CAN RAM. 255. 256. 257. /Start CAN 258. void start_CAN (void) 259. 260. /* Calculation of the CAN bit timing : 261. 262. System clock f_sys = 22.1184 MHz/2 = 11.0592 MHz. 263. System clock period t_sys = 1/f_sys = 90.422454 ns. 264. CAN time quantum tq = t_sys (at BRP = 0) 265. 266. Desired bit rate is 1 MBit/s, desired bit time is 1000 ns. 267. Actual bit time = 11 tq = 996.65ns 1000 ns 268. Actual bit rate is 1.005381818 MBit/s = Desired bit rate+0.5381% 269. 270. CAN bus length = 10 m, with 5 ns/m signal delay time. 271. Propagation delay time : 2*(transceiver loop delay + bus line delay) = 400 ns 272. (maximum loop delay between CAN nodes) 273. 274. Prop_Seg = 5 tq = 452 ns ( >= 400 ns). 275. Sync_Seg = 1 tq 276. 277. Phase_seg1 + Phase_Seg2 = (11-6) tq = 5 tq 278. Phase_seg1 <= Phase_Seg2, => Phase_seg1 = 2 tq and Phase_Seg2 = 3 tq 279. SJW = (min(Phase_Seg1, 4) tq = 2 tq 280. 281. TSEG1 = (Prop_Seg + Phase_Seg1 - 1) = 6 282. TSEG2 = (Phase_Seg2 - 1) = 2 283. SJW_p = (SJW - 1) = 1 284. 285. Bit Timing Register = BRP + SJW_p*0x0040 = TSEG1*0x0100 + TSEG2*0x1000 = 2640 286. 287. Clock tolerance df : 288. 289. A: df < min(Phase_Seg1, Phase_Seg2) / (2 * (13*bit_time - Phase_Seg2) 290. B: df < SJW / (20 * bit_time) 291. 292. A: df < 2/(2*(13*11-3) = 1/(141-3) = 1/138 = 0.7246% 293. B: df < 2/(20*11) = 1/110 = 0.9091% 294. 295. Actual clock tolerance is 0.7246% - 0.5381% = 0.1865% (no problem for quartz) 296. */ 297. 298. SFRPAGE = CAN0_PAGE; 299. CAN0CN |= 0x41; / Configuration Change Enable CCE and INIT 300. CAN0ADR = BITREG / Point to Bit Timing register 301. CAN0DAT = 0x2640; / see above 302. 303. CAN0ADR = IF1CMDMSK; / Point to Command Mask 1 304. CAN0DAT = 0x0087; / Config for TX : WRITE to CAN RAM, write data bytes, 305. / set TXrqst/NewDat, clr IntPnd 306. 307. / RX-IF2 operation may interrupt TX-IF1 operation 308. CAN0ADR = IF2CMDMSK; / Point to Command Mask 2 309. CAN0DATL = 0x1F; / Config for RX : READ CAN RAM, read data bytes, 310. / clr NewDat and IntPnd 311. CAN0CN |= 0x06; / Global Int. Enable IE and SIE 312. CAN0CN &= 0x41; / Clear CCE and INIT bits, starts CAN state machine 313. 314. 315. /Transmit CAN frame to turn other node's LED ON 316. void transmit_turn_LED_ON (char MsgNum) 317. 318. SFRPAGE = CAN0_PAGE; / IF1 already set up for TX 319. CAN0ADR = IF1CMDMSK; / Point to Command Mask 1 320. CAN0DAT = 0x0087; / Config to WRITE to CAN RAM, write data bytes, 321. / set TXrqst/NewDat, Clr IntPnd 322. CAN0ADR = IF1DATA1; / Point to 1st byte of Data Field 323. CAN0DATL = 0x11; / Ones signals to turn LED's light ON in data A1 field 324. CAN0ADR = IF1CMDRQST; / Point to Command Request Reg. 325. CAN0DATL = MsgNum; / Move new data for TX to Msg Obj "MsgNum" 326. 327. 328. /Transmit CAN Frame to turn other node's LED OFF 329. void transmit_turn_LED_OFF (char MsgNum) 330. 331. SFRPAGE = CAN0_PAGE; / IF1 already set up for TX 332. CAN0ADR = IF1DATA1; / Point to 1st byte of Data Field 333. CAN0DATL = 0x00; / Zero signals to turn LED's light ON in Data A1 field 334. CAN0ADR = IF1CMDRQST; / Point to Command Request Reg. 335. CAN0DATL = MsgNum; / Move new data for TX to Msg Obj "MsgNum" 336. 337. 338. 339. / Receive Data from the IF2 buffer 340. void receive_data (char MsgNum) 341. 342. char virtual_button; 343. SFRPAGE = CAN0_PAGE; / IF1 already set up for RX 344. CAN0ADR = IF2CMDRQST;/ Point to Command Request Reg. 345. CAN0DATL = MsgNum; / Move new data for RX from Msg Obj "MsgNum" 346. / Move new data to a 347. CAN0ADR = IF2DATA1; / Point to 1st byte of Data Field 348. 349. virtual_button = CAN0DATL; 350. if (virtual_button = 0x11) /Ones is signal from other node to turn LED ON 351. LED = 1; 352. else LED = 0; /Otherwise turn LED OFF (message was one's) 353. 354. 355. / 356. /Interrupt Service Routine 357. / 358. void ISRname (void) interrupt 19 359. 360. status = CAN0STA; 361. if (status&0x10) != 0) 362. / RxOk is set, interrupt caused by reception 363. CAN0STA = (CAN0STA&0xEF)|0x07; / Reset RxOk, set LEC to NoChange 364. /* read message number from CAN INTREG */ 365. receive_data (0x01); / Up to now, we have only one RX message 366. 367. if (status&0x08) != 0) 368. / TxOk is set, interrupt caused by transmision 369. CAN0STA = (CAN0STA&0xF7)|0x07; / Reset TxOk, set LEC to NoChange 370. 371. if (status&0x07) != 0)&&(status&0x07) != 7) 372. / Error interrupt, LEC changed 373. /* error handling ? */ 374. CAN0STA = CAN0STA|0x07; / Set LEC to NoChange 375. 376. 377. /- / F04x_CAN1.c /- / / / DEVICE: C8051F040 / / AUTHOR: LS / / TOOLS: Keil C-compiler and Silicon Labs IDE / / / CAN1.c and CAN2.c are a simple example of configuring a CAN network to / transmit and receive data on a CAN network, and how to move information to / and from CAN RAM message objects. Each C8051F040-TB CAN node is configured / to send a message when it's P3.7 button is depressed/released, with a 0x11 / to indicate the button is pushed, and 0x00 when released. Each node also has / a message object configured to receive messages. The C8051 tests the / received data and will turn on/off the target board's LED. When one target / is loaded with CAN2.c and the other is loaded with CAN1.c, one target / board's push-button will control the other target board's LED, establishing / a simple control link via the CAN bus and can be observed directly on the / target boards. / /