PBMaster

PBMaster:Communication with the device FDL API

From PBMasterWiki

This section introduces the Application Programming Interface (API) of the Profibus's FDL layer. It ties together with the device drivers and will explain the basic mechanisms to communicate with another station on the Profibus network.

Even thought the communication with another station on the bus could be provided by sending bytes in the raw form directly to the Profibus device, the fact that a developer needs to understand frame structures and even the Profibus specification, make it unsuitable and inconvenient for most application developers. Hence an API was developed to offer a unified and simple mechanism to access the Profibus network.

The API is provided in the form of a library. The library offers a unified system and architecture-independent programming interface handling the transfer between FDL applications and Profibus stations. At the beginning we will take a look at the API functions and their arguments. Later in this section an example using the FDL programming interface will be introduced.

[edit] Interface description

An application wanting to communicate first needs to open the device. Afterwards the communication can be carried out using the read/write operations. At the end the communication should be properly closed using the appropriate function. The library involves the following functions (please consult the manual pages for more details):

pbm_close       - close a connection
pbm_read        - blocking read/receive data from the network
pbm_read_poll   - unblocking read/receive data from the network with
pbm_write       - write/send data to the network
pbm_write_srd   - set up a frame of SRD type and send it to the network
pbm_errno       - get number of the last error

The FDL API functions are intended to be similar to the POSIX's I/O functions:

 /* Open a device. */
 int pbm_open(char *dev);

 /* Close a device. */
 int pbm_close(int fildes);

 /* Read from a device. All arguments are equivalent to the arguments
 * of the read(3) functions. */
 int pbm_read(int fildes, void *buf, int nbyte);

 /* Write to a device. All arguments are equivalent to the arguments
 * of the write(3) functions. */
 int pbm_write(int fildes, const void *buf, int nbyte);

 /* Read from the device with timeout. The first three arguments are the same
 * as arguments of the read() function. Argument timeout is used for the
 * poll() function. */
 int pbm_read_poll(int fildes, void *buf, int nbyte, int timeout);

 /* Return number of the last error */
 int pbm_errno(void);

 /* Write a SRD telegram to the device */
 int pbm_write_srd(int fildes, void *buf, int nbyte, int addr, int dsap, int ssap, int priority);

[edit] FDL API compatibility

The project had a plan to fully support the FDL programming interface by Siemens. In the end, backwards support was not implemented due to the proprietary license of that programming interface. Nonetheless, the project's API partly supports backward compatibility with the Siemens's FDL programming interface. Everything related to Siemens's Request Block should be removed as the library does not work with that structure. Replace the Request Block with a buffer. This backward support is implemented as macros calling the proper API functions described previously. Mapping between the project's API and the API by Siemens is listed below:

SCP_open       - pbm_open
SCP_close      - pbm_close
SCP_send       - pbm_write
SCP_receive    - pbm_read_poll
SCP_get_errno  - pbm_errno

[edit]

The following code shows a simple example using the FDL programming interface. The program sends parameterization and configuration to a slave station, an ET200B by Siemens, then it turns on the first digital output of this slave station.

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <pbmcore.h>
#include <pbm.h>

#define ET200B          18 /* slave address */

/* Set parameters of Siemens ET200B */
void et200b_set_conf(int fd)
{
        /* parametrization */
        unsigned char param[] = { 0xb0, 0x08, 0x09, 0x0b, 0x00, 0x0f,
                                        0,    0,    0,    0,    0,    0 };
        /* configuration */
        unsigned char conf[] = { 0x20, 0x12 };

        /* send parametrization */
        pbm_write_srd(fd, param, sizeof(param),
                        ET200B, SAP_SET_PARAM, SAP_CHECK_CFG, PB_MSG_HIGH);

        /* send configuration */
        pbm_write_srd(fd, conf, sizeof(conf),
                        ET200B, SAP_CHECK_CFG, SAP_CHECK_CFG, PB_MSG_HIGH);
}

/* Turn on digital output */
void et200b_on(int fd, int output_num)
{
        unsigned char q[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

        /* set digital output */
        pbm_write_srd(fd, &q[output_num], 1,
                        ET200B, SAP_DEFAULT, SAP_DEFAULT, PB_MSG_HIGH);
}

int main(int argc, char **argv)
{
        int fd;

        fd = pbm_open("/dev/pbmaster0");
        if (fd < 0)
                exit(1);

        et200b_set_conf(fd);
        et200b_on(fd, 0);

        pbm_close(fd);

        return 0;
}