Thông báo

Collapse
No announcement yet.

Sử dụng cổng RS232 trên nền Linux

Collapse
This is a sticky topic.
X
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • #16
    Mặc dù Java được phát minh bởi hãng Sun, việc lập trình cổng RS232 bằng ngôn ngữ này không nhất thiết cứ phải dùng thư viện của Sun. Cộng đồng phần mềm tự do rộng lớn lắm, đơn cử có thể dùng thư viện RxTx này
    http://users.frii.com/jarvi/rxtx/index.html
    Mã mở nhé, giấy phép LGPL nhé, điều khiển cả cổng tuần tự RS232 lẫn cổng song song IEEE1284.

    Nhưng nói gì thì nói, trong thế giới Unix, C và C++ vẫn thống trị.
    Phần mềm tự do hoặc không dùng máy tính nữa !.

    Comment


    • #17
      Em xin bổ sung cho anh bqviet một chương trình test RS232 khá hay của ubuntu là minicom. Thằng này dùng giao diện dạng text thôi.

      Cài đặt: sudo spt-get install minicom

      Thông tin tìm hiểu chi tiết tại đây Em xin tạm copy một đoạn giới thiệu đầu của nó, chỉ là một cái overview thôi, em không dịch ra nhé:

      minicom is a communication program which somewhat resembles the shareware program TELIX but is free with source code and runs under most unices. Features include dialing directory with auto-redial, support for UUCP-style lock files on serial devices, a seperate script language interpreter, capture to file, multiple users with individual configurations, and more.
      Thằng Ubuntu có cái hay nữa là: em mới được mua con PC mạnh quá , không có cổng RS232 nên lấy cái cable USB-RS232, khi gõ lệnh dmesg thấy nó tự nhận được khỏi cần cài cắm gì cả, sướng quá vì đang tính phải mua cái PCI-RS232 he he ( usb 2-2: FTDI USB Serial Device converter now attached to ttyUSB0 ), nên bây giờ chỉ cần config COM Port lại thành ttyUSB0 là được.

      Để dùng thằng minicom với chú màu sắc và cho tiện dụng không phải gõ gì thêm thì định nghĩa lại biến môi trường MINICOM mà thằng minicom vẫn search ban đầu khi nó khởi động.
      Code:
      MINICOM='-m -c on'
      export MINICOM
      khi dùng minicom thì gõ lệnh minicom vào terminal là xong.

      Chúc mọi người thành công.
      Last edited by ngohaibac; 15-11-2008, 03:06.
      Technical sale at WT Microelectronics S'pore
      Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
      Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

      Comment


      • #18
        Nếu lập trình Python, hãy dùng PySerial, đơn giản như không thể đơn giản hơn!

        Comment


        • #19
          Cập nhập thêm 1 số điểm của Minicom làm đc không tốt (hay mình không nắm rõ) là buffer ngang của minicom không đủ nên khi serial console hoạt động thì hay bị mất thông tin phía cuối câu

          Điều này thì Cute com làm tương đối tốt nhưng có vùng hiển thị nhỏ và không hiểu được các kí tự theo chuẩn của stdio (như tab) nhưng bù lại cutecom cho phép ta log lại quá trình làm việc vào file.

          Giải pháp better hơn nữa là có thể dùng GTKterm terminal này hoạt động như minicom nhưng không bị lỗi buffer ngang và cung cấp cơ chế save lại toàn bộ quá trình làm việc,Vote cho GTKterm 5 sao.

          Sông dài, Thuyền lớn, Biển rộng bao la.
          Tháo neo ngôn ngữ, lèo lái con thuyền kiến thức nhân loại.

          Comment


          • #20
            Nguyên văn bởi quoc_thaibk Xem bài viết
            Cập nhập thêm 1 số điểm của Minicom làm đc không tốt (hay mình không nắm rõ) là buffer ngang của minicom không đủ nên khi serial console hoạt động thì hay bị mất thông tin phía cuối câu

            Điều này thì Cute com làm tương đối tốt nhưng có vùng hiển thị nhỏ và không hiểu được các kí tự theo chuẩn của stdio (như tab) nhưng bù lại cutecom cho phép ta log lại quá trình làm việc vào file.

            Giải pháp better hơn nữa là có thể dùng GTKterm terminal này hoạt động như minicom nhưng không bị lỗi buffer ngang và cung cấp cơ chế save lại toàn bộ quá trình làm việc,Vote cho GTKterm 5 sao.
            Số kí tự hiển thị trên 1 dòng ở Minicom phụ thuộc vào cửa sổ Terminal, nó không tự xuống dòng chứ không phải là buffer không đủ. Bạn thử kéo Terminal rộng ra, bằng bề rộng màn hình xem, rồi start Minicom, sẽ thấy là hiển thị rất ngọt ngào không sao cả.

            Nói thế thôi, chứ hầu hết các message rất ít khi quá dài như vậy (theo mình biết), như khi boot hệ điều hành thì qua console với bề rộng mặc định của Terminal thì chưa thấy thông tin nào bị thiếu chỗ hiển thị cả. Hay là mấy cái U-Boot nó khôn nhỉ

            Chúc bạn thành công.
            Technical sale at WT Microelectronics S'pore
            Hỗ trợ dự án sử dụng các hãng Texas Instrument, STMicro, Freescale, Fairchild, International Rectifier, Ublox, Lumiled, Maxim
            Liên hệ: 0915.560.511 hoặc ngo.haibac@wtmec.com

            Comment


            • #21
              Vote phát cho minicom, từ trước tới giờ xài mỗi nó nên không dám so sánh với các trình khác, chỉ biết là chưa thấy gì không hài lòng cả. Riêng việc log file thì tôi thường ssh vô máy Linux để chạy minicom thành ra xài luôn tính năng của ssh client rồi
              Some rights reserved!

              Comment


              • #22
                Asynchronous Notification

                Tiếp theo là một stuff khá hay cần được áp dụng trong embedded Linux:

                Giả sử có một chương trình chạy với vòng loop thực hiện nhiều xử lý (thường thấy trên các chương trình ứng dụng single task chạy trên VĐK thông thường). Cái mà chương cần hướng đến là việc thực thi đoạn code xử lý khi có incoming data và thực hiện sớm nhất nếu có thể. Hoặc như phần trên có giới thiệu về cơ chế gpio interrupt, tuy nhiên, hàm gpio inerrrupt chỉ thực hiện trong kernel space, làm cách nào ta có thể thông báo tín hiệu ngắt này lên user space? Điều này chỉ có thể thực hiện dựng thông qua cơ chế signal trong Linux.

                Linux cung cấp cơ chế Asynchronous Notification, thực hiện quá trình gửi signal SIGIO từ driver đến user program nhằm thông báo data đã hiện diện trong vùng đệm trong driver.

                - Để truyền và nhận signal đòi hỏi driver phải biết pid của chương trình ứng dụng, điều này được thực hiện thông qua fcntl system call (dùng lệnh F_SETOWN), hàm thực hiện chép PID của owner process vào filp->f_owner.pid, và kernel driver dùng pid này để biết rằng đích cần gửi signal đến là ai.
                - Để bật chức năng Asynchronous Notification, chương trình ứng dụng cần phải thực thi lệnh F_SETFL và bật cờ FASYNC.

                Các bước kích hoạt fasync trên chương trình ứng dụng như sau:
                Code:
                int pid = getipd ();                           /* get pid of process*/
                int oflags = fcntl (fd, F_GETFL);   /* read file status flag */
                fcntl (fd, F_SETOWN, getpid());     /* store pid of proccess */
                fcntl (fd, F_SETFL, oflags  |  FASYNC);


                Kế tiếp, chương trình catch signal được gửi đến theo các bước sau

                Code:
                struct sigaction action;
                memset (&action, 0, sizeof (action));       /* clean variable */
                action.sa_handler = signal_handler;      /* specify signal handler */
                action.sa_flags = 0;                                  /* operation flags setting */
                sigaction (SIGIO, &action, NULL);        /* attach action with SIGIO */
                Ví dụ như cổng COM, khi có data hiện diện trong bộ đệm, driver gửi signal SIGIO đến các process (đã đăng ký sử dụng fasync). Có thể tham khảo trong file tty_io.c trong source kernel.

                Chương trình sau cải tiến cho ví dụ "serial.c" ở trên, thực hiện fasync handler đọc data từ console UART0 và hiện lên console DBGU (file có tên là "tty_fasync.c"):

                Code:
                #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 <signal.h> /* Use signal */
                 
                /***********************************************************
                serial asynchronous notification example
                test on KM9260 development board
                using ttyS1 (UART0), on Externtion Connector (J16)
                ***********************************************************/
                int config_uart (int fd);
                void signal_handler (int signum);
                 
                #define BUFSZ 20
                char a[BUFSZ];
                int fd;
                 
                int main (int argc, char *argv[])
                {
                 
                const char *dev_name = "/dev/ttyS1";
                 
                struct sigaction action;
                memset (&action, 0, sizeof (action)); /* clean variable */
                action.sa_handler = signal_handler; /* specify signal handler */
                action.sa_flags = 0; /* operation flags setting */
                sigaction (SIGIO, &action, NULL); /* attach action with SIGIO */
                 
                 
                /* remove O_NDELAY if use blocking access */
                fd = open (dev_name , O_RDWR | O_NOCTTY | O_NDELAY);
                if (fd == -1)
                {
                printf ("-E- Cannot open %s \r\n", dev_name);
                return -1;
                }
                 
                printf ("-I- open %s success \r\n", dev_name);
                 
                if ( config_uart (fd) != 0 )
                {
                printf ("-E- cannot configure %s", dev_name);
                }
                 
                fcntl (fd, F_SETOWN, getpid());
                fcntl (fd, F_SETFL, fcntl(fd, F_GETFL) | FASYNC);
                 
                while (1)
                {
                /* do something here */
                usleep (100);
                }
                 
                printf ("-I- program terminated \r\n");
                 
                close (fd);
                 
                return 0;
                }
                 
                void signal_handler (int signum)
                {
                int i, count;
                if (signum == SIGIO)
                {
                count = read (fd, a, BUFSZ);
                if (count)
                {
                for (i = 0; i < count ; i++)
                {
                printf ("%c", a[i]);
                }
                printf ("\r\n");
                }
                /* flush data recieve but not read or not transmit */
                tcflush (fd, TCIOFLUSH);
                }
                return;
                }
                 
                int config_uart (int fd)
                {
                struct termios config;
                 
                // is a tty device ?
                if (!isatty (fd))
                {
                printf ("-E- not is a tty deive \r\n");
                return -1;
                }
                 
                // get the current port config
                if (tcgetattr (fd, &config) < 0)
                {
                printf ("-E- cannot get current config \r\n");
                return -1;
                }
                 
                config.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR |
                PARMRK | INPCK | ISTRIP | IXON);
                config.c_oflag = 0;
                config.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG);
                config.c_cflag &= ~(CSIZE | PARENB);
                config.c_cflag |= CS8;
                config.c_cc[VMIN] = 1;
                config.c_cc[VTIME] = 0;
                 
                if (cfsetispeed (&config, B115200) < 0 || cfsetospeed (&config, B115200) < 0)
                {
                printf ("-E- cannot set baudrate \r\n");
                return -1;
                }
                 
                if (tcsetattr (fd, TCSAFLUSH, &config) < 0)
                {
                printf ("-E- config failed \r\n");
                return -1;
                }
                 
                printf ("-I- config success \r\n");
                 
                return 0;
                }
                Khi có data, hàm signal_handler () được gọi, chương trình ứng dụng chỉ việc đọc dữ liệu về, tối đa là 20 ký tự.
                Nếu lượng ký tự đầu vào vượt quá 20, thì các ký tự thứ 21 trở đi trong bộ đệm của driver được xóa đi bởi hàm
                tcflush (fd, TCIOFLUSH). Điều này khắc phục hiện tượng "bad frame" khi truyền nhận dữ liệu với thiết bị ngoài.
                Nếu không flush sau mỗi lần đọc, thì có khả năng các ký tự dư của lần truyền trước kết hợp với lần truyền hiện tại
                gây ra frame dữ liệu sai.

                Để kết nối với thiết bị COM ngoài, ví dụ như máy đọc mã vạch, máy in hóa đơn... Chương trình ứng dụng cần được xây dựng protocol phù hợp để giao tiếp với thiết bị. Mỗi đơn vị giao tiếp có thể là 1 frame truyền, bao gồm các thành phần như Start Frame Byte, Total Byte Number, Check CRC...

                Trích từ tài liệu "KM9260_Technical_Reference_V1.0.pdf"
                Chúc thành công.
                Last edited by kamejoko80; 18-12-2009, 08:33.

                Comment


                • #23
                  Code:
                  // adrserial.c - Serial Port Test Example                  
                  #include <stdio.h>
                  #include <stdlib.h>
                  #include <string.h>
                  #include <unistd.h>
                  #include "adrport.h"  
                  
                  // this is the mainline thingee
                  #include <pthread.h>
                  
                  int gl_fd1 = 0;
                  int gl_fd2 = 0;
                  
                  void *ThreadSend( void *ptr )
                  {
                  	char sCmd[254];
                  	int iSpot;
                          strcpy(sCmd,"Cong COM 1");
                          iSpot = strlen(sCmd);
                          sCmd[iSpot] = 0x0d; // stick a <CR> after the command
                  	sCmd[iSpot+1] = 0x00; // terminate the string properly
                          int fd = *((int*) ptr);
                  	while (1)
                  	{
                  		if (WriteAdrPort(sCmd,fd)< 0) 
                  			break ;
                  		usleep(1000000); // give the ADR card some time to respond
                  	} // end while
                  }
                  
                  void signal_handler_1 (int signum)
                  {
                  	int i, count;
                  	if (signum == SIGIO)
                  	{
                  		char szData[255];
                  		ReadAdrPort(szData,254,gl_fd1);
                  		/* flush data recieve but not read or not transmit */
                  		tcflush (gl_fd1, TCIOFLUSH);
                  	}
                  	return;
                  }
                  void signal_handler_2 (int signum)
                  {
                  	int i, count;
                  	if (signum == SIGIO)
                  	{
                  	    char szData[255];
                  		ReadAdrPort(szData,254,gl_fd2);
                  		/* flush data recieve but not read or not transmit */
                  		tcflush (gl_fd2, TCIOFLUSH);
                  	}
                  	return;
                  }
                  int main(int argc, char *argv[]) 
                  { 
                  	if (argc != 3)
                  	{
                  		printf("adrserial needs 1 parameter for the serial port\n");
                  		printf("  ie. use 'adrserial 0' to connect to /dev/ttyS0\n");
                  		return 0;
                  	} // end if
                  	printf("Type q to quit.\n\n");
                  	gl_fd1 = OpenAdrPort(argv[1],gl_fd1);
                  	gl_fd2 = OpenAdrPort(argv[2],gl_fd2);
                  	if (gl_fd1 < 0) 
                  		return 0;
                  	if (gl_fd2 < 0) 
                  		return 0;
                  
                          tcflush(gl_fd1, TCIOFLUSH);
                          tcflush(gl_fd2, TCIOFLUSH);
                  	pthread_t thread1,thread2,thread3,thread4;
                  	pthread_create( &thread1, NULL, ThreadSend, &gl_fd2);
                  	//________________________________________________________________SINAL
                  	struct sigaction action_1;
                  	memset (&action_1, 0, sizeof (action_1)); /* clean variable */
                  	action_1.sa_handler = signal_handler_1; /* specify signal handler */
                  	action_1.sa_flags = 0; /* operation flags setting */
                  	sigaction (SIGIO, &action_1, NULL); /* attach action_1 with SIGIO */
                  	
                  	fcntl (gl_fd1, F_SETOWN, getpid());
                  	fcntl (gl_fd1, F_SETFL, fcntl(gl_fd1, F_GETFL) | FASYNC);
                  	//_________
                  	struct sigaction action_2;
                  	memset (&action_2, 0, sizeof (action_2)); /* clean variable */
                  	action_2.sa_handler = signal_handler_2; /* specify signal handler */
                  	action_2.sa_flags = 0; /* operation flags setting */
                  	sigaction (SIGIO, &action_2, NULL); /* attach action_2 with SIGIO */
                  	
                  	fcntl (gl_fd2, F_SETOWN, getpid());
                  	fcntl (gl_fd2, F_SETFL, fcntl(gl_fd2, F_GETFL) | FASYNC);
                  	//__________________________________________________________________________________________
                  	char sCmd[254];
                  	int iSpot;
                          strcpy(sCmd,"____Cong COm2___");
                  	iSpot = strlen(sCmd);
                  	sCmd[iSpot] = 0x0d; // stick a <CR> after the command
                  	sCmd[iSpot+1] = 0x00; // terminate the string properly
                  	while (1)
                  	{
                  		if (WriteAdrPort(sCmd,gl_fd2) < 0) 
                  			break ;
                  		usleep(1000000); // give the ADR card some time to respond
                  	} // end while
                  	
                  	CloseAdrPort(gl_fd1);
                  	CloseAdrPort(gl_fd2);
                  	return 0;
                  }
                  Code:
                  // adrport.h
                  #include <stdio.h>
                  #include <unistd.h>
                  #include <sys/types.h>
                  #include <sys/stat.h>
                  #include <fcntl.h>
                  #include <termios.h>
                  #include <string.h>
                  #include <errno.h>
                  int OpenAdrPort (char* sPortNumber,int fd);
                  int WriteAdrPort(char* psOutput,int fd);
                  int ReadAdrPort(char* psResponse, int iMax,int fd);
                  void CloseAdrPort(int fd);


                  Code:
                  // adrport.c - Serial Port Handler
                  
                  #include "adrport.h"
                  
                  // opens the serial port
                  // return code:
                  //   > 0 = fd for the port
                  //   -1 = open failed
                  int OpenAdrPort(char* sPortNumber,int fd)
                  {
                  	char sPortName[64];
                  	printf("in OpenAdrPort port#=%s\n", sPortNumber);
                  	sprintf(sPortName, "/dev/ttyS%s", sPortNumber);
                  	printf("sPortName=%s\n", sPortName);
                  
                  	// make sure port is closed
                  	CloseAdrPort(fd);
                  
                  	fd = open(sPortName, O_RDWR | O_NOCTTY | O_NDELAY);
                  	if (fd < 0)
                  	{
                  		printf("open error %d %s\n", errno, strerror(errno));
                  	}
                  	else
                  	{
                  		struct termios my_termios;
                  		tcgetattr(fd, &my_termios);
                  
                  		tcflush(fd, TCIFLUSH);
                  
                  		my_termios.c_cflag = B9600 | CS8 |CREAD | CLOCAL | HUPCL;
                  
                  		cfsetospeed(&my_termios, B9600);
                  		tcsetattr(fd, TCSANOW, &my_termios);
                  
                  	} // end if
                  	return fd;
                  } // end OpenAdrPort
                  
                  // writes zero terminated string to the serial port
                  // return code:
                  //   >= 0 = number of characters written
                  //   -1 = write failed
                  int WriteAdrPort(char* psOutput,int fd)
                  {
                  	int iOut;
                  	if (fd < 1)
                  	{
                  		printf(" port is not open\n");
                  		return -1;
                  	} // end if
                  	iOut = write(fd, psOutput, strlen(psOutput));
                  	if (iOut < 0)
                  	{
                  		printf("write error %d %s\n", errno, strerror(errno));
                  	}
                  	return iOut;
                  } // end WriteAdrPort
                  
                  // read string from the serial port
                  // return code:
                  //   >= 0 = number of characters read
                  //   -1 = read failed
                  int ReadAdrPort(char* psResponse, int iMax,int fd)
                  {
                  	int iIn;
                  	// printf("in ReadAdrPort iMax=%d\n", iMax);
                  	if (fd < 1)
                  	{
                  		printf(" port is not open\n");
                  		return -1;
                  	} // end if
                  	strncpy (psResponse, "N/A", iMax<4?iMax:4);
                  	iIn = read(fd, psResponse, iMax-1);
                  	if (iIn < 0)
                  	{
                  		if (errno == EAGAIN)
                  		{
                  			return 0; // assume that command generated no response
                  		}
                  		else
                  		{
                  			printf("read error %d %s\n", errno, strerror(errno));
                  		} // end if
                  	}
                  	else
                  	{
                  		psResponse[iIn<iMax?iIn:iMax] = '\0';
                  		printf("read %d chars: %s\n", iIn, psResponse);
                                  tcflush (fd, TCIOFLUSH);
                  	} // end if
                  
                  	return iIn;
                  } // end ReadAdrPort
                  
                  // closes the serial port
                  void CloseAdrPort(int fd)
                  {
                  	// you may want to restore the saved port attributes
                  	if (fd > 0)
                  	{
                  		close(fd);
                  	} // end if
                  } // end CloseAdrPort
                  mình làm thế này giống hệt bạn kamejoko mà cứ bị chạy liên tục không ngừng nghỉ mặc dù mình đã usleep cho nó tận 1 giây zồi mà nó cứ chạy rất nhanh vậy, ko rõ tại sao

                  makefile

                  Code:
                  CFLAGS=-g -Wall 
                  adrserial: adrserial.c adrport.c
                  	gcc -pthread -g -c -Wall adrserial.c -o adrserial.o
                  	gcc -pthread -g -c -Wall adrport.c -o adrport.o
                  	gcc -pthread adrport.o adrserial.o -o sonpipi

                  Comment


                  • #24
                    hay là mình chưa đặt 1 stop byte vào nhỉ

                    Comment


                    • #25
                      Nguyên văn bởi QT embedded Xem bài viết
                      Code:
                      // adrserial.c - Serial Port Test Example 
                      #include <stdio.h>
                      #include <stdlib.h>
                      #include <string.h>
                      #include <unistd.h>
                      #include "adrport.h" 
                       
                      // this is the mainline thingee
                      #include <pthread.h>
                       
                      int gl_fd1 = 0;
                      int gl_fd2 = 0;
                       
                      void *ThreadSend( void *ptr )
                      {
                      char sCmd[254];
                      int iSpot;
                      strcpy(sCmd,"Cong COM 1");
                      iSpot = strlen(sCmd);
                      sCmd[iSpot] = 0x0d; // stick a <CR> after the command
                      sCmd[iSpot+1] = 0x00; // terminate the string properly
                      int fd = *((int*) ptr);
                      while (1)
                      {
                      if (WriteAdrPort(sCmd,fd)< 0) 
                      break ;
                      usleep(1000000); // give the ADR card some time to respond
                      } // end while
                      }
                       
                      void signal_handler_1 (int signum)
                      {
                      int i, count;
                      if (signum == SIGIO)
                      {
                      char szData[255];
                      ReadAdrPort(szData,254,gl_fd1);
                      /* flush data recieve but not read or not transmit */
                      tcflush (gl_fd1, TCIOFLUSH);
                      }
                      return;
                      }
                      void signal_handler_2 (int signum)
                      {
                      int i, count;
                      if (signum == SIGIO)
                      {
                      char szData[255];
                      ReadAdrPort(szData,254,gl_fd2);
                      /* flush data recieve but not read or not transmit */
                      tcflush (gl_fd2, TCIOFLUSH);
                      }
                      return;
                      }
                      int main(int argc, char *argv[]) 
                      { 
                      if (argc != 3)
                      {
                      printf("adrserial needs 1 parameter for the serial port\n");
                      printf(" ie. use 'adrserial 0' to connect to /dev/ttyS0\n");
                      return 0;
                      } // end if
                      printf("Type q to quit.\n\n");
                      gl_fd1 = OpenAdrPort(argv[1],gl_fd1);
                      gl_fd2 = OpenAdrPort(argv[2],gl_fd2);
                      if (gl_fd1 < 0) 
                      return 0;
                      if (gl_fd2 < 0) 
                      return 0;
                       
                      tcflush(gl_fd1, TCIOFLUSH);
                      tcflush(gl_fd2, TCIOFLUSH);
                      pthread_t thread1,thread2,thread3,thread4;
                      pthread_create( &thread1, NULL, ThreadSend, &gl_fd2);
                      //________________________________________________________________SINAL
                      struct sigaction action_1;
                      memset (&action_1, 0, sizeof (action_1)); /* clean variable */
                      action_1.sa_handler = signal_handler_1; /* specify signal handler */
                      action_1.sa_flags = 0; /* operation flags setting */
                      sigaction (SIGIO, &action_1, NULL); /* attach action_1 with SIGIO */
                       
                      fcntl (gl_fd1, F_SETOWN, getpid());
                      fcntl (gl_fd1, F_SETFL, fcntl(gl_fd1, F_GETFL) | FASYNC);
                      //_________
                      struct sigaction action_2;
                      memset (&action_2, 0, sizeof (action_2)); /* clean variable */
                      action_2.sa_handler = signal_handler_2; /* specify signal handler */
                      action_2.sa_flags = 0; /* operation flags setting */
                      sigaction (SIGIO, &action_2, NULL); /* attach action_2 with SIGIO */
                       
                      fcntl (gl_fd2, F_SETOWN, getpid());
                      fcntl (gl_fd2, F_SETFL, fcntl(gl_fd2, F_GETFL) | FASYNC);
                      //__________________________________________________________________________________________
                      char sCmd[254];
                      int iSpot;
                      strcpy(sCmd,"____Cong COm2___");
                      iSpot = strlen(sCmd);
                      sCmd[iSpot] = 0x0d; // stick a <CR> after the command
                      sCmd[iSpot+1] = 0x00; // terminate the string properly
                      while (1)
                      {
                      if (WriteAdrPort(sCmd,gl_fd2) < 0) 
                      break ;
                      usleep(1000000); // give the ADR card some time to respond
                      } // end while
                       
                      CloseAdrPort(gl_fd1);
                      CloseAdrPort(gl_fd2);
                      return 0;
                      }
                      Code:
                      // adrport.h
                      #include <stdio.h>
                      #include <unistd.h>
                      #include <sys/types.h>
                      #include <sys/stat.h>
                      #include <fcntl.h>
                      #include <termios.h>
                      #include <string.h>
                      #include <errno.h>
                      int OpenAdrPort (char* sPortNumber,int fd);
                      int WriteAdrPort(char* psOutput,int fd);
                      int ReadAdrPort(char* psResponse, int iMax,int fd);
                      void CloseAdrPort(int fd);


                      Code:
                      // adrport.c - Serial Port Handler
                       
                      #include "adrport.h"
                       
                      // opens the serial port
                      // return code:
                      // > 0 = fd for the port
                      // -1 = open failed
                      int OpenAdrPort(char* sPortNumber,int fd)
                      {
                      char sPortName[64];
                      printf("in OpenAdrPort port#=%s\n", sPortNumber);
                      sprintf(sPortName, "/dev/ttyS%s", sPortNumber);
                      printf("sPortName=%s\n", sPortName);
                       
                      // make sure port is closed
                      CloseAdrPort(fd);
                       
                      fd = open(sPortName, O_RDWR | O_NOCTTY | O_NDELAY);
                      if (fd < 0)
                      {
                      printf("open error %d %s\n", errno, strerror(errno));
                      }
                      else
                      {
                      struct termios my_termios;
                      tcgetattr(fd, &my_termios);
                       
                      tcflush(fd, TCIFLUSH);
                       
                      my_termios.c_cflag = B9600 | CS8 |CREAD | CLOCAL | HUPCL;
                       
                      cfsetospeed(&my_termios, B9600);
                      tcsetattr(fd, TCSANOW, &my_termios);
                       
                      } // end if
                      return fd;
                      } // end OpenAdrPort
                       
                      // writes zero terminated string to the serial port
                      // return code:
                      // >= 0 = number of characters written
                      // -1 = write failed
                      int WriteAdrPort(char* psOutput,int fd)
                      {
                      int iOut;
                      if (fd < 1)
                      {
                      printf(" port is not open\n");
                      return -1;
                      } // end if
                      iOut = write(fd, psOutput, strlen(psOutput));
                      if (iOut < 0)
                      {
                      printf("write error %d %s\n", errno, strerror(errno));
                      }
                      return iOut;
                      } // end WriteAdrPort
                       
                      // read string from the serial port
                      // return code:
                      // >= 0 = number of characters read
                      // -1 = read failed
                      int ReadAdrPort(char* psResponse, int iMax,int fd)
                      {
                      int iIn;
                      // printf("in ReadAdrPort iMax=%d\n", iMax);
                      if (fd < 1)
                      {
                      printf(" port is not open\n");
                      return -1;
                      } // end if
                      strncpy (psResponse, "N/A", iMax<4?iMax:4);
                      iIn = read(fd, psResponse, iMax-1);
                      if (iIn < 0)
                      {
                      if (errno == EAGAIN)
                      {
                      return 0; // assume that command generated no response
                      }
                      else
                      {
                      printf("read error %d %s\n", errno, strerror(errno));
                      } // end if
                      }
                      else
                      {
                      psResponse[iIn<iMax?iIn:iMax] = '\0';
                      printf("read %d chars: %s\n", iIn, psResponse);
                      tcflush (fd, TCIOFLUSH);
                      } // end if
                       
                      return iIn;
                      } // end ReadAdrPort
                       
                      // closes the serial port
                      void CloseAdrPort(int fd)
                      {
                      // you may want to restore the saved port attributes
                      if (fd > 0)
                      {
                      close(fd);
                      } // end if
                      } // end CloseAdrPort
                      mình làm thế này giống hệt bạn kamejoko mà cứ bị chạy liên tục không ngừng nghỉ mặc dù mình đã usleep cho nó tận 1 giây zồi mà nó cứ chạy rất nhanh vậy, ko rõ tại sao

                      makefile

                      Code:
                      CFLAGS=-g -Wall 
                      adrserial: adrserial.c adrport.c
                      gcc -pthread -g -c -Wall adrserial.c -o adrserial.o
                      gcc -pthread -g -c -Wall adrport.c -o adrport.o
                      gcc -pthread adrport.o adrserial.o -o sonpipi
                      Mình cũng đang gặp vấn đề ở chỗ này. Mình nhìn trong Code không thấy có đoạn nào nó clear cài buffer nhận cả, không biết là nó có tự clear hay là do thiếu lệnh nào. Mình search mà chưa thấy lệnh clear buffer, hic 1 tuần rồi

                      Comment


                      • #26
                        Oh xin lỗi, mình vội quá nên nhìn lộn trong Code của bạn có dòng.
                        tcflush (fd, TCIOFLUSH);
                        Bản nguyên thủy trên internet thì không có

                        Comment


                        • #27
                          chào các bạn tình hình cuối tuần tới mình phải nộp báo cáo tìm hiểu về lập trình giao tiếp com 232 trên pc cái ubuntu bằng Qt. Nhưng mình do khả năng tìm hiểu kém và thực sự là mình thấy mình kém lên nhờ các bạn giúp. mình đã cài được Qt 4.7 rồi. mình đọc thấy bạn bqviet nói dùng thư viện QextSerialPort , mình đã tải thư viện này : cụ thẻ mình tải gói này về ko bít có đúng ko : qextserialport.1.2win-alpha2.zip. nhưng mình ko bít cách add thư viện vào Qt của mình. các bạn ai biết giúp mình với.
                          mình trước tiên add thư viện vào đã. còn các sử dụng lớp phuơng thức trong thư viện mình sẽ hỏi sau.
                          các cậu ai biết có thể add nick yahoo giúp mình tiện hơi, cảm ơn các bạn rất nhiều. các bạn giúp được mình chắc mình sẽ bớt lo mối học lại môn lập trình hệ nhúng và cảm thấy mình đỡ xấu hỏi khi gặp thầy.

                          yahoo : song_voi_hien_tai

                          tksssssssssss

                          Comment


                          • #28
                            Lập trình trên Ubuntu mà lại tải về thư viện cho Windows thì làm sao mà chạy được. Ngay cái tên file qextserialport.1.2win-alpha2.zip đã nói rõ tất cả rồi.

                            Cần tải về ít nhất một trong hai tập tin sau (là mã nguồn thư viện dùng cho cả Windows lẫn Linux)
                            qextserialport-1.2beta2.tar.gz - qextserialport - Released in 2012 for Qt4& Qt5 - Serial port library for Qt2, Qt3, Qt4 and Qt5 - Google Project Hosting

                            hoặc
                            qextserialport-1.1.tar.gz - qextserialport - Released in 2007 for Qt4 - Serial port library for Qt2, Qt3, Qt4 and Qt5 - Google Project Hosting

                            Sau đó giải nén và đọc tập tin README là xong. Cách dùng cực kỳ dễ. Tuy nhiên trước tiên người lập trình phải viết được một chương trình tối giản dùng thư viện Qt đã. Ít nhất là chương trình phải chạy rồi in ra dòng chữ kiểu như "Hello, world!" ở cửa sổ dòng lệnh. Tiếp đến là chương trình bật lên một cái cửa sổ hoặc hộp thoại chẳng hạn. Không thể viết ngay một chương trình to được đâu.
                            Phần mềm tự do hoặc không dùng máy tính nữa !.

                            Comment


                            • #29
                              cảm ơn bạn đã giúp nhưng mình vẫn chẳng thể build được, lỗi nhiều quá. mình đã tạo project giống hệt từ tên đến các lớp giống hệt nhưng mà không thể chạy được. cứ tình hình này mình chắc ko còn mặt mủi gặp thầy. nhờ bạn bè trên lớp thì lại không chung đề tài. mình hi vọng có thể gặp cậu nhờ cậu chỉ giúp mình sẽ hậu tạ cậu pqviet à. hoặc cậu có thể làm cho mình cái project được không .mình sẻ nạp thể tiền điện thoại cho cậu như là lời cảm ơn chân thành vì sự giúp đỡ của cậu. các cụ nói mà ; học thầy không bằng học bạn. thực sự lúc này mình chỉ biết trông chờ vào sự giúp đỡ thôi.

                              tớ thực sự đang bế tắc không thể nào chạy được mặc dù add đầy đủ các lớp hay tạo ra project giống hệt.

                              nếu ai đó giúp đỡ tôi thì thực sự đó là niềm hạnh phúc nhất như vị cứu tinh vậy.

                              địa chỉ của tôi là :
                              yahoo tôi : song_voi_hien_tai
                              gmail : truong3288@gmail.com
                              Last edited by okmen; 05-12-2012, 20:56.

                              Comment


                              • #30
                                Đây là một project Qt tối thiểu, chỉ bật lên một cửa sổ QMainWindows trong đó có 1 cái QTextedit, kết hợp thư viện Qextserialport (đã kèm sẵn) mà bqv dùng làm template cho các dự án chuyên nghiệp. Xin nhấn mạnh đây là tối giản, không để giản lược hơn được nữa. Hy vọng nó có ích cho ai đó mới bắt đầu học, nếu vẫn không đọc hiểu được mã nguồn của nó thì trên đời này không còn cách nào khác để học Qt + Qextserialport nữa !


                                Cách dùng
                                1. Máy tính cần cài đặt ít nhất các gói phần mềm sau : build-essential và libqt4-dev. Nếu chưa có, từ terminal dùng lệnh
                                Code:
                                sudo apt-get install build-essential libqt4-dev
                                2. Tải về và giải nén
                                Code:
                                unzip minimal_qt_app.zip
                                3. Chuyển vào thư mục project này
                                Code:
                                cd minimal_qt_app
                                4. Sinh makefile
                                Code:
                                qmake
                                5. Biên dịch phần mềm
                                Code:
                                make
                                6. Chạy thử
                                Code:
                                ./main
                                Đơn giản vậy thôi.

                                minimal_qt_app.zip
                                Phần mềm tự do hoặc không dùng máy tính nữa !.

                                Comment

                                Về tác giả

                                Collapse

                                bqviet Tìm hiểu thêm về bqviet

                                Bài viết mới nhất

                                Collapse

                                Đang tải...
                                X