2014-01-28 2 views
1

Привет, я пытаюсь установить связь между avr atmega32a и дистрибутивом linux. Я использую чип ftdi на USB-порту (драйверы VCOM и т. Д.)Проблемы с последовательным портом на linux, между avr и linux

Я выложу коды в avr и linux, но код в avr отлично работает, поскольку я тестировал его на minicom.

Я предполагаю, что проблема здесь в моем коде на linux. Основная проблема заключается в том, что она иногда работает, иногда не работает. Я предполагаю, что это имеет какое-то отношение к открытию и закрытию дескриптора файла или самого порта.

Почему я говорю это?

Код на avr делает простую вещь. Ожидает нажатия кнопки, а затем начинает отправлять «Hello world» навсегда.

Так что при использовании minicom он работает отлично.

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

Затем я открываю миникомпьютер и сразу начинает считывать (потому что кнопка нажата). Затем я закрываю minicom, я открываю свою программу, и она отлично работает.

Кажется, что возникают проблемы с открытием и закрытием файла (порта), но я не уверен. В любом случае эта вещь недостаточно стабильна.

Любая помощь была бы признательна.

То, что я хочу написать, - это постоянное чтение из последовательного порта. Ive читал о блокировании чтения, но когда я пытаюсь его реализовать, он, похоже, не работает.

Спасибо.

UPDATE * * Я просто добавил еще, если (wordsRead < 0) Е ("Ошибка чтения \ п"); Кажется, что он получает -1 при чтении в первый раз, но я не понимаю, почему это происходит Проблема в том, что когда он правильно читает из порта (после использования minicom в первый раз) я получаю много показания ошибок между печатями «Hello world» ....

Вот мой код AVR только основная функция.

int main() 
{ 
    uart_init(); 
    //Set A0-6 as input, A7 as output 
    //Set as hexademical cause compiler does not support 0b 
    DDRA = 0x80;; 
    //Triggers up 
    PORTA = 0xFF; 

    while ((PINA & 0x1) == 1); 
    //Led on 
    PORTA &= 0x7F; 

    while (1){ 
     uart_putstring("Hello world "); 
    } 
} 

Вот мой код C на linux.

#include <errno.h> 
#include <termios.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/wait.h> 
#include <signal.h> 

int main() 
{ 
    //Open Port 
    int fdSP= open("/dev/ttyUSB0",O_RDWR | O_NOCTTY | O_NDELAY); 
    if (fdSP == -1){ 
     printf("Error opening serial port\n"); 
     return 1; 
    } 

    // create the struct 
    struct termios options; 

    //Preferences 
    int BaudRate = 19200; 

    //Set Baud Rate 
    cfsetispeed(&options, BaudRate); 
    cfsetospeed(&options, BaudRate); 

    //Set Parity (No Parity) 
    options.c_cflag &= ~PARENB; 

    //Set Stop Bits (2 Stop Bits) 
    options.c_cflag &= CSTOPB; 

    //Set Data Bits (8 Data Bits) 
    options.c_cflag &= ~CSIZE; 
    options.c_cflag |= CS8; 


    if (tcsetattr(fdSP, TCSANOW, &options) != 0){ 
     printf("Error applying settings to serial port\n"); 
     return 1; 
    } 



    //Read Port 
    pid_t pid = fork(); 
    if (pid < 0){ 
     printf("Error creating child\n"); 
     return 1; 
    } 
    else if (pid == 0){ 
     raise(SIGSTOP); 
     int wordsRead; 
     char readSP; 
     while (1){ 
      wordsRead = read(fdSP, &readSP, 1); 
      if (wordsRead > 0) 
       printf("%c", readSP); 
        else if (wordsRead < 0) 
          printf("Error reading\n"); 
      } 
    } 
    else{ 
     printf("Created a child to read from serial port\n"); 
     printf("To kill the child open another terminal and type sudo kill %ld or press enter ok?", (long) pid); 
     getchar(); 
     kill(pid, SIGCONT); 
     getchar(); 
     kill(pid, SIGKILL); 

     if (close(fdSP) == -1){ 
      printf("Error closing port\n"); 
      return 1; 
     }; 
    } 
    return 0; 
} 
+0

Почему вилка? Попробуйте удалить вилку и запустить ее, чтобы уменьшить пространство проблем. –

+0

Правильны ли настройки порта? 'minicom' устанавливает настройки в первый раз, затем ваша программа использует их. Возможно, вам что-то не хватает. –

+0

Сначала вы должны использовать 'tcgetattr', чтобы заполнить структуру termios. Теперь он полон мусора. –

ответ

0

Это:

// create the struct 
struct termios options; 

создает неинициализированнымstruct termios. Сначала необходимо инициализировать текущие настройки порта, а затем изменить настройки:

// create the struct 
struct termios options; 
tcgetattr(fdSP, &options); 
+0

Добавил его, но у меня все еще есть проблемы с настройками minicom - Serial Device/dev/ttyUSB0, Lockfile Location/var/lock, Bps/Par/Bitss 19200 8N2, Hardware Flow Control No, Управление потоком программного обеспечения Нет – tchar

+0

@BartDriederichs Кажется, вы правы если я начинаю сначала minicom, он правильно устанавливает параметры последовательного порта, а затем он работает. Параметры termios установлены правильно (после i tcgetattr()), но как узнать правильные параметры termios для их установки? – tchar

+0

@tchar проверить настройки minicom. Вы также можете попробовать прочитать параметры, когда они будут работать. –

1

Хорошо, я нашел проблему ...

Кажется, что проблема была в порядке, в котором я выполнял все дело о настройке атрибутов и т.д.

Я изменил порядок

  1. Определить нужные атрибуты -> Параметры (новый).
  2. Открыть последовательный порт.
  3. Получить существующие атрибуты -> oldoptions.
  4. Установите новые атрибуты -> параметры (новые).
  5. Читайте с порта.
  6. Восстановить старые атрибуты -> oldoptions.
  7. Закрыть порт.

Порядок раньше (не работал) был (2-> 3-> 1-> 4-> 5-> 6-> 7)

Благодаря @Bart Friederichs за ценные советы и помощь

Мой окончательный код ниже

Основной (будет выполнен)

#include <errno.h> 
#include <termios.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/wait.h> 
#include <signal.h> 
#include <string.h> 
#include "sp-proc.h" 

#define MY_BAUDRATE B19200 


int main() 
{ 
    // create the struct 
    struct termios options, oldoptions; 


    memset(&options,0,sizeof(options)); 
    options.c_iflag = 0; 
    options.c_oflag = 0; 
    options.c_cflag = CS8|CREAD|CLOCAL; 
    options.c_lflag = 0; 
    options.c_cc[VMIN] = 1; 
    options.c_cc[VTIME] = 0; 

    //Setting Baud Rate 
    cfsetispeed(&options, MY_BAUDRATE); 
    cfsetospeed(&options, MY_BAUDRATE); 

    //Open Serial Port 
    int fdSP = openSP(); 

    //Save old options to oldoptions 
    getOldAttr(fdSP, &oldoptions); 

    //Set new options 
    setNewAttr(fdSP, &options, &oldoptions); 

    //Create child to read from port 
    pid_t pid = fork(); 
    if (pid < 0){ 
     printf("Error creating child\n"); 
     exit(1); 
    } 
    else if (pid == 0){ 

     raise(SIGSTOP); 
     //Read Port 
     int wordsRead; 
     char readSP; 
     while (1){ 
      wordsRead = read(fdSP, &readSP, 1); 
      if (wordsRead > 0) 
       printf("%c", readSP); 
     } 
     exit(0); 
    } 
    else{ 
     printf("Created child with pid = %ld to read from Serial Port\n", (long) pid); 
     printf("To stop reading from serial port open another terminal "); 
     printf("and type sudo kill %ld or press <enter> ok?", (long) pid); 
     getchar(); 
     kill(pid, SIGCONT); 
     getchar(); 
     kill(pid, SIGSTOP); 
     printf("\n"); 

     //Restoring old options 
     resetOldAttr(fdSP, &oldoptions); 
     //Closing SerialPort 
     closeSP(fdSP); 
     exit(0); 
    } 
} 

SP-proc.h

int openSP(void); 
void closeSP(int fd); 
void getOldAttr(int fd, struct termios* old); 
void resetOldAttr(int fd, struct termios* old); 
void setNewAttr(int fd, struct termios* new, struct termios* old); 

зр-proc.c

#include <termios.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <fcntl.h> 

int openSP(){ 
    int fd= open("/dev/ttyUSB0",O_RDWR | O_NOCTTY | O_NDELAY); 
    if (fd == -1){ 
     printf("Error opening serial port\n"); 
     exit(1); 
    } 
    return fd; 
} 

void closeSP(int fd){ 
    if (close(fd) == -1){ 
      printf("Error closing port\n"); 
      exit(1); 
    } 
} 

void getOldAttr(int fd, struct termios* old){ 
    if (tcgetattr(fd, old) != 0){ 
     printf("Error getting old options from serial port\n"); 
     closeSP(fd); 
     exit(1); 
    } 
} 

void resetOldAttr(int fd, struct termios* old){ 
    if (tcsetattr(fd, TCSANOW, old) != 0){ 
     printf("Error restoring old options\n"); 
     closeSP(fd); 
     exit(1); 
    } 
} 

void setNewAttr(int fd, struct termios* new, struct termios* old){ 
    if (tcsetattr(fd, TCSANOW, new) != 0){ 
     printf("Error applying settings to serial port\n"); 
     resetOldAttr(fd, old); 
     closeSP(fd); 
     exit(1); 
    } 
} 
Смежные вопросы