Модераторы: xvr
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> RS485 (плата PCI-1602B), Проблемы с приемом ! 
:(
    Опции темы
plica98
Дата 19.12.2012, 11:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 91
Регистрация: 12.3.2012

Репутация: нет
Всего: нет



Добрый день, уважаемые Коллеги.

Возникли проблемы при работе с RS485 (плата PCI-1602B - двухголовая). 
При приеме идет какой-то мусор из порта.
Может кто- нибудь что подскажет или какие-нибудь исходники скинет.

Может не совсем корректно проинициализировал плату ?

Заранее благодарю за помощь и внимание.

PM MAIL   Вверх
tzirechnoy
Дата 19.12.2012, 13:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 3
Всего: 16



Напишыте минимальный пример, который демонстрирует проблемы, и покажыте. Возможно, кто-нибудь что-нибудь в нём поймёт и объяснит, что не так.
PS Да, проблемы с приёмом на подобных каналах -- это обычно несоответствие скорости или битности. Но таки всякое можэт быть.
PM MAIL   Вверх
plica98
Дата 20.12.2012, 10:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 91
Регистрация: 12.3.2012

Репутация: нет
Всего: нет



Добрый день, уважаемые Коллеги.


ПЕРЕДАЧА
Код



Код

#include <stdio.h>   /* Стандартные объявления ввода/вывода */
#include <stdlib.h>
#include <string.h>  /* Объявления строковых функций */
#include <unistd.h>  /* Объявления стандартных функций UNIX */
#include <fcntl.h>   /* Объявления управления файлами */
#include <errno.h>   /* Объявления кодов ошибок */
#include <termios.h> /* Объявления управления POSIX-терминалом */


#include <time.h>
#include <sys/timeb.h>
#include <sys/types.h>
#include <sys/ioctl.h>


void clear_port(int);
void open_dev();
void work();

unsigned char time_out = 40;
int port;
char str[256];

int main(int argc,char **argv)
{
    int i,j,k;

    open_dev();
    work();
    
}

/* Открытие и конфигурирование порта*/
void open_dev()
{
    struct termios m_termios;
    int j;
/* Открываем порт */
    port = open("/dev/ttyAP0",O_RDWR|O_NDELAY|O_NOCTTY);
    if(port < 0) {
        printf("/dev/ttyAP0 Open BAD !!!\n")  ;
        exit(-1);
        }
    printf("/dev/ttyAP0 Open Ok !!!\n")  ;

/* Получаем атрибуты порта */
    tcgetattr(port, &m_termios);
    m_termios.c_iflag |= ( BRKINT | IXANY | IMAXBEL | IUTF8 ) ;
    m_termios.c_cflag |= ( CREAD | CLOCAL | HUPCL  );

    m_termios.c_cflag &= ~CSIZE; /* Mask the character size bits */
    m_termios.c_cflag |= CS8;    /* Select 8 data bits */

    m_termios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); //Raw input
    m_termios.c_oflag &= ~OPOST;
/* Установка четности */
    m_termios.c_cflag &=  (~PARODD) ;
    m_termios.c_cflag &= (~PARENB) ;
/* Стопы */
    m_termios.c_cflag &=  (~CSTOPB) ;
/* Скорость */
    cfsetospeed(&m_termios,B19200);
    cfsetispeed(&m_termios,B19200);
/* Установка новых атрибутов */
    tcsetattr(port,TCSANOW,&m_termios);
/* Очищаем порт */
    clear_port(port);
    printf("PORT  - Ok!!! \n");

}

void work()
{
    int i,j,len;
    len = 5;
    printf("WORK - BEGIN \n");

    while(1)  {
    unsigned char XmitBuffer[len];
    XmitBuffer[1] = 0;
    XmitBuffer[2] = 1;
    XmitBuffer[3] = 0x46;
    XmitBuffer[4] = 0xB2;

    for (i = 0; i < 8; i++) {
        XmitBuffer[0] = i+1;
        printf(" SENDER = %X,%X,%X,%X,%X,%X,\n",XmitBuffer[0],XmitBuffer[1],XmitBuffer[2],XmitBuffer[3],XmitBuffer[4],len);

    if (write(port,XmitBuffer , len) == -1) {
        printf("ERROR write in port");
    }
    sleep(1);
    }
}
}

void clear_port(int i)
{
    int j;
    j=1;
    while(j > 0)    {
        j=read(i,str,256);
    }
}




ПРИЕМ

Код



Код

#include <stdio.h>   /* Стандартные объявления ввода/вывода */
#include <stdlib.h>
#include <string.h>  /* Объявления строковых функций */
#include <unistd.h>  /* Объявления стандартных функций UNIX */
#include <fcntl.h>   /* Объявления управления файлами */
#include <errno.h>   /* Объявления кодов ошибок */
#include <termios.h> /* Объявления управления POSIX-терминалом */


#include <time.h>
#include <sys/timeb.h>
#include <sys/types.h>
#include <sys/ioctl.h>



void clear_port(int);
void open_dev();
void work();
void read_data();
int wait_blok(int);

int time_out1 = 2000;
unsigned char time_out = 40;

int port;
char str[256];
unsigned char XmitBuffer[20];

int main(int argc,char **argv)
{
    int i,j,k;

    open_dev();
    work();
    
}

/* Открытие и конфигурирование порта */
void open_dev()
{
    struct termios m_termios;
    int j;
/* Открываем порт */
    port = open("/dev/ttyAP1",O_RDWR|O_NDELAY|O_NOCTTY);
    if(port < 0) {
        printf("/dev/ttyAP1 Open BAD !!!\n")  ;
        exit(-1);
        }
    printf("/dev/ttyAP1 Open Ok !!!\n")  ;

/* Получаем атрибуты порта */
    tcgetattr(port, &m_termios);
    m_termios.c_iflag |= ( BRKINT | IXANY | IMAXBEL | IUTF8 ) ;
    m_termios.c_cflag |= ( CREAD | CLOCAL | HUPCL  );

    m_termios.c_cflag &= ~CSIZE; /* Mask the character size bits */
    m_termios.c_cflag |= CS8;    /* Select 8 data bits */

    m_termios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); //Raw input
    m_termios.c_oflag &= ~OPOST;
/* Четность */
    m_termios.c_cflag &=  (~PARODD) ;
    m_termios.c_cflag &= (~PARENB) ;
/* СТОПЫ */
    m_termios.c_cflag &=  (~CSTOPB) ;
/*Скорость */
    cfsetospeed(&m_termios,B19200);
    cfsetispeed(&m_termios,B19200);
/* Устанавливаем новые атрибуты */
    tcsetattr(port,TCSANOW,&m_termios);
/* Очищаем порт */
    clear_port(port);
    printf("PORT  - Ok!!! \n");

}

void work()
{
    int i,j,len;
    len = 5;
    printf("WORK - BEGIN \n");

    while(1)  {
    read_data();
    }

}

void clear_port(int i)
{
    int j;
    j=1;
    while(j > 0)    {
        j=read(i,str,256);
    }
}

int wait_blok(int num)
{
    struct timeb st_time,end_time;
    time_t i,i1,l;
    int n;
    n=0;
    ftime(&st_time);
    while(n < num) {
        ftime(&end_time);
        i=end_time.time*1000+end_time.millitm;
        i1=st_time.time*1000+st_time.millitm;
        l=i - i1;
        ioctl(port, FIONREAD, &n);

        if(n >= num) {
    printf(" COUNT BYTE = %d !!!!!!!!!!!!\n", n);
            return 0 ;
            }
        if( l > time_out1) {
            clear_port(port);
            return(1);
            }
    }
    return(0);
}

void read_data()
{
    int j,c;
    struct timeval mm_val;
    fd_set infd;
    FD_ZERO(&infd);
    FD_SET(port, &infd);
    mm_val.tv_sec= 2;
    mm_val.tv_usec=0;
    // юЙФБА ЛБДТ
        j=port+1;
    c = select(j, &infd, NULL, NULL, &mm_val);
    if(c > 0 ) {

        if (FD_ISSET(port, &infd)) {
            if((j=wait_blok(5))) {
                return;
            }
            j=read(port,XmitBuffer , 5);
    printf(" RECEIVER = %X,%X,%X,%X,%X \n",XmitBuffer[0],XmitBuffer[1],XmitBuffer[2],XmitBuffer[3],XmitBuffer[4]);
        }
    }
}



Передающая пишет в порт по 5 байт с интервалом в 1сек.

Приемная должна читать по 5 байт, а читает мусор.

Может FIFO не задано ? Как задать ?






Это сообщение отредактировал(а) plica98 - 21.12.2012, 11:33
PM MAIL   Вверх
tzirechnoy
Дата 20.12.2012, 13:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 3
Всего: 16



1) У Вас, я смотрю, какой-то юникс? Почему бы тогда для начальной приладки не вопсользоваться простыми написанными средствами -- stty+cat или там cu -l или minicom.
2) Выглядят программы вроде нормально, собирать не пробовал. ожыдание через FIONREAD немного странное, но для пяти байт буферов должно хватить (там 8k вроде стандартно).
3) Проверьте физику. + должэн быть к +, - к -. Терминаторы по 120 ом (с обоих сторон по-моему).
PM MAIL   Вверх
xvr
Дата 20.12.2012, 13:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 20
Всего: 223



Посмотрите в документацию на плату (и/или на ее драйвера) - не надо ли каких либо явных манипуляций по управлению направлением передачи информации, т.к. RS485 - это полудуплекс, и одновременно принимать и передавать оно не может физически

PM MAIL   Вверх
plica98
Дата 20.12.2012, 14:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 91
Регистрация: 12.3.2012

Репутация: нет
Всего: нет



Плата сама управляет переключением прием-передача.

У платы две головы. Я соединил выход одной с входом другой и наоборот.
Иногда удается что-то принять. Причем, для этого надо запустить вначале программу приема, а потом передачу.
Такое впечатление, что как бы синхронизация нарушается.

Добавлено через 5 минут и 2 секунды
Без операционки на физическом уровне я работаю с этой платой нормально.

А вот хотел сделать под Linux (у меня Fedora стоит). Документации на драйвера нет. Через IOCTL тоже нет документации.
Может кто-то уже с ней работал под Linux. Тем более я хотел ее использовать на не стандартных скоростях (192000).
PM MAIL   Вверх
tzirechnoy
Дата 20.12.2012, 17:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 3
Всего: 16



Цитата
Причем, для этого надо запустить вначале программу приема, а потом передачу.


Вот это как раз неудивительно.

Добавлено через 39 секунд
А, да, чуть не забыл. Все системные вызовы надо проверять на ошыбки, и если есть -- информировать. Часто всплывают очень любопытные вещи.
PM MAIL   Вверх
bsa
Дата 20.12.2012, 23:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 16
Всего: 196



plica98, исправь свой пост с кодом оформив сам код в теги [code=cpp] [/code]
PM   Вверх
tzirechnoy
Дата 21.12.2012, 10:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1173
Регистрация: 30.1.2009

Репутация: 3
Всего: 16



Цитата
Документации на драйвера нет.


Зато, наверняка, есть исходники. Если нет -- ну, даташыт с описанием регистров у тебя вроде есть -- драйвер serial порта -- это в районе тысячи-полутора строк, из которых половину можно взять из существующего обычного.
PM MAIL   Вверх
bsa
Дата 21.12.2012, 16:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 16
Всего: 196



PM   Вверх
plica98
Дата 24.12.2012, 09:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 91
Регистрация: 12.3.2012

Репутация: нет
Всего: нет



Цитата(bsa @ 21.12.2012,  16:16)
Это не про нее? http://www.fccps.cz/download/adv/frr/pci-1...E.pci-16xx.html

Да, это она.

Большое спасибо за участие.
Пока сдвигов нет, надо разбираться.
PM MAIL   Вверх
rsm
Дата 25.12.2012, 08:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник Клуба
Сообщений: 999
Регистрация: 16.3.2005

Репутация: 3
Всего: 62



Доводилось работать с разными платами этой серии, их нормальная инициализация действительно проблема smile
Вот кусок из старых исходников (проверки на ошибки убраны для уменьшения кода):

Код

#define PORT_SPEED (B19200) /* скорость порта */
#define PACKET_SIZE (16) /* размер одного пакета, байт */

int fd;
struct termios tio;

fd = open("/dev/ttyS0", O_RDONLY | O_NOCTTY | O_NDELAY);
fcntl(fd, F_SETFL, 0);
tcgetattr(fd, &tio);
cfsetispeed(&tio, PORT_SPEED);
tio.c_cflag = PORT_SPEED | CLOCAL | CREAD | CS8;
tio.c_iflag = IGNBRK | IGNPAR;
tio.c_lflag = 0;
tio.c_line = 0;
tio.c_oflag = 0;
tio.c_cc[VSTART] = 0;
tio.c_cc[VSTOP] = 0;
tio.c_cc[VMIN] = PACKET_SIZE;
tcsetattr(fd, TCSANOW, &tio);


В данном примере порт открывается только для чтения. Для записи нужно: поменять флаги open (строка 7), добавить cfsetospeed(&tio, PORT_SPEED) после строки 10 и всё остальное оставить без изменений.

И таки да: использование ioctl(FIONREAD), причём ещё и в цикле - это очень плохая идея. Данная серия плат славится своими глюками в части передачи данных пакетами фиксированной длины, поэтому ioctl лучше оставить в покое и формировать пакеты программно, внутри select'а набивая массив и уже его разбивая по пакетам. Хотя это крайняя мера, лично у меня приведённый выше код делил данные по пакетам без всякого шаманства (см. PACKET_SIZE).

И ещё: "очищать" порт попытками вычитать из него все данные - это ещё более худшая идея. Для этого есть вызов tcflush(3).

Общие рекомендации:
- настройки портов должны быть полностью идентичны (скорость, разрядность, чётность, контроль потока и пр.);
- размеры пакетов желательно делать полностью идентичными (отправляется 16 байт и принимается 16 байт);
PM MAIL   Вверх
plica98
Дата 25.12.2012, 10:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 91
Регистрация: 12.3.2012

Репутация: нет
Всего: нет



RSM, спасибо за помощь.

Но, как я уже говорил, без операционки на физическом уровне я работаю с этой платой нормально.
Причем работаю даже на максимальных скоростях и дуплексном режиме. Проблем нет ни с приемом, ни с передачей пакетов любой длины.  
Плата отлично работает, нареканий никаких нет.

Думаю, что проблема не в плате, а в софте. Вот и хотелось бы разобраться. Можно же с ней работать, наверное, и на низком уровне (через IOCTL).



Вот и хочу сделать под Linux (у меня Fedora стоит). Плохо что документации никакой нет. 

PM MAIL   Вверх
rsm
Дата 25.12.2012, 11:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник Клуба
Сообщений: 999
Регистрация: 16.3.2005

Репутация: 3
Всего: 62



Цитата(plica98 @  25.12.2012,  12:23 Найти цитируемый пост)
Думаю, что проблема не в плате, а в софте

Очень может быть smile

Цитата(plica98 @  25.12.2012,  12:23 Найти цитируемый пост)
Можно же с ней работать, наверное, и на низком уровне (через IOCTL)

tc[gs]etattr - это обёртка над ioctl. Проблема скорее в том, что единственные (?) имеющиеся дрова врубают в ядро нехилый костыль, что запросто может приводить к феерическим багам. По видимому, разработчик не нашёл иного пути smile

Цитата(plica98 @  25.12.2012,  12:23 Найти цитируемый пост)
Плохо что документации никакой нет

Какой именно документации - по платам? Не думаю, что Advantech внезапно откроет все спецификации...
PM MAIL   Вверх
plica98
Дата 25.12.2012, 14:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 91
Регистрация: 12.3.2012

Репутация: нет
Всего: нет



Цитата(rsm @ 25.12.2012,  11:43)
Какой именно документации - по платам? Не думаю, что Advantech внезапно откроет все спецификации...

RSM.

Документации ADVANTECH IOCTL
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Программирование под Unix/Linux"
xvr
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой "Код".
  • Вопросы мобильной разработки тут
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, xvr.

 
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Программирование под Unix/Linux | Следующая тема »


 




[ Время генерации скрипта: 0.0577 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.