Возникли проблемы с последовательным портом в Linux, между AVR и Linux
Здравствуйте, я пытаюсь общаться между AVR Atmega32a и Linux дистрибутива. Я использую чип FTD на USB-порт (драйверы VCOM и т. Д.)
Я буду публиковать коды в AVR и Linux, но код в AVR работает нормально, так как я тестировал его на Minicom.
Я предполагаю, что проблема здесь в моем коде на Linux. Основная проблема в том, что иногда это работает, иногда не работает. Я предполагаю, что это как-то связано с открытием и закрытием файлового дескриптора или самого порта.
Почему я это говорю?
Код на AVR делает простую вещь. Ожидает нажатия кнопки, а затем начинает посылать "Hello world" навсегда.
Так что при использовании minicom все работает просто отлично.
Когда я использую свою программу в первый раз и жду, пока кнопка не будет нажата, мне кажется, что я ничего не могу прочитать из порта, даже если я нажимаю кнопку.
Затем я открываю Minicom, и он сразу начинает читать (потому что кнопка была нажата). Затем я закрываю Minicom, я открываю свою программу, и она отлично работает....
Кажется, возникают проблемы с открытием и закрытием файла (порта), но я не уверен. В любом случае, эта вещь недостаточно стабильна.
Любая помощь будет благодарна.
То, что я хочу написать, это читать постоянно с последовательного порта. Я читал о блокировке чтения, но когда я пытаюсь реализовать это, это, кажется, не работает.
Благодарю.
ОБНОВЛЕНИЕ ** Я просто добавил else if (wordsRead<0) printf ("Ошибка чтения \ n"); кажется, что он получает -1 при чтении в первый раз, но я не понимаю, почему это происходит Проблема в том, что когда он правильно читает с порта (после первого использования minicom), я получаю много чтений ошибок между "Привет, мир" печатает....
Вот мой код 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;
}
2 ответа
Хорошо, я нашел проблему...
Кажется, проблема была в том порядке, в котором я выполнял все действия по настройке атрибутов и т. Д.
Я изменил заказ на
- Определите нужные атрибуты -> параметры (новые).
- Откройте серийный порт.
- Получить существующие атрибуты -> oldoptions.
- Установите новые атрибуты -> параметры (новые).
- Читать из порта.
- Восстановите старые атрибуты -> oldoptions.
- Закройте порт.
Порядок до (не работал) был (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);
}
}
зр-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);
}
}
Это:
// create the struct
struct termios options;
создает неинициализированный struct termios
, Сначала вы должны выполнить инициализацию с текущими настройками порта, а затем изменить настройки:
// create the struct
struct termios options;
tcgetattr(fdSP, &options);