Передача данных в com порт (Программа для работы с весами по com-порту)

Модератор: Модераторы разделов

xmxcrew
Сообщения: 2

Передача данных в com порт

Сообщение xmxcrew »

Есть у меня на работе электронные весы, данные на которые отправляются и принимаются через com порт. Под каждыми весами стоит комп с winxp, на нем 1С, в которой формируется список товаров которые нужно передать на эти весы. Список сохраняется в текстовой файлик и в дальнейшем программкой написанной в Дельфях отправляется на эти самые весы (исходников ее нет).
Пытаюсь написать программку под FreeBsd которая бы делала то же самое. Отправляла данные из файлика на весы.
Но пока что все бестолку.
Проблема в том что С++ я начал изучать неделю назад и именно ради того чтобы написать эту программу. Так что не бейте больно, а лучше направьте в правильном направлении (что где почитать).
Сейчас пытаюсь просто написать программку которая передаст в эти весы просто одну настройку.

на данный момент получилась вот такая вот программа

Код: Выделить всё

#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <iostream>

using namespace std;
int main(void)
{
int n;
int fd; /* File descriptor for the port */
char buf[200];
struct termios options;

fd = open("/dev/cuad0", O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fd == -1) perror("open_port: Unable to open /dev/cuad0 - ");
else
{
fcntl(fd, F_SETFL, 0);

tcgetattr(fd, &options);
cfmakeraw(&options);

/************************************************************************/
// c_cflag
 options.c_cflag |= PARENB;
 options.c_cflag |= PARODD;
 options.c_cflag &= ~CSTOPB;

 options.c_cflag &= ~CSIZE;
 options.c_cflag |= CS8;

 options.c_iflag |= (INPCK);

cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);

tcsetattr(fd, TCSAFLUSH, &options);
tcflush(fd, TCIOFLUSH); /**/


// Main code
buf[0]=0;
n = write(fd, buf, 1);
usleep(150000);
cout << "Written:" << n << '\n';
usleep (150000);
read(fd,buf,1);
cout << "Readen:" << int(buf[0]) << '\n';

buf[0]=0x01;
n = write(fd, buf, 1);
usleep(150000);
cout << "Written:" << n << '\n';
usleep (150000);
read(fd,buf,1);
cout << "Readen:" << int(buf[0]) << '\n';

buf[0]=0;
buf[1]=60;

n = write(fd, buf, 2);
usleep(150000);
cout << "Written:" << n << '\n';
usleep (150000);
read(fd,buf,3);
cout << "Readen:" << int(buf[0]) << '\n';



close(fd);
}
}


результат ее работы такой

Код: Выделить всё

Written:1
Readen:0
Written:1
Readen:1
Written:2
Readen:0


при этом то что ожидалось с весами не происходит

алгоритм по которому делалась программа

У вас нет необходимых прав для просмотра вложений в этом сообщении.
Спасибо сказали:
Аватара пользователя
Женя Подсыпальников
Сообщения: 482

Re: Передача данных в com порт

Сообщение Женя Подсыпальников »

А read тоже число возвращает -
дак оно в первом случае уже "ноль", поди ? :)
Пойдём на рыбалку !
Спасибо сказали:
xmxcrew
Сообщения: 2

Re: Передача данных в com порт

Сообщение xmxcrew »

немного непонял, после первого write он должен сказать либо хекс77 (все ок)
Спасибо сказали:
Аватара пользователя
Женя Подсыпальников
Сообщения: 482

Re: Передача данных в com порт

Сообщение Женя Подсыпальников »

xmxcrew писал(а):
10.06.2009 16:57
у весов номера от 1 до 99, а ноль это универсальный номер который позволяет отправить на любые весы


Угу, уже понял, спасибо :)

Если первый n = read(..) ноль возвращает (cout << n) -
параметры порта менять можно попробывать...
Пойдём на рыбалку !
Спасибо сказали:
Аватара пользователя
AestheteAnimus
Сообщения: 135
ОС: FreeBSD 8.0-RELEASE amd64

Re: Передача данных в com порт

Сообщение AestheteAnimus »

Для начала, сразу стоит пофиксить вот это:
fd = open("/dev/cuad0", O_RDWR | O_NOCTTY | O_NONBLOCK);
Ну в самом деле, зачем Вам здесь неблокируемые операции? Вместо того, чтобы их не использовать, Вы решили напихать задержки usleep.

А теперь по-существу. Обычно девятый бит - это бит четности, но в описании было сказано, что здесь 9-й бит используется как бит данных "Передачу информации по протоколу 0 [бла бла бла], а девятый бит устанавливается в 1. Все остальные комманды ... передаются с девятым битом, равным 0". Тоесть, нельзя просто выставить способ проверки четности, как Вы это сделали:

Код: Выделить всё

 options.c_cflag |= PARENB;
 options.c_cflag |= PARODD;

и ожидать, что в девятом бите окажется подходящее значение. Чтобы управлять этим битом, нужно менять соответсвующим образом четность: Mark и Space.
Спасибо сказали:
Аватара пользователя
eddy
Сообщения: 3321
Статус: Красный глаз тролля
ОС: ArchLinux

Re: Передача данных в com порт

Сообщение eddy »

Можно вот так:

Код: Выделить всё

void write_tty_raw(unsigned char wb){
    if(crc(wb)) // нечетная сумма
        tty.c_cflag |=PARODD; // 9-й бит = 0
    else
        tty.c_cflag &= ~PARODD; // = 1
    ioctl(comfd,TCSETA,&tty); // перенастраиваем порт
    if(write(comfd, &wb, 1) < 0) fprintf(stderr, "Ошибка! Запись не удалась :(\n"); // и пишем в него байт
}


Четность я считаю так:

Код: Выделить всё

unsigned char crc(unsigned char data){
    unsigned char crc = data & 1;
    unsigned int i;
    for(i = 1; i<8; i++) crc ^= (data >> i) & 1;
    return crc;
}

но есть и более быстрые алгоритмы (см. сниппеты).
RTFM
-------
KOI8-R - патриотичная кодировка Изображение
Спасибо сказали: