"Yingchuang em335x industrial control motherboard uses cortex-a8 and wec7 operating systems. Taking the CD routine of em335x industrial control motherboard as an example, this paper briefly introduces how C and c# code call can driver on wec7 platform to realize can communication.
C code
Customers can add em335x in routines in their own projects_ Can. H and em335x_ Can.cpp, use the em335x encapsulated inside_ Can class.
#include 'EM335X_ CAN.h'
EM335X_ CAN can;
Turn on can
Call em335x_ Opencan method of can class. For example, open Can1 with 250kbps (only Can1 by default).
DWORD dwCanNo = 1;
DWORD dwBaudRate = 250000;
can.OpenCAN( dwCanNo, dwBaud );
Turn off can
Call em335x_ Closecan method of can class.
can.CloseCAN( );
Send can packet
Call em335x_ Writecan method of can class.
can.WriteCAN(&canmsg );
Receive can packet
A separate thread is used in the routine to receive. Then pass the received data to the packagepro function for processing. Parameter 1 is the data buffer pointer, and parameter 2 is the length of the data.
int EM335X_ CAN::PackagePro(char* pBuf , int len)
Users can add corresponding logic codes according to specific application requirements.
Can send and receive packet structure definition
Both can sending and can receiving are sent and received in data packets. The size of a single packet is 16 bytes, and the structure is defined as follows:
typedef struct {
CAN_ ID id;
BYTE dlc;
BYTE data[8];
}CAN_ MESSAGE,*PCAN_ MESSAGE;
ID, one can_ ID, which is defined in the following description.
DLC, 1 byte, data length, value 0-8;
Data, 8 bytes, transmitted data.
Note: because of the alignment of the structure, the size of the structure is 16 bytes.
CAN_ The ID structure is an integer, 32 bits, which is used to record the ID information required for can communication.
typedef struct{
unsigned int id:29;
unsigned int reserved:1;
unsigned int remote:1;
unsigned int extended:1;
}CAN_ ID;
ID, the lower 29 bits of the structure integer, indicating the ID number.
Reserved, the 30th bit, is used to mark whether it is a received packet or a sent packet. It can be set to 0 by default.
Remote, the 31st bit, is used to set whether it is a data frame or a remote frame. 0 is the data frame and 1 is the remote frame.
Extended, the 32nd bit, used to set whether it is a standard frame or an extended frame. 0 is the standard frame and 1 is the extended frame.
Can filter condition filter setting
Em335x also supports packet filtering. Setting filter can enable can to receive only the packets it needs.
Call em335x_ The setfilter method of can class can add a filter condition or delete an existing filter condition. For example:
bResult = can.SetFilter( &Filter, FALSE );
The first parameter is the filter condition parameter, which is a can_ The structure of filter is described below. If the second parameter is false, it means to add the filter condition; if it is true, it means to delete the existing filter condition.
When there are multiple filter conditions, the data packet can be received as long as it can meet any filter condition.
Can filter condition filter structure definition
CAN_ Filter structure is defined as follows: (can)_ Definition of ID structure (described in the packet structure above)
typedef struct {
CAN_ ID id;
CAN_ ID mask;
}CAN_ FILTER,*PCAN_ FILTER;
The filtering logic here is as follows:
Suppose the ID in the received packet is recorded as ID_ Message, and the ID and mask in the filter parameter in the filter condition meet the condition: (ID)_ Message & mask = = (ID & mask), then the packet can be received, that is, the mask represents the bits to be compared. If the ID bits of the packet are the same as those in the filter setting, then the packet can be received.
For example:
Mask of a filter = 0x03, that is, binary b0000 0011, that is, the last two bits need to be compared.
ID of filter = 0x02, i.e. binary b0000 0010.
If the last two bits of the packet ID are 10, the packet can be received through the filter conditions.
Packet id = 0xf7, i.e. binary b1111 0111, cannot be received.
Packet id = 0xe6, i.e. binary b1110 0110, can be received.
Packet id = 0x2e, i.e. binary b0010 1110, can be received.
Can loopback mode setting
The loopback mode is to select whether the data packets sent by the board can be received at the same time.
Call em335x_ Can class can_ Loopback method. If you want to receive the can packet sent by yourself, set the second parameter to true. If you want to turn off the loopback function, the second parameter is set to false.
Can other commands
EM335X_ Cancommand method of can class can control can reset, start and stop.
BOOL CanCommand( CAN_ COMMAND eCommand);
Parameter can_ Command is an enumeration type. Its definition is as follows: stop = 0, start = 1, reset = 3:
typedef enum {
STOP,
START,
RESET
} CAN_ COMMAND;
1. Reset can
Can reset resets each register value in the can drive and performs relevant initialization operations.
When opening can, this function has been called in opencan function to realize can reset. The user can decide when to perform can reset according to the actual situation of his application.
2. Start can
After setting the can baud rate, loopback, filter and other parameters, the can driver thread does not start immediately. It needs to execute the can start before the can thread starts to work.
When CAN is opened, the OpenCAN function is called CAN after the parameter is set. Users can decide when to execute the function according to the actual situation of their application. For example, when the can receiving thread receives an error event, you can add the call to stop can and restart can in the error handling code.
3. Stop can
Stopping can will close the can driver thread. When closing can, the closecan function calls can to stop.
C# code
The C # code refers to the C code and is slightly adjusted relative to the C interface. We also encapsulate a can class in em335x_ CAN_ Api.cs to facilitate customers to add to their own projects.
Turn on can
The process of opening can is: open the can device, obtain the device handle, initialize can, then set the parameters of can (baud rate, loopback mode), create the can receiving thread, finally start can, and then the can driving thread starts to work.
1. Turn on the can device
int CanNo = 1;
hCAN = CAN.OpenCAN(CanNo);
2. Reset can
Execute reset operation to initialize can.
bRet = CAN.CAN_ Command(hCAN, (uint)CAN_ COMMAND.RESET);
3. Set baud rate
Set the baud rate of can, such as 250kbps:
uBaud = 250000;
bRet = CAN.CAN_ SetBaudRate(hCAN, uBaud);
4. Set can loopback mode
If you want to receive the can packet sent by yourself, you can set the second parameter to 1. The function is temporarily turned off in the routine, so set 0.
bRet = CAN.CAN_ Loopback(hCAN, 0);
5. Create a separate receive thread
When receiving, the function needs to wait for can receiving events. It is in a blocked state and should not be written directly in the main thread. Here, a receiving thread is added to deal with can data reception.
Create thread:
revThread = new Thread(new ThreadStart(BeginReceive));
threadStop = false;
revThread.Start();// Start the waitformessage thread
6. Start can
When ready, you can start the can device.
bRet = CAN.CAN_ Command(hCAN, (uint)CAN_ COMMAND.START);
Turn off can
It mainly ends the receiving thread, stops can, and closes the can device handle.
revThread.Abort();// End thread
revThread.Join();
bRet = CAN.CAN_ Command(hCAN, (uint)CAN_ COMMAND.STOP);
bRet = CAN.CloseCAN(hCAN);
Send can packet
Call WriteFile to send can packet.
bRet = CAN.WriteFile(hCAN, ref pktSend, CAN.sizePacket, ref uLen, 0);
Receive can packet
Call readfile to send can packet.
bResult = CAN.ReadFile(hCAN, ref pktRev, CAN.sizePacket, ref uLen, 0);
Can send and receive packet structure definition
Whether can sends WriteFile or can receives readfile, it is sent and received in packets. The size of a single packet is 16 bytes, and the structure is defined as follows:
[StructLayout(LayoutKind.Explicit, Size = 16)]
public struct CAN_ MESSAGE
{
[FieldOffset(0)]
public uint id;
[FieldOffset(4)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
public byte[] data;// Data byte
}
ID is an integer, 4 bytes and 32 bits, which is used to record the ID information required for can communication.
The lower 29 bits of ID represent the ID number.
The 30th bit of ID is used to mark whether it is a received packet or a transmitted packet.
The 31st bit of ID is used to set whether it is a data frame or a remote frame. If this bit is 0, it is a data frame, and if this bit is 1, it is a remote frame.
The 32nd bit of ID is used to set whether it is a standard frame or an extended frame. If this bit is 0, it is the standard frame, and if this bit is 1, it is the extended frame.
Data is a 12 byte array.
Data [0] is the length of data in can data packet, with a value of 0-8;
Data [1] - Data [8], 8 bytes, data transmitted in can data packet.
Data [9] - Data [11] not used.
Note: the main reason why the structure is designed in this way is that it needs to interface with the driver of C code, so it will be more efficient.
For example, we want to send a standard data frame with ID 5 and data length 3, which are 0x01, 0x02 and 0x03 respectively. The code is as follows:
CAN_ MESSAGE pktSend = new CAN_ MESSAGE();
pktSend.id = 5;
//If it is a data frame, it will remain unchanged, and if it is a remote frame, it will remain unchanged
//pktSend.id = pktSend.id | 0x20000000;// remote
//If it is a standard frame, it will remain unchanged, and if it is an extended frame, it will remain unchanged
//pktSend.id = pktSend.id | 0x40000000;// extended
pktSend.data[0] = 3;
pktSend.data[1] = 0x01;
pktSend.data[2] = 0x02;
pktSend.data[3] = 0x03;
For example, we want to send an extended frame with ID 55 and data length of 6, which are 0x04, 0x04, 0x04, 0x05, 0x05 and 0x05 respectively. The code is as follows:
CAN_ MESSAGE pktSend = new CA
Our other product: