Hallo,
ich versuche gerade verzweifelt den CAN-Bus zum Laufen zu bringen mit
einem STM32F103R4. Dazu habe ich mir den Beispielcode von Keil
(http://www.keil.com/download/docs/351.asp) angeschaut. Leider ist schon
während der Initialisierung schluss.
Wenn ich nämlich aus dem "initialization mode" in den "normal mode"
wechseln will, also das INRQ Bit rücksetze, setzt mir die hardware das
INAK bit nicht zurück. Das passiert sowohl wenn ich den Beispielcode
ausführe als auch meinen eigenen.
Hier der Auszug aus dem Keil-Code:
1 | void CAN_setup (void) {
|
2 | unsigned int brp = stm32_GetPCLK1();
|
3 |
|
4 | RCC->APB1ENR |= RCC_APB1ENR_CANEN; // enable clock for CAN
|
5 |
|
6 | // Note: MCBSTM32 uses PB8 and PB9 for CAN
|
7 | RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; // enable clock for Alternate Function
|
8 | AFIO->MAPR &= 0xFFFF9FFF; // reset CAN remap
|
9 | AFIO->MAPR |= 0x00004000; // set CAN remap, use PB8, PB9
|
10 |
|
11 | RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; // enable clock for GPIO B
|
12 | GPIOB->CRH &= ~(0x0F<<0);
|
13 | GPIOB->CRH |= (0x08<<0); // CAN RX pin PB.8 input push pull
|
14 |
|
15 | GPIOB->CRH &= ~(0x0F<<4);
|
16 | GPIOB->CRH |= (0x0B<<4); // CAN TX pin PB.9 alternate output push pull
|
17 |
|
18 | NVIC->ISER[0] |= (1 << (USB_HP_CAN_TX_IRQChannel & 0x1F));// enable interrupt
|
19 | NVIC->ISER[0] |= (1 << (USB_LP_CAN_RX0_IRQChannel & 0x1F));// enable interrupt
|
20 |
|
21 | CAN->MCR = (CAN_MCR_NART | CAN_MCR_INRQ); // init mode, disable auto. retransmission
|
22 | // Note: only FIFO 0, transmit mailbox 0 used
|
23 | CAN->IER = (CAN_IER_FMPIE0 | CAN_IER_TMEIE); // FIFO 0 msg pending, Transmit mbx empty
|
24 |
|
25 | /* Note: this calculations fit for PCLK1 = 36MHz */
|
26 | brp = (brp / 18) / 500000; // baudrate is set to 500k bit/s
|
27 |
|
28 | /* set BTR register so that sample point is at about 72% bit time from bit start */
|
29 | /* TSEG1 = 12, TSEG2 = 5, SJW = 4 => 1 CAN bit = 18 TQ, sample at 72% */
|
30 | CAN->BTR &= ~((( 0x03) << 24) | (( 0x07) << 20) | (( 0x0F) << 16) | ( 0x1FF));
|
31 | CAN->BTR |= ((((4-1) & 0x03) << 24) | (((5-1) & 0x07) << 20) | (((12-1) & 0x0F) << 16) | ((brp-1) & 0x1FF));
|
32 | }
|
33 |
|
34 |
|
35 |
|
36 |
|
37 | void CAN_testmode (unsigned int testmode) {
|
38 |
|
39 | CAN->BTR &= ~(CAN_BTR_SILM | CAN_BTR_LBKM); // set testmode
|
40 | CAN->BTR |= (testmode & (CAN_BTR_SILM | CAN_BTR_LBKM));
|
41 | }
|
42 |
|
43 |
|
44 | void CAN_start (void) {
|
45 |
|
46 | CAN->MCR &= ~CAN_MCR_INRQ; // normal operating mode, reset INRQ
|
47 | while (CAN->MSR & CAN_MCR_INRQ);
|
48 |
|
49 | }
|
Die Funktionen werden nacheinander aufgerufen. In CAN_start bleibt er
dann endlos in der while-Schleife hängen, weil eben das INAK bit im MSR
Register nicht gecleared wird.
Ich hoffe mir kann jemand helfen, ich kanns mir jedenfalls nicht
erklären.
Gruß, Alex