In recent years, in order to quickly deploy the substation, the electric power industry has adopted the method of building the whole substation: the internal equipment of the substation is installed and debugged in the production base, leaving only the interface with the outside world, and the whole substation can be put into operation after installation and simple debugging. Its internal devices communicate through CAN bus, and the original monitoring software of the system is based on DOS system, so it is difficult to maintain and debug, so we want to seek more convenient and friendly system support. After comparison, Windows CE. Net, the most popular embedded operating system in the market, becomes the final choice. Microsoft’s latest product windows CE.NET It provides the means of end-to-end development and debugging. Without dismantling the device, it can log in to Windows CE through Telnet for debugging and maintenance. The system itself is redesigned for the embedded market, including everything needed to create a customized device based on Windows CE. So we need to transplant the original DOS program to WindowsCE.NET But each hardware manufacturer has not provided can communication card in windows CE.NET Under the driver, so the development of windows CE.NET The can card driver based on can has become a key link in the implementation of the project.

This paper mainly analyzes the dual port can card pcm3680 of Advantech, and introduces the application of pcm3680 in WindowsCE.ENT The method of developing the bottom device driver under the system and the example of CAN communication are provided.

1 can bus communication protocol and can communication card

Can bus is a serial data communication protocol developed by Bosch Company of Germany in the early 1980s to solve the data exchange between numerous control and test instruments in modern automobiles. It is a multi master bus, instead of the traditional station address coding, it encodes the communication data block. This method makes the number of nodes in the network unlimited in theory. The 29 bit identification code in the extended format can define 229 different data blocks.

In this project, Advantech’s pcm3680 is used, which is a dual port can bus communication card of embedded PC104; the CAN controller adopts Philips’s independent can controller SJA1000 chip; the can transceiver adopts Philips’s p82c250, which can operate two can networks at the same time, providing a transmission speed of up to 1MB / s. Pcm3680 supports a wide range of interrupts: interrupts 3, 4, 5, 6, 7, 9, 10, 11, 12, 15. At the same time, 1000V photoelectric isolation provides high system reliability. In the communication of can card, many registers in can controller are used. The meaning and function of each register can refer to the instruction of control chip. Figure 1 lists the most important register structures used in driver design.

Design of bottom layer function of can card driver

The design of can driver is a real driver in the lower kernel layer of Windows CE operating system, which is located in the OEM adaptation layer (oal) layer, rather than the serial operation in the main program. In the device manager of Windows CE, you can see Can1 and can2 ports, and you can check whether they work normally or not and configure them. Such as interrupt number and I / O address.

2.1 can card register read / write function

The communication of can card is carried out by operating can controller on CAN card. There are many registers in can controller, such as control register, command register, status register, interrupt register and so on. The behavior of can card can be detected and controlled by reading and writing the command status words in these registers. On Windows CE.NET The physical address assigned by can card is mapped to logical address by calling the API function haltranslatebusaddress in DOK. In this way, each register corresponds to the offset address of the can card base address. Therefore, the reading and writing of the register is converted into the reading and writing of the memory address. The following is the read / write function of can card register:

*Read one byte of data in the address with offset of off_ HW_ OPEN_ INFO hCan,DWORD off)


return hCan-》lpCanHWInfo-》lpCanObj-》lpMappedBaseAddr[off];

*Write a byte of data to the address with offset of off, inline void canw (lpcan)_ HW_ OPEN_ INFO hCan,DWORD off,BYTE val)




Parameter lpcan_ HW_ OPEN_ Info defines the data structure of can card, in which lpmappebaseaddr [0] represents the base address after mapping, lpmappedbaseaddr [1] is the address of base address + 1, and the corresponding register of can card is the command register. All registers on CAN card can be operated by the above two functions.

2.2 can card initialization

The controller of can card is complex, so it is necessary to confirm the correctness of hardware information and initialize the registers before communication. The basic flow of initialization function is shown in Figure 3.

The first step is to check the correctness of port number and hardware information, mainly whether the can card interrupt number is valid.

Second, set the default parameters of can card


{0x00, 0xff, 0x03, 0x1c}; / * set the default baud rate to 125kbps*/

DWORD dwThreadID =0;

PHYSICAL_ADDRESS phyAddr={hwInfo-》dwIOBaseAddr *16,0 };

In the third card, wince API function localalloc is used to allocate buffer for data structure used in can card driver; haltranslatebusaddress and mmmapiospace function are used to map I / O address to provide virtual address of direct access device


goto _ExiTInit;




goto _ExiTInit;

If the allocation of memory or mapping logical address fails, exit the initialization program, can card initialization fails.

The fourth step is to initialize the read-write attribute, sharing mode, read timeout and the base address of the second can port.

The fifth step is to create can card events and data receiving events: hcan – “lpcanhwinfo -” hcanevent = create event (null, false, false, null);


The sixth step is initialization interrupt. If the can card has reset request, exit the initialization program. After setting the interrupt, start the data receiving thread, set the thread priority to continue the thread processing; finally, configure the can card parameters to enter the normal operation state.

2.3 can card information sending can card information sending is divided into two steps. After checking the basic information of can card, the ID number of transmit buffer is set first. The ID number of can standard mode is 11 bits. The high 8 bits of ID number are stored in offset address 10, the low 3 bits of ID number are stored in the high 3 bits of offset address 11, and the remaining 5 bits are RTR bit (remote transmission request bit) and data length respectively. The processed data is written to the corresponding offset address through the canw function. After setting the corresponding address data, the data of offset address 12-19 is collected and stored in the array through the loop. Then, set the transmission request of can card to allow and continuously detect the change of status register. When the transmission buffer full flag or the transmission end flag is 1, the program will be sent out to complete a data acquisition. The registers of the transfer buffer are listed in Table 1.

Design of pcm3680 dual port can bus communication card based on SJA1000 and p82c250

The implementation of can message sending function is as follows:

BOOL CAN_SendMessage(LPCAN_HW_OPEN_INFO hCan,LPCanCardMessageBuflpMsg)



Assert (hcan lpmsg lpmsg – “dwmessage len = 8); / * error proofing*/

if(0= =(hCan-》dwAccessCode GENERIC_WRITE))

return FALSE;

:: EnterCriTIcalSection(hCan-》lpCanHWInfo-》

Transmitcritsec); / * enter the critical region*/

BYTE byV=static_castBYTE》(1pMsg-》dwMsgID》》3);

Canw (hcan, 10, BYV); / * set the ID value 8 bits higher*/

byV=static_castBYTE》=((lpMsg-》dwMsgID 7)5);

if(lpMsg-》bRTR) byV|=0x10;


Canw (hcan, 11, BYV); / * set ID value lower 3 bits, RTR and data length*/

for(UINT i=0;lpMsg-》dwMessageLen;++i)



}/ * collect data*/

Canw (hcan, 1, 1); / * reset transfer request*/



If (BYV 0x40) / * the transmission buffer is full, exit*/


If (BYV 0x8) {/ * transmission ends, return correctly and exit*/

bSuc = TRUE;



:: LeaveCriticalSection (hcan – 、 lpcanhwinfo – 、 transmitcrititsec); / * leave the critical region*/

return bSuc;


2.4 can card information receiving

The information receiving of can card is the reverse process of sending. When the receive buffer flag is 1, it means that the buffer is full and can receive data. After receiving the data into the array, the receive buffer is released, and then the received data is decomposed and stored in the can card information buffer structure. The register structure of the receive buffer is listed in Table 2.

The implementation of can message receiving function is as follows:


HCan,OUT LPCanCardMessageBuflpMsg)


If (canr (hcan, 2) 1) {/ * judge whether the receive buffer is full*/

for(UINT i=0;i10;++i)

Recvbuf [i] = canr (hcan, 20 + I); / * store data in temporary buffer*/

Canw (hcan, 1, 4); / * release receive buffer*/

Lpmsg – “dwmsgid = recvbuf [0] 3; / * take out the upper 8 bits of ID*/

BYTE byV =recvBuf[1];

Lpmsg – > dwmsgid + = BYV > > 5; / * take out the lower 3 bits of ID, and then merge with the upper 8 bits*/

LpMsg-》bRTR =byV 0x10? True: / * returns the RTR status*/

Lpmsg – “dwmessage len = BYV 0xf; / * return data length*/




{+ + hcan – > “lpcanhwinfo – >” dwerrormsgcount;} / * no data received, error count plus 1*/


Receivecritsec); / * leave the critical region*/

Return bSuc;


2.5 can card event handling

Can card event handling function is a very important part of can card driver. The driver design requires the function of message notification. When an event occurs, it can capture the event in time and process the message.

The following is the implementation of the event handling function:

staric DWORD WINAPI CAN_EventHanle(LPVOID lpParam)




CanCardMessageBuf bufMsg;


{/ * wait for the can card message to generate, and then process it*/


If (hcan – > “lpcanhwinfo – >” bkillcanthread) break; / * if the can thread is closed, it will be interrupted*/

if(CAN_ Recvmessage (hcan, hufmsg)) {/ * after receiving data correctly*/

CAN_ Recvbufpush (hcan, bufmsg);} / * press data into buffer*/

Byte BYV = canr (hcan, 3); / * read register 3 and write it immediately*/

Canw (hcan, 3, BYV); / * can get every interrupt*/


}/ * this interrupt ends, waiting for the next interrupt*/

return 0;


2.6 other functions

In order to provide more functions and use can card to communicate more conveniently, some functions such as can are designed in the driver of can card_ Can card information configuration and can_ Recvbufpop is used to process receive buffer and can_ Reset is used to reset can card and checkhwinfo is used to check hardware information. These functions provide the setting, checking and other functions of CAN communication card, which will not be detailed here.

3 can card driver package design

Although the bottom driver function of can card has complete function, it is more complex for users, and ordinary users do not need to understand the underlying implementation mechanism. In order to make it easy to use, the driver of can card is encapsulated. Five functions such as canopenfile and cansendmsg are provided for CAN bus communication, which are provided to users in the form of dynamic link library (DLL). The encapsulation functions and functions are as follows:

*Canopenfile; initializes and opens a port of can card.

*Canclosefile; closes the can card port opened by canopenfile.

*Canrecvmsg; to receive can card data, it must have generic when opening can card_ Read permission.

*Cansendmsg; send data through can card. You must have generic when opening can card_ Write permission.

*Caniocontrol: set or obtain the I / O parameters of can card. The supported I / O controls include: IOCTL_ CAN_ CONFIG,IOCTL_ CAN_ RESET,IOCTL_ CAN_ TIMEOUT,IOCTL_ CAN_ SENDREADY,IOCTL_ CAN_ RECVREADY。

The following is the code of cansendmsg function implementation:

BOOL CanSendMSg(





!lpMsg||lpMsg-》dwMessageLen》8)return FALSE;

return CAN_SendMessage(LPCAN_HW_OPEN_INFO)


This function is realized by encapsulating the bottom driver function SendMessage of can card, which makes the five functions in the function set more convenient for users.


The software environment is: Windows 2000 professional, embedded visual c + + 4.0, and the lower computer WinCE.NET The corresponding SDK is compiled and generated when Platform Builder 4.0 is used to customize wince. The hardware of the lower computer is Advantech’s embedded PC104 motherboard pcm3346n, and the operating system is WinCE.ENT .

The driver designed and developed in this paper has been successfully applied in the substation project of Huairou in Beijing. The communication of can card is stable, and the system is running smoothly WINCE.NET The system is reliable in operation and ensures the smooth implementation of the project.

Editor in charge: GT

Leave a Reply

Your email address will not be published. Required fields are marked *