I'm trying to set up a 33333 bus that uses a single wire for can. Took a bit to get the 33333 configured but now it seems to have issues with receiving. Putting a break point at CAN2_SignalObjectEvent's checks never triggers. This set up below is for a dual wire CAN, do I need to combine the RX/TX to make it work for single wire? How would I go about this?
#define CAN_CONTROLLER2 1 // CAN Controller number (can 1 is pa12/11) (can 2 is pb12/13) //------------------------------------------------------------------------------ #define _CAN_Driver_(n) Driver_CAN##n #define CAN_Driver_(n) _CAN_Driver_(n) extern ARM_DRIVER_CAN CAN_Driver_(CAN_CONTROLLER2); #define ptrCAN (&CAN_Driver_(CAN_CONTROLLER2)) uint32_t rx2_obj_idx; uint8_t rx2_data[8]; ARM_CAN_MSG_INFO rx2_msg_info; uint32_t tx2_obj_idx; uint8_t tx2_data[8]; ARM_CAN_MSG_INFO tx2_msg_info; static int ID_Read; static int _TIMEOUT = 100;//each 100 is a second void CAN2_SignalUnitEvent (uint32_t event) { switch (event) { case ARM_CAN_EVENT_UNIT_ACTIVE: break; case ARM_CAN_EVENT_UNIT_WARNING: break; case ARM_CAN_EVENT_UNIT_PASSIVE: break; case ARM_CAN_EVENT_UNIT_BUS_OFF: break; } } void CAN2_SignalObjectEvent (uint32_t obj_idx, uint32_t event) { if (event == ARM_CAN_EVENT_RECEIVE) { // If receive event if (obj_idx == rx2_obj_idx) { // If receive object event ptrCAN->MessageRead(rx2_obj_idx, &rx2_msg_info, rx2_data, 8U); ID_Read = rx2_msg_info.id; printf("single caught:ID_Read &i \n", ID_Read); } } if (event == ARM_CAN_EVENT_SEND_COMPLETE) { if (obj_idx == tx2_obj_idx) { } } } bool CAN2_Initialize (int CAN_BITRATE_NOMINAL) { ARM_CAN_CAPABILITIES can_cap; ARM_CAN_OBJ_CAPABILITIES can_obj_cap; int32_t status; uint32_t i, num_objects, clock; can_cap = ptrCAN->GetCapabilities (); num_objects = can_cap.num_objects; status = ptrCAN->Initialize (CAN2_SignalUnitEvent, CAN2_SignalObjectEvent); if (status != ARM_DRIVER_OK) { return false; } status = ptrCAN->PowerControl (ARM_POWER_FULL); if (status != ARM_DRIVER_OK) { return false; } status = ptrCAN->SetMode (ARM_CAN_MODE_INITIALIZATION); if (status != ARM_DRIVER_OK) { return false; } clock = ptrCAN->GetClock(); if ((clock % (10U*CAN_BITRATE_NOMINAL)) <= 300U) { status = ptrCAN->SetBitrate (ARM_CAN_BITRATE_NOMINAL, CAN_BITRATE_NOMINAL, ARM_CAN_BIT_PROP_SEG (1U) | ARM_CAN_BIT_PHASE_SEG1(5U) | ARM_CAN_BIT_PHASE_SEG2(3U) | ARM_CAN_BIT_SJW (1U)); } else if ((clock % (8U*CAN_BITRATE_NOMINAL)) == 0U) { status = ptrCAN->SetBitrate (ARM_CAN_BITRATE_NOMINAL, CAN_BITRATE_NOMINAL, ARM_CAN_BIT_PROP_SEG (5U) | ARM_CAN_BIT_PHASE_SEG1(1U) | ARM_CAN_BIT_PHASE_SEG2(1U) | ARM_CAN_BIT_SJW (1U)); } else if ((clock % (10U*CAN_BITRATE_NOMINAL)) == 0U) { status = ptrCAN->SetBitrate (ARM_CAN_BITRATE_NOMINAL, CAN_BITRATE_NOMINAL, ARM_CAN_BIT_PROP_SEG (7U) | ARM_CAN_BIT_PHASE_SEG1(1U) | ARM_CAN_BIT_PHASE_SEG2(1U) | ARM_CAN_BIT_SJW (1U)); } else if ((clock % (12U*CAN_BITRATE_NOMINAL)) == 0U) { status = ptrCAN->SetBitrate (ARM_CAN_BITRATE_NOMINAL, CAN_BITRATE_NOMINAL, ARM_CAN_BIT_PROP_SEG (7U) | ARM_CAN_BIT_PHASE_SEG1(2U) | ARM_CAN_BIT_PHASE_SEG2(2U) | ARM_CAN_BIT_SJW (2U)); } else { return false; } if (status != ARM_DRIVER_OK) { return false; } rx2_obj_idx = 0xFFFFFFFFU; tx2_obj_idx = 0xFFFFFFFFU; for (i = 0U; i < num_objects; i++) { can_obj_cap = ptrCAN->ObjectGetCapabilities (i); if ((rx2_obj_idx == 0xFFFFFFFFU) && (can_obj_cap.rx == 1U)) { rx2_obj_idx = i; } else if ((tx2_obj_idx == 0xFFFFFFFFU) && (can_obj_cap.tx == 1U)) { tx2_obj_idx = i; break; } } if ((rx2_obj_idx == 0xFFFFFFFFU) || (tx2_obj_idx == 0xFFFFFFFFU)) { return false; } status = ptrCAN->ObjectSetFilter(rx2_obj_idx, ARM_CAN_FILTER_ID_EXACT_ADD, 0xfff, 0U); if (status != ARM_DRIVER_OK) { return false; } status = ptrCAN->ObjectConfigure(tx2_obj_idx, ARM_CAN_OBJ_TX); if (status != ARM_DRIVER_OK) { return false; } status = ptrCAN->ObjectConfigure(rx2_obj_idx, ARM_CAN_OBJ_RX); if (status != ARM_DRIVER_OK) { return false; } status = ptrCAN->SetMode (ARM_CAN_MODE_NORMAL); if (status != ARM_DRIVER_OK) { return false; } return true; } void CANWrite_MS (int ECU, unsigned char data[], char noReply) { _LEDON (BLUE); osDelay(1);_LEDOFF (BLUE); // sendCompleted=false; if (!noReply) ID_Read=0; memset(&rx2_data, 0U, 8);//clear data. memset(&tx2_msg_info, 0U, sizeof(ARM_CAN_MSG_INFO)); tx2_msg_info.id = ECU; ptrCAN->MessageSend(tx2_obj_idx, &tx2_msg_info, data, 8U); } long CANRead_MS (int ECU, unsigned char data, char position) { memset(&command_Data, 0U, 8); for (int t=0;t <_TIMEOUT;t++) { osDelay(10); printf("read:ID_Read &i \n", ID_Read); if (ID_Read > 0) { if (ECU == 0 ) { memcpy(&command_Data, &rx2_data,8); if (data != 0) { if (command_Data[position] == data) return ID_Read; } else return ID_Read;
Hi,
what transceiver do you have between microcontroller and CAN bus?
Best regards, Milorad
mcp2551 - We have also used this on a pic design with positive results.
And with PIC you also use it on a single-wire bus?
How did you connect CAN_H and CAN_L from transceiver to the single-wire bus?
Yes PIC was ok. As with the PIC ALSO, we had to tie can LO to ground AND can hi to the data pin on the car. Data does send and the car does react correctly. I see the reply on the sniff but the software does not receive the data. I plan to catch the debug in CANx_MessageRead and see if I get an error.
can you perhaps try it on normal CAN, with CAN_H and CAN_L if it works there, as I would expect it to work? If it doesn't work there, I can try to debug it on my end. If it does work with normal CAN, then signal levels and terminations are probably the problem.
By normal do you mean like a two wire?
We have to following modes. Can Hi Can Lo Can single-wire
The Hi and Lo are used for the common car protocols that most all cars support. Normally found on pins 3/11 6/10. These work fine without issues. The single-wire is used on one car in particular at a 33mhz bus. Sending works fine but receiving is hit and miss. When and if a message is caught the application freezes.
Yes, by normal I meant two wire.
As I have seen, there are transceivers for single-wire CAN available as well as www.peak-system.com/PCAN-AU5790.217.0.html High-speed CAN to Single-wire CAN converter, which leads to conclusion that it might not go as simple as you connected two-wire transceiver to a single-wire bus.
It is also probably very much dependant on the whole car system, how many CAN devices are connected to that single wire as well as terminations.
My guess is that hw signals are not good on your two-wire transceiver.
As I do not see any differences on protocol layer between two-wire and single-wire, and if you tested two-wire it has to be physical layer problem.
I do appreciate the insight.
Unless I'm missing something I don't see how it's a car bus issue because the car is doing as it should. Maybe I mis-explained that? The car does accept the data from the single wire and it does reply. The fault lay with the code as far as I can determine with sniffing. Even the analyzer I have shows the data past the transceiver (from arm to transceiver). So the reply packets are getting that far. It could be a weak logic level I guess. The transceiver is powered by 5 volts. My analyzer does have an analog mode I can see what levels it reaches. I'll keep this all in mind and not omit hardware as a possibility. thx.
I'll reach back once I have more information.
As you predicted it was hardware. Turns out my debug unit needed to be grounded to the car for it to work. The difference in ground potentials was upsetting something.
It's nice to hear that you solved the problem!