[c++]rs232 на atmega8 под FreeBSD - не могу получить ответ

Обсуждаем контроллеры компании Atmel.
Ответить
Открыл глаза
Сообщения: 73
Зарегистрирован: Пт ноя 12, 2010 10:13:51
Откуда: Крым, Ялта

Сообщение tabr »

такая вот беда:
есть устройство(на меге8) с одной стороны
с другой программа, написаная на c++ под FreeBSD
общаются собственно через rs232

Устройство щелкает релюхами, собирает показания с датчиков температуры.
Команды на данные момент типа "aa","bb".
Если подключиться через виндовый HyperTerminal или cu:
cu -l /dev/ttyu0 -s9600
То все работает нормально, МК принимает данные, дрыгает релюхами, отсылает в ответ показания с датчиков.
НО когда запускаешь программу, данные МК принимает(реле щелкает), но в ответ НИЧЕГО получить не могу :( - ни букву, которую отсылаю в ответ ни показания - ВООБЩЕ ничего. программа либо ждет бесконечно долго либо ничего не получает.

да, последнее, что выводится на экран "reading data..."
исходник c++:

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

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <iostream>

#define MODEMDEVICE "/dev/cuau0"
#define BAUDRATE B9600
int main ()
        {
        int fd,n;
        char buf[255];
        fd      = open ("/dev/ttyu0",O_RDWR | O_NOCTTY | O_NDELAY);
        if (fd<0)
                perror("open_port: Unable to open port - ");
        else
                fcntl(fd, F_SETFL, 0);
        std::cout << "writing data...\n";
        n = write(fd, "aa", 2);
        if (n<0)
                std::cout << "write command error\n";
        std::cout << "wrote " << n << "bytes\n";
//      fcntl(fd, F_SETFL, FNDELAY);
        std::cout << "reading data...\n";
        n = read(fd,buf,1);
        if (n<0)
                std::cout << "read command error\n";
        else
                std::cout << "recivied:["<<buf<<"]";
        std::cout << "read conplete\n";
        close(fd);
        }
прошивка:

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

/*лишнее постарался поубирать*/
#define cbi(port,bit)   port&=~(1<<bit);
#define sbi(port,bit)   port|=(1<<bit);
#include <mega8.h>
#include <delay.h>
#include <stdio.h> 
// 1 Wire Bus functions
#include <1wire.h>
// DS1820 Temperature Sensor functions
//#include <ds1820.h>
#include <ds18b20.h>
interrupt [USART_TXC] void usart_tx_isr(void)
    {
    }
interrupt [USART_DRE] void usart_dre_isr(void)
    {
    if (uart_start_pointer == uart_end_pointer)
        {
        uart_tx_buffer_empty=1;
        cbi(UCSRB,UDRIE);
        #asm("RJMP EXIT_DRE");
        }
    if (uart_tx_buffer_empty==1)
        {
        cbi(UCSRB,UDRIE);
        #asm("RJMP EXIT_DRE");
        }
//не пустой буффер
    UDR=uart_buffer[uart_start_pointer++];
#asm("EXIT_DRE:");
    }
interrupt [USART_RXC] void usart_rx_isr(void)
    {
    if (UARTReciviedCommand==0)
        UARTReciviedCommand=UDR;
    else
        {
        UARTReciviedData=UDR;
        UARTRecivied=1;
        }
    }
void uart_send(unsigned char byte)
    {
    #asm
    uart_snt:
    SBIS 	UCSRA,UDRE	; Пропуск если нет флага готовности
    RJMP	uart_snt 	; ждем готовности - флага UDRE
    #endasm
    UDR=byte;
    }
void UARTClean()
    {
    UARTReciviedCommand=0;
    UARTReciviedData=0;
    UARTRecivied=0;
    }
void UARTStore(unsigned char data[32], unsigned char size)
    {
    unsigned char i;
    for (i=0;i<size;i++)
        {
        uart_buffer[uart_end_pointer++]=data[i];
        }
    uart_tx_buffer_empty=0;
    sbi(UCSRB,UDRIE);
    }
void main(void)
{
unsigned char ds1820_rom_codes[MAX_DS1820][9];
unsigned char tmp=0,tmp1=0;
unsigned char i=0;
unsigned char devices=0;
PORTB=0x00;
DDRB=1<<0;
PORTC=0x00;
DDRC=0x00;
PORTD=0x00;
DDRD=0x00;
TCCR0=0x00;
TCNT0=0x00;
TCCR1A=0x00;
TCCR1B=0x05;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1A=30;
OCR1BH=0x00;
OCR1BL=0x00;
ASSR    = 0;
TCCR2   = 4;
TCNT2   = 0;
OCR2    = 25;
MCUCR=0x00;
TIMSK=0x80|0x10;
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSRA=0x00;
UCSRB=1<<RXCIE|1<<TXCIE|1<<RXEN|1<<TXEN;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x67;

ACSR=0x80;
SFIOR=0x00;
ADCSRA=0x00;
SPCR=0x00;
TWCR=0x00;
w1_init();
devices=w1_search(DS18B20_SEARCH_ROM_CMD,ds1820_rom_codes);
while(1)
    {
    if (UARTRecivied==1)
        {
        switch (UARTReciviedCommand)
            case 97://a
            OnOffL1();
            uart_send(UARTReciviedData);
            break;
            case 98://b
            OnOffL2();
            uart_send(UARTReciviedData);
            break;
            case 99://c
            OnOffL3();
            uart_send(UARTReciviedData);
            break;
            case 100://d
            OnOffL4();
            uart_send(UARTReciviedData);
            break;
            case 101://e
            devices=w1_search(DS18B20_SEARCH_ROM_CMD,ds1820_rom_codes);
            uart_send(UARTReciviedData);
            break;
            case 102://f
            if (UARTHuman==1)
                uart_send(UART_NUMERIC+devices);//количество девайсов
            else
                uart_send(devices);
            break;
            case 103://g
            if (UARTHuman==1)
                {
                tmp=ds18b20_temperature(&ds1820_rom_codes[UARTReciviedData-UART_NUMERIC][0]);
                sprintf(cTmp,"%+02d",tmp);
                UARTStore(cTmp,6);
                }
            else
                {
                tmp=ds18b20_temperature(&ds1820_rom_codes[UARTReciviedData][0]);
                uart_send(tmp);
                }
            break;
            case 104://h
            if (UARTHuman == 0)
                UARTHuman=1;
            else
                UARTHuman=0;
            break;
            }
        UARTClean();
        }
    }
Подскажите, что не так.
ЗЫ: что-то подсказывает что на стороне компа беда.
ЗЫЫ: гуглил. долго.
Реклама
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница

Сообщение urry »

вы не установили в параметрах порта неканонический ввод или не дезактивировали аппаратное управление потоком

короче

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

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

//--------------------------------------------------------------
#define nBuf 32 // число принятых байт в буфере
//--------------------------------------------------------------
int fd;// /* Файловый дескриптор для порта */
char *bufptr;      /* текущий символ в буфере */
char buffer[nBuf];//32 байта принимаем
char buffer2[15];//выходной буфер

int open_port(void)
{
fd=open("/dev/ttyACM0", O_RDWR | O_NOCTTY | O_NDELAY);
/*Флаг O_NOCTTY говорит UNIX, что эта программа не хочет быть управляющим терминалом для этого порта. Если вы не укажете этого, то любой ввод (подобный сигналу абортирования от клавиатуры или что-нибудь подобное) будет затрагивать ваш процесс. Программы подобные getty(1M/8) используют эту возможность при старте логин-процесса, но обычно пользовательская программа не нуждается в таком поведении.
Флаг O_NDELAY говорит UNIX, что эта программа не заботится о состоянии сигнала DCD, т.е. что другой конец линии запущен. Если вы не укажете этот флаг, то ваш процесс "заснет" до тех пор пока на линии DCD не появится уровень space (off).*/
    if(fd == -1)
        {
        perror ("nea");
        }
        else
        {
        fcntl (fd,F_SETFL,0);
    }
    return (fd);
}
//------------------------------------
int main()
{
int nBytes;

char *bufptr;
//-------------------------
struct termios options; // структура, где изменяем данные порта
int fd;
fd=open_port();

//--------------------------------------------------------------
tcgetattr(fd, &options);//берем атрибуты в структуру для изменения

cfsetispeed(&options, B500000);//скорость 115200
cfsetospeed(&options, B500000);
options.c_cflag |= (CLOCAL | CREAD); /* Разрешение приемника и установка  локального режима...*/
options.c_cflag &= ~PARENB;// 8 нет 1
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_cflag &= ~CRTSCTS;/*для деактивирования аппаратного управления потоком передаваемых данных*/
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
/*
Выбор неканонического (Raw) ввода
Неканонический ввод не обрабатывается. Вводимый символ передается без изменений, так как он был принят. В основном вы сбрасываете опции ICANON, ECHO, ECHOE и ISIG приустановке неканонического ввода:
ECHO    Разрешить эхо вводимых символов
ECHOE    Символ эхо стирания как BS-SP-BS
ISIG    Разрешить SIGINTR, SIGSUSP, SIGDSUSP, и SIGQUIT сигналы
*/
options.c_iflag &= ~(IXON | IXOFF | IXANY);/*отмена программно управляемого управления потоком*/
options.c_oflag &= ~OPOST;/*Выбор необработанного (raw) вывода*/
/*
Драйвера последовательного интерфейса UNIX предоставляют возможность специфицировать таймауты для символа и пакета. Два элемента массива c_cc используемых для указания таймаутов: VMIN и VTIME. Таймауты игнорируются в случае режима канонического ввода или когда для файла устройства установлена опция NDELAY при открытии файла open или с использованием fcntl.
VMIN определяет минимальное число символов для чтения. Если VMIN установлено в 0, то значение VTIME определяет время ожидания для каждого читаемого символа. Примечательно, что это не подразумевает, что вызов read для N байтов будет ждать поступление N символов. Тайаут произойдет в случае задержки приема любого одиночного символа и вызов read вернет число непосредственно доступных символов (вплоть до числа которое вы запросили).

Если VMIN не 0, то VTIME определяет время ожидания для чтения первого символа. Если первый символ прочитан в течение указанного времени, то любое чтение будет блокироваться (ждать) пока все число символов, указанное в VMIN, не будет прочитано. Таким образом, как только первый символ будет прочитан, драйвер последовательного интерфейса будет ожидать приема всего пакета символов (всего количества байтов указанного в VMIN). Если символ не будет прочитан за указанное время, то вызов read вернет 0. Этот метод позволяет вам указать последовательному интерфейсу возвращать 0 или N байтов. Однако, таймаут будет приниматься только для первого читаемого символа, таким образом, если драйвер по какой-либо причине 'потеряет' один символ из N-байтного пакета, то вызов readможет быть заблокирован ожиданием ввода дополнительного символа навсегда.

VTIME определяет величину времени ожидания ввода символа в десятых долях секунды. Если VTIME установлено в 0 (по умолчанию), то чтение будет заблокировано в ожидании на неопределенное время если для порта не была установлена опция NDELAY вызовом open или fcntl. */
options.c_cc[VMIN] = 32;//32 байта
options.c_cc[VTIME] = 5;// таймаут 0.5 сек
tcsetattr(fd, TCSANOW, &options);// установили новые атрибуты порта
/*
Константа    Описание
TCSANOW        Произвести изменения немедленно, не дожидаясь завершения операций пересылки данных
TCSADRAIN    Подождать пока все данные будут переданы
TCSAFLUSH    Очистить буфера ввода/вывода и произвести изменения
*/
//-----------------------------------------------------------------------
int i;
i=write(fd,"1",1);// выдача строба для инициализации чтения
if (i<0){
        perror ("error write!"); // ошибка выдачи байта для стробирования
}
//--------------------------------------------------------------
/*Чтение данных с порта несколько сложнее. Когда вы работаете с портом в режиме не структурированного посимвольного обмена (raw data mode), каждый системный вызов read(2) будет каждый раз возвращать число символов реально прочитанных в буфер ввода. Если в текущий момент нет символов доступных для чтения, то вызов будет блокироваться (wait) до тех пор пока не появятся символы для чтения, или закончится счетчик таймаута, или обнаружится какая-нибудь ошибка. Функцию read можно выполнить так, что она вернет управление немедленно. Для этого она должна быть оформлена следующим образом:

      fcntl(fd, F_SETFL, FNDELAY);

Опция FNDELAY указывает функции read возвращать 0 если нет символов доступных для чтения из последовательного порта. Для восстановления нормально поведения (с блокировками), необходимо вызвать fcntl() без опции FNDELAY:

      fcntl(fd, F_SETFL, 0);

Это также выполняется после открытия последовательного порта с опцией O_NDELAY.
*/
fcntl(fd, F_SETFL, 0);
  int  nbytes;       /* число прочитанных байтов*/

    bufptr = buffer;

read(fd, buffer,32);

close (fd); // закрываем последовательный порт



Контактная информация:
Реклама
Открыл глаза
Сообщения: 73
Зарегистрирован: Пт ноя 12, 2010 10:13:51
Откуда: Крым, Ялта

Сообщение tabr »

ЗАРАБОТАЛО!
Огромное спасибо!
ЗЫ: Я как раз подозревал нечто подобное и копал)
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница

Сообщение urry »

Так ежу понятно, что вопрос по никсам нужно задавать на форуме "микроконтроллеры".
А где же еще Вам ответят ?
:)
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Родился
Сообщения: 4
Зарегистрирован: Пт мар 05, 2010 20:07:25
Откуда: Правда

Сообщение Chacha.s »

Наткнулся на тему. У меня тоже проблема с чтением из UART. Но только массива

Настраиваю UART так:

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

/* USB Init */
	fd_serialport = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
	if(fd_serialport == -1){
		perror("Unable to open /dev/ttyUSB0");
	}
	 
	tcgetattr(fd_serialport, &options);
	cfsetispeed(&options, B230400);
	cfsetospeed(&options, B230400);
	options.c_lflag = 0;
	options.c_iflag = 0;
	options.c_oflag = 0;
	options.c_cflag = B230400 | CREAD | CS8 | CLOCAL | HUPCL;
//	options.c_cc[VTIME] = 5; /* междусимвольный таймер выключен */
//	options.c_cc[VMIN]  = 0; /* блокируем read после получения 255 символов */
	
	tcflush(fd_serialport, TCIFLUSH);
	fcntl(fd_serialport, F_SETFL, 0);
	tcsetattr(fd_serialport, TCSANOW, &options);
Читаю и вывожу так:

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

	i = read(fd_serialport, test, size+9);
	
	printf("Emount of readed bytes = %d\n", i);

	printf("Data was readed = ");
	i = 0;
	
	while ((test[i] != 0xC0) && (i<(size+9)) )// New string from the end of package
	{
		printf("0x%02x ", test[i]);
		if ((i-6) % 17 == 0) printf(" %d  %d\n", (i-6)/17, i);
		i++ ;
	}
	printf("0x%02x\n", test[i]);
	
//////////////////////////////////////////////////////////////////////////////////////////////////////
/*waitung for incoming bytes from buttons*/
	while( read(fd_serialport, &temp, 1) != -1 )
	{
		printf("0x%02x ", (unsigned char)temp);
		fflush(stdout);
		if (temp == 0xC0) // New string from the end of package
			printf("\n");
	}
	temp =0;
}


Дело в том, что массив читается не полностью вызовом read. Возвращается только около 15 символов. А остальная часть выплевывается в цикле считывания инфы в бесконечном цикле опроса.

При использовании флагов с_сс - установки
options.c_cc[VTIME] = 5; /* междусимвольный таймер выключен */
options.c_cc[VMIN] = 255;

Читает нормально, но максимальное количество 255 байт(((

Вроде бы настроил блокирующий вызов, не пойму почему read читает всего около 10 байт, когда я хочу прочитать около 1000. На стороне МК все работает хорошо массив передается через DMA.
Контактная информация:
Реклама
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница

Сообщение urry »

и что вы хотите услышать ?
максимальная длина приемного буфера - 255 байт, так уж исторически сложилось - при вводе с клавы в линуксе максимальное количество символов в 1 строке - 255.
для 1000 - режьте пакеты, что еще сказать...
Контактная информация:
Реклама
Родился
Сообщения: 4
Зарегистрирован: Пт мар 05, 2010 20:07:25
Откуда: Правда

Сообщение Chacha.s »

Да, разобрался. Там похоже еще скорость приемного буфера маленькая. Просто читал в один массив, пока не было прочитано нужное количество элементов)
Контактная информация:
Ответить

Вернуться в «AVR»