Hallo,
Ich habe eine selbst entworfene Platine mit einem LPC11C14 & SN65HVD234
als CAN Tranceiver drauf. Der LPC11C14 sollte nun ein wenig CAN
Kommunikation mit einem "Master" betreiben (das ist ein LPC1768 - sollte
aber gerade eher nicht von Interesse sein).
Aktuell versuche ich einfach nur den LPC11C14 so weit zu bekommen, dass
er eine CAN Message nach dem Booten sendet (unter Verwendung des ROM
API). Daran scheitere ich und hab nun schon Stunden verbracht, ohne zu
einem Ergebnis zu kommen.
Den Code hab im wesentlichen aus dem NXP LPCWare Sample entnommen. Und
auch mit den Samples die man im Internet findet verglichen - ich finde
keinen relevanten Unterschiede.
Das Problem:
Der LPC11C14 sendet das gewünschte CAN Telegramm die ersten 16x mit
scheinbar sehr kurzen Zeitabständen auf den Bus. Der LPC1768 quittiert
diese dann mit dem nicht sonderlich gut dokumentierten Fehler
"Acknowledge Delimiter". Ab dem 16. Frame macht der LPC11C14 dann
längere Pausen zwischen den Frames und der LPC1768 Empfängt die
Nachricht ganz normal und sendet auch das erwartete ACK auf den Bus.
ABER: der LPC11C14 hört nicht auf, die Nachricht auf den Bus zu senden.
Der sendet die gleiche Nachricht permanent ohne Pause auf den Bus.
Das besonders schräge daran: die CAN-ISR am LPC11C14 wird genau 1x
aufgerufen und meldet dabei den Fehler "Missing ACK" (ISR Auruf ist der
Ch2 Ausschlag jeweils am 2ms Oszi Bild). Die Oszi Bilder sind Aufnahmen
direkt vom CAN Bus, einmal mit dem "Master" (LPC1768) angeschlossen und
einmal ohne (der LPC11C14 ist alleine am Bus).
Ich habe schon viele Varianten ausprobiert - alles ohne Erfolg. Unter
anderem:
- mit ISR/mit Polling
- CPU Takt variiert (10/20/30/40/50 MHz)
- Alles aus dem Projekt entfernt, was ich für den Zweck nicht benötige
(FreeRtos, etc.)
Den RAM Bereich, der vom ROM Treiber API verwendet wird, hab ich in den
Linker settings ausgenommen.
Der Saleae Logic Analyzer zeigt mir (hinter dem Tranceiver am LPC1768
und auch am LPC11C14) auch keinerlei Fehler. Er erkennt die CAN Frames
(Identifier, Daten, CRC) mit jeweils dem fehlerhaften und passendem ACK.
Daraus würde ich einmal schliessen, dass die Tranceiver OK sind.
Der Code (die Standarddinge wie SystemCoreClockUpdate und Board_Init
lass ich mal aussen vor):
1 | void CAN_IRQHandler(void) {
|
2 | Board_PIN_Set(BOARD_PIN_RESERVED_B1, true); // am Oszi ch2
|
3 | DEBUGSTR("I+");
|
4 | LPC_CCAN_API->isr();
|
5 | DEBUGSTR("-\n");
|
6 | Board_PIN_Set(BOARD_PIN_RESERVED_B1, false);
|
7 | }
|
8 |
|
9 | void CAN_Init() {
|
10 | cntRx = cntTx = msgObjBusy = 0;
|
11 |
|
12 | uint32_t CanApiClkInitTable[2];
|
13 | Board_PIN_Set(BOARD_PIN_CAN_TRANCEIVER_ENABLED, true);
|
14 | Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_CAN);
|
15 | baudrateCalculate(CAN_BAUDRATE, CanApiClkInitTable);
|
16 | LPC_CCAN_API->init_can(&CanApiClkInitTable[0], true);
|
17 | LPC_CCAN_API->config_canopen((CCAN_CANOPENCFG_T*) &canOpenConfig);
|
18 |
|
19 | callbacks.CAN_rx = callback_CAN_rx;
|
20 | callbacks.CAN_tx = callback_CAN_tx;
|
21 | callbacks.CAN_error = callback_CAN_error;
|
22 | callbacks.CANOPEN_sdo_read = callback_sdo_read;
|
23 | callbacks.CANOPEN_sdo_req = callback_sdo_req;
|
24 | callbacks.CANOPEN_sdo_seg_read = callback_sdo_seg_read;
|
25 | callbacks.CANOPEN_sdo_seg_write = callback_sdo_seg_write;
|
26 | callbacks.CANOPEN_sdo_write = callback_sdo_write;
|
27 | LPC_CCAN_API->config_calb(&callbacks);
|
28 |
|
29 | NVIC_EnableIRQ(CAN_IRQn);
|
30 | }
|
31 |
|
32 | void sendBootUpMessage(void) {
|
33 | static CCAN_MSG_OBJ_T msg_obj;
|
34 | msg_obj.msgobj = MSGBUFFER_NMT;
|
35 | msg_obj->mode_id = CAN_MSGOBJ_STD | CAN_MSGOBJ_DAT | (0x700 + NODE_ID);
|
36 | msg_obj->mask = 0x0;
|
37 | msg_obj.dlc = 3;
|
38 | msg_obj.data[0] = 0x05;
|
39 | msg_obj.data[1] = 0xff;
|
40 | msg_obj.data[2] = 0x45;
|
41 | LPC_CCAN_API->can_transmit(&msg_obj);
|
42 | }
|
43 |
|
44 | int main(void)
|
45 | {
|
46 | SystemCoreClockUpdate();
|
47 | Board_Init();
|
48 | DEBUGSTR("\033[2J\033[H");
|
49 | DEBUGSTR("*** CAN Node ***\n");
|
50 |
|
51 | CAN_Init();
|
52 | Board_PIN_Set(BOARD_LED_CAN_ACTIVITY, false);
|
53 | Board_PIN_Set(BOARD_LED_CAN_ERROR, false);
|
54 | sendBootUpMessage();
|
55 | while(true) {
|
56 | LPC_CCAN_API->canopen_handler();
|
57 | Board_PIN_Set(BOARD_LED_CAN_ACTIVITY, false);
|
58 | Board_PIN_Set(BOARD_LED_CAN_ERROR, false);
|
59 | }
|
60 | return 1;
|
61 | }
|
Irgendeine Idee, was hier schief läuft? Ich bin so weit, dass ich schon
die Hardware im Verdacht habe ... aber meine bisherige Erfahrung hat
gezeigt, dass es so gut wie nie die Hardware ist ...
Danke für eure Hilfe!
vG Alram