#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <termios.h> #include <sys/ioctl.h> #include <string.h> #define CRTSCTS 020000000000 /* flow control */ #define KDM96XX_HEADER 0x60 #define KDM96XX_CONTROL_CLA 0x43 #define KDM96XX_CONTROL_EJECT_CMD 0x31 #define KDM96XX_CONTROL_PRESPOS_CMD 0x32 #define KDM96XX_CONTROL_INIT_CMD 0x33 #define KDM96XX_CONTROL_GETVER_CMD 0x34 #define KDM96XX_MSCARD_CLA 0x4D #define KDM96XX_MSCARD_FREAD_CMD 0x31 #define KDM96XX_MSCARD_BREAD_CMD 0x32 #define KDM96XX_MSCARD_READCLEAR_CMD 0x33 char calculate_xor(char * data, int len) { char rslt = 0; int i; for(i=0; i<len; i++) rslt ^= data[i]; return rslt; } int set_interface_attribs (int fd, int speed, int parity, float timeoutSec) { struct termios tty; memset (&tty, 0, sizeof tty); if (tcgetattr (fd, &tty) != 0) { printf("error from tcgetattr"); return -1; } cfsetospeed (&tty, speed); cfsetispeed (&tty, speed); tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars // disable IGNBRK for mismatched speed tests; otherwise receive break // as \000 chars tty.c_iflag &= ~IGNBRK; // ignore break signal tty.c_lflag = 0; // no signaling chars, no echo, // no canonical processing tty.c_oflag = 0; // no remapping, no delays tty.c_cc[VMIN] = 0; // read doesn't block tty.c_cc[VTIME] = (int)(timeoutSec * 10.0);// read timeout in sec tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls, // enable reading tty.c_cflag &= ~(PARENB | PARODD); // shut off parity tty.c_cflag |= parity; tty.c_cflag &= ~CSTOPB; //tty.c_cflag &= ~CRTSCTS; if (tcsetattr(fd, TCSANOW, &tty) != 0) { printf("error from tcsetattr"); return -1; } return 0; } void set_blocking (int fd, int should_block, float timeoutSec) { struct termios tty; memset (&tty, 0, sizeof tty); if (tcgetattr (fd, &tty) != 0) { printf ("error from tcgetattr"); return; } tty.c_cc[VMIN] = should_block ? 1 : 0; tty.c_cc[VTIME] = (int)(timeoutSec * 10.0); // read timeout in sec if (tcsetattr (fd, TCSANOW, &tty) != 0) printf("error setting term attributes"); } void show_char_vect_as_hex(char * buf, int size) { printf("["); int i; for(i=0; i<size; i++) { printf("x%02x", (unsigned int) buf[i]); if(i != size-1) printf(", "); } printf("]"); } void show_char_vect_as_dec(char * buf, int size) { printf("["); int i; for(i=0; i<size; i++) { printf("%02d", (unsigned int) buf[i]); if(i != size-1) printf(", "); } printf("]"); } void send_init_cmd(int fd) { int len = 6; char data[len]; data[0] = KDM96XX_HEADER;//header data[1] = 0x00; data[2] = 0x02;//data field size data[3] = KDM96XX_CONTROL_CLA;//instructions class data[4] = KDM96XX_CONTROL_INIT_CMD;//command data[5] = calculate_xor(data, len-1); int rslt = write(fd, data, len); printf("\n'init', sent bytes: "); show_char_vect_as_hex(data, len); if(rslt < 0) { printf(" write error!!"); } } void send_getver_cmd(int fd) { int len = 6; char data[len]; data[0] = KDM96XX_HEADER;//header data[1] = 0x00; data[2] = 0x02;//data field size data[3] = KDM96XX_CONTROL_CLA;//instructions class data[4] = KDM96XX_CONTROL_GETVER_CMD; //command data[5] = calculate_xor(data, len-1); int rslt = write(fd, data, len); printf("\n'getver', sent bytes: "); show_char_vect_as_hex(data, len); if(rslt < 0) { printf(" write error!!"); } } void send_report_the_presence_and_pos_cmd(int fd) { int len = 6; char data[len]; data[0] = KDM96XX_HEADER;//header data[1] = 0x00; data[2] = 0x02;//data field size data[3] = KDM96XX_CONTROL_CLA;//instructions class data[4] = KDM96XX_CONTROL_PRESPOS_CMD;//command data[5] = calculate_xor(data, len-1); int rslt = write(fd, data, len); if(rslt < 0) { printf(" send_report_the_presence_and_pos_cmd(), write error\n"); return; } printf("\n'presence and position', sent bytes: "); show_char_vect_as_hex(data, len); } void send_fread_cmd(int fd) { int len = 6; char data[len]; data[0] = KDM96XX_HEADER;//header data[1] = 0x00; data[2] = 0x02;//data field size data[3] = KDM96XX_MSCARD_CLA;//instructions class data[4] = KDM96XX_MSCARD_FREAD_CMD;//command data[5] = calculate_xor(data, len-1); int rslt = write(fd, data, len); if(rslt < 0) { printf("send_fread_cmd(), write error\n"); return; } printf("\n'fread', sent bytes: "); show_char_vect_as_hex(data, len); } void send_bread_cmd(int fd) { int len = 6; char data[len]; data[0] = KDM96XX_HEADER;//header data[1] = 0x00; data[2] = 0x02;//data field size data[3] = KDM96XX_MSCARD_CLA;//instructions class data[4] = KDM96XX_MSCARD_BREAD_CMD;//command data[5] = calculate_xor(data, len-1); int rslt = write(fd, data, len); if(rslt < 0) { printf("send_bread_cmd(), write error\n"); return; } printf("\n'bread', sent bytes: "); show_char_vect_as_hex(data, len); } void send_cread_cmd(int fd) { int len = 6; char data[len]; data[0] = KDM96XX_HEADER;//header data[1] = 0x00; data[2] = 0x02;//data field size data[3] = KDM96XX_MSCARD_CLA;//instructions class data[4] = KDM96XX_MSCARD_READCLEAR_CMD; //command data[5] = calculate_xor(data, len-1); int rslt = write(fd, data, len); if(rslt < 0) { printf("send_cread_cmd(), write error\n"); return; } printf("\n'cread', sent bytes: "); show_char_vect_as_hex(data, len); } void read_and_show_resp(int fd) { //read first 4 bytes (message header) int transmitted = -1; int headerSize = 3; char header[headerSize]; memset(header, 0, headerSize); transmitted = read(fd, header, headerSize); if(transmitted < 0) { printf("read_and_show_resp(), read header error\n"); return; } printf("\nheader: "); show_char_vect_as_hex(header, transmitted); //calculate message body size and read it int dataSize = ((unsigned int)header[1]) * 256 + (unsigned int) header[2] + 1; //plus 1 byte for LRC char data[dataSize]; memset(data, 0, dataSize); transmitted = read(fd, data, dataSize); if(transmitted < 0) { printf("read_and_show_resp(), read message body error\n"); return; } printf("\nbody: "); show_char_vect_as_hex(data, transmitted); } void show_help() { printf("program {serial port device} {command name} [timeout in seconds] \n"); printf("command name : fread, bread, cread, getver, init, pres \n"); printf("usage example: \n"); printf("./program /dev/ttyS0 fread 2.5 \n"); } void clear_buf(int fd) { set_interface_attribs (fd, B9600, 0, 0.1); // set speed to 9600 bps, 8n1 (no parity) set_blocking (fd, 0, 0.1); // set no blocking int bufSize = 1024; char buf[bufSize]; read(fd, buf, bufSize); } int main(int argc, char *argv[]) { float timeoutSec = 2.5; if(argc < 2) { printf("serial port name was omitted\n"); show_help(); return 0; } if(argc < 3) { printf("command name was omitted\n"); show_help(); return 0; } char *portname = argv[1]; // like "/dev/ttyS0" char *cmdStr = argv[2]; // "read", "init", "pres" if(argc >= 4) //if there is timeout in command line - set it { timeoutSec = atof(argv[3]); } int fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC); if (fd < 0) { printf("error opening %s, retval %d\n", portname, fd); return -1; } clear_buf(fd); set_interface_attribs (fd, B9600, 0, timeoutSec); // set speed to 9600 bps, 8n1 (no parity) set_blocking (fd, 0, timeoutSec); // set no blocking if(strcmp("init", cmdStr) == 0) { send_init_cmd(fd); } if(strcmp("getver", cmdStr) == 0) { send_getver_cmd(fd); } if(strcmp("pres", cmdStr) == 0) { send_report_the_presence_and_pos_cmd(fd); } if(strcmp("fread", cmdStr) == 0) { send_fread_cmd(fd); } if(strcmp("bread", cmdStr) == 0) { send_bread_cmd(fd); } if(strcmp("cread", cmdStr) == 0) { send_cread_cmd(fd); } read_and_show_resp(fd); printf("\n"); close(fd); return 0; } //The values for speed are B115200, B230400, B9600, B19200, B38400, B57600, B1200
Показаны сообщения с ярлыком serial port. Показать все сообщения
Показаны сообщения с ярлыком serial port. Показать все сообщения
пятница, 21 февраля 2014 г.
Ридер для магнитных лент KDM-96XX
Ниже представлен код для карт-ридера магнитных лент KDM-96XX.
пятница, 19 апреля 2013 г.
Работа в Linux с последовательным портом.
Для работы с последовательным портом удобнее всего использовать библиотеки типа boost, но только в том случае, если писать на C++, который на данный момент менее популярен, чем старый добрый C. Еще в преимущества можно добавить тот факт, что понятность кода, использующего синтаксис, созданный пару дестяков лет назад, заметно выше, чем всякие биндинги, плейсхолдеры и модели событийного программиования, которые густо замешаны с шаблонами в библиотеке boost. Простейший пример открытия, чтения и записи см. ниже.
Как использовать VMIN и VTIME читать здесь:
http://www.unixwiz.net/techtips/termios-vmin-vtime.html
Остальное должно быть ясно из комментариев к коду.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <termios.h> #include <sys/ioctl.h> #include <string.h> int openSerialPort(const char * devName) { //read and write in sync mode int hSerial = open(devName, O_RDWR | O_NOCTTY | O_SYNC); if(hSerial < 0) printf("open device \"%s\" error: %d\n", devName, hSerial); struct termios port_settings; bzero(&port_settings, sizeof(port_settings)); // port_settings.c_cflag |= CREAD; port_settings.c_cflag |= CLOCAL; // port_settings.c_cc[VMIN] = 100; //delay, x0.2 sec port_settings.c_cc[VTIME] = 2; //flush serial port int fres = tcflush(hSerial, TCIFLUSH); if (fres < 0) { printf("tcflush() error %d\n", fres); } //set baud rate fres = cfsetispeed(&port_settings, B9600); if (fres < 0) { printf("cfsetispeed() error %d\n", fres); } fres = cfsetospeed(&port_settings, B9600); if (fres < 0) { printf("cfsetospeed() error %d\n", fres); } //set character size: 8. port_settings.c_cflag &= ~CSIZE; port_settings.c_cflag |= CS8; //set flow cotrol: none port_settings.c_cflag &= ~(CRTSCTS); //set parity: none port_settings.c_cflag &= ~(PARENB); port_settings.c_iflag |= IGNPAR; //set stop bits: 1 port_settings.c_cflag &= ~(CSTOPB); //apply port settings fres = tcsetattr(hSerial, TCSANOW, &port_settings); if (fres < 0) { printf("tcsetattr() error %d\n", fres); } return hSerial; } int main(int argc, char* argv[]) { if(argc < 2) { printf("One parameter is omitted\n"); return -1; } const char * devName = argv[1]; // "/dev/ttyS0" int hSerial = openSerialPort(devName); if(hSerial < 0) { return hSerial; } const char sendVect[5] = {0x01, 0x02, 0x03, 0x04, 0x05}; int byteCount = write(hSerial, sendVect, sizeof(sendVect)); if (byteCount < 0) { printf("write error %d\n", byteCount); } char buf[250]; bzero(buf, sizeof(buf)); byteCount = read(hSerial, buf, sizeof(buf)); if (byteCount < 0) { printf("read error %d\n", byteCount); } else { printf("response: \"%s\" \n", buf); } close(hSerial); return 0; }
Как использовать VMIN и VTIME читать здесь:
http://www.unixwiz.net/techtips/termios-vmin-vtime.html
Остальное должно быть ясно из комментариев к коду.
Подписаться на:
Сообщения (Atom)