PBMaster:Communication with the device
From PBMasterWiki
- The communication with another station on the bus is possible through the character device (for instance /dev/pbmaster0). You can manipulate with the device like a common file. Frames of requests are written directly into this device. On the contrary responses are read in the same way.
- The following program illustrates the way it can be done. The program sends parametrization to slave station ET200B by Siemens. Then it turns on and off periodically outputs of the slave. Responses are displayed to the standard output. You can obtain the program in download section.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#define DEV "/dev/pbmaster"
#define DEV_NAME_LEN 20
#define FDL_MAX_FLEN 252
#define ET200B 18
char dev_name[DEV_NAME_LEN];
/* Set parameters of Siemens ET200B */
void et200b_set_conf(int fd)
{
/* parametrization */
unsigned char param[] = { 0x68, 0x11, 0x11, 0x68,
0x80 | ET200B, 0x80,
0x4d, 61, 62,
0xb0, 0x08, 0x09, 0x0b, 0x00, 0x0f,
0, 0, 0, 0, 0, 0,
0x00, 0x16 };
/* configuration */
unsigned char conf[] = { 0x68, 0x07, 0x07, 0x68,
0x80 | ET200B, 0x80,
0x4d, 62, 62,
0x20, 0x12,
0x00, 0x16 };
/* send parametrization */
write(fd, param, sizeof(param));
/* send configuration */
write(fd, conf, sizeof(conf));
}
/* Turn on digital output */
int et200b_on(int fd, int output_num)
{
unsigned char q[] = { 0x11, 0x33, 0x77, 0xff, 0xee, 0xcc, 0x88, 0x00};
/*unsigned char q2[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};*/
unsigned char conf[] = { 0x68, 0x04, 0x04, 0x68,
ET200B, 0x00,
0x5d, q[output_num],
0x00, 0x16 };
int rv = 0;
/* send configuration */
rv = write(fd, conf, sizeof(conf));
return rv;
}
/* Thread process. Do the job. */
void *process(void *a) {
struct timeval tv;
unsigned char frm_buf[FDL_MAX_FLEN];
unsigned char last_frm_buf[FDL_MAX_FLEN];
ssize_t frm_len;
ssize_t last_frm_len = 0;
fd_set fdset_read, fdset_write, fdset_except;
int fd, num = 0, cnt = 0;
int i, rv = 0;
fd = open(dev_name, O_RDWR);
if (fd < 0) {
printf("Unable to open file: %s\n", dev_name);
exit(1);
}
FD_SET(fd, &fdset_read);
FD_ZERO(&fdset_write);
FD_ZERO(&fdset_except);
tv.tv_sec = 5;
tv.tv_usec = 0;
if (select(fd+1, &fdset_read, &fdset_write, &fdset_except, &tv) == -1)
printf("unable to select\n");
/* set parameters */
et200b_set_conf(fd);
while (1) {
/* read from device */
if (FD_ISSET(fd, &fdset_read)) {
frm_len = read(fd, frm_buf, FDL_MAX_FLEN);
if (frm_len > 0) {
if (frm_len != last_frm_len ||
memcmp(last_frm_buf, frm_buf, frm_len)) {
if (cnt)
printf("\n");
memcpy(last_frm_buf, frm_buf, frm_len);
last_frm_len = frm_len;
printf("received(%d): ", frm_len);
for (i=0; i<frm_len; i++)
printf("0x%02x ", frm_buf[i]);
printf("\n");
cnt = 0;
} else {
cnt++;
printf("last message repeated %d "
"times\t\r", cnt);
}
}
} else {
printf("timeout expired\n");
}
/* turn on specified output */
rv = et200b_on(fd, num);
if (rv > 0) {
num++;
num %= 8;
}
usleep(500000);
}
close(fd);
}
/* Start thread */
void start_thread() {
pthread_t on_off;
int rc;
void *rv;
rc = pthread_create(&on_off, NULL, process, "A");
if (rc != 0)
printf("Failed to create thread %d\n", rc);
rc = pthread_join(on_off, &rv);
if (rc != 0)
printf("Failed to join thread %d\n", rc);
}
void print_usage(char *prog_name)
{
printf( "PBMaster test program. "
"Change periodically output of ET200B\n");
printf( "Usage: %s <dev_minor>\n", prog_name);
printf( "\n");
exit(0);
}
int main(int argc, char **argv)
{
if (argc > 2)
print_usage(argv[0]);
/* minor number defined */
if (argc == 2)
sprintf(dev_name, "%s%s", DEV, argv[1]);
else
sprintf(dev_name, "%s%d", DEV, 0);
/* start thread and do the job */
start_thread();
return 0;
}