2015/7/16

【治具】RS232 迴路測試每根Pin腳功能

RS232是個歷久不衰的訊號通訊協議,雖然在主流電腦上已經很難看見其蹤跡,但在伺服器或是嵌入式裝置乃至於近年很夯的物連網裝置都很容易見到,這篇文章主要記錄如何設計硬體治具並撰寫對應測試程式。

首先可以先參考RS232每根Pin腳的功能用途,網路上有大量文章介紹,就不再贅述,可以參考連結:Ethernut RS-232 Primer

先看做好的治具成品圖

治具硬體Rework
  1. 使用4.7kOhm電阻將TxD與RxD串接起來,如果只需要驗證資料傳輸只需做這部分重工即可,大部分情況下(未使用Hardware Flow Control)其他Pin腳都不會用到。
  2. 使用4.7kOhm電阻將DCD與DSR串接起來。
  3. 將DSR跟DTR直接短路串接。
  4. 使用4.7kOhm電阻將RI與CTS串接起來。
  5. 將CTS跟RTS直接短路串接。
測試概念
  1. 從TX發送資料,硬體TxD與RxD已經串接,因此會收到送出資料,確認收到資料並比對資料內容即可確認TxD與RxD腳位功能是否正常。
  2. 硬體RTS與CTS及RI串接,因此設置/重置RTS訊號,再讀取CTS與RI訊號即可確認這三根腳位功能是否正常。
  3. 硬體DTR與DSR及DCD串接,因此設置/重置DTR訊號,再讀取DSR與DCD訊號即可確認這三根腳位功能是否正常。
程式碼實做
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// File name: uart.c
// gcc -o uart uart.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <termios.h>

int main (int argc, char *argv[])
{
 int ret = 0;
 int len;
 unsigned char buf[16] = {0xAA, 0x55, 0x00, 0xFF,
    0x5A, 0xA5, 0xF0, 0x0F,
    0x01, 0x02, 0x04, 0x08,
    0x10, 0x20, 0x40, 0x80};
 unsigned char buf_rev[16];
 int fd;
 FILE *fp = NULL;
 int status;
 struct termios tio;
 
 if (argc <= 1) {
  fprintf(stderr, "Usage: %s <dev>\n", argv[0]);
  ret = 255;
  goto end;
 }

 fp = fopen (argv[1], "w+");
 if (fp == NULL) {
  puts ("Fail to open device");
  ret = 255;
  goto end;
 }
 
 printf ("+ TX: ");
 fflush (fp);
 len = fwrite (buf, sizeof (char), 16, fp);
 fflush (fp);
 if (len < 16) {
  puts ("Fail to transfer data");
  ret = 255;
  goto clean;
 }
 puts ("Pass");

 printf ("+ RX: ");
 len = fread (buf_rev, sizeof (char), 16, fp);
 if (len < 16) {
  puts ("Fail to receive data");
  ret = 255;
  goto clean;
 } else if (memcmp (buf, buf_rev, 16) != 0) {
  puts ("Check data fail");
  ret = 255;
  goto clean;
 }
 puts ("Pass");
 fclose (fp);
 fp = NULL;

 if ( (fd = open (argv[1], O_RDWR)) < 0 ) {
  puts ("Fail to open device");
  ret = 255;
  goto end;
 }

 tcgetattr(fd, &tio);
 printf ("RTS -> CTS - RI: ");
 status |= TIOCM_RTS;
 ioctl(fd, TIOCMSET, &status);
 ioctl(fd, TIOCMGET, &status);
 ret = status & (TIOCM_CTS | TIOCM_RNG); // Should be 0xA0

 status &= ~TIOCM_RTS;
 ioctl(fd, TIOCMSET, &status);
 ioctl(fd, TIOCMGET, &status);
 if ( (status & (TIOCM_CTS | TIOCM_RNG)) || ret != 0xA0) { // Status should be 0x00, false
  puts ("FAIL");
  if (ret == 0x0)
   puts ("  --> Case1: RTS fail; Case2: CTR & RI fail");
  else if (ret == 0x80)
   puts ("  --> CTS fail");
  else if (ret == 0x20)
   puts ("  --> RI fail");
  else
   puts ("  -> RTS fail");
  ret = 6;
  goto clean;
 } else {
  puts ("PASS");
  ret = 0;
 }

 printf ("DTR -> DSR - DCD: ");
 status |= TIOCM_DTR;
 ioctl(fd, TIOCMSET, &status);
 ioctl(fd, TIOCMGET, &status);
 ret = status & (TIOCM_DSR | TIOCM_CAR); // Should be 0x140
 status &= ~TIOCM_DTR;
 ioctl(fd, TIOCMSET, &status);
 ioctl(fd, TIOCMGET, &status);
 if ( (status & (TIOCM_DSR | TIOCM_CAR)) || ret != 0x140) { // Status should be 0x00, false
  puts ("FAIL");
  if (ret == 0x0)
   puts ("  --> Case1: DTR fail; Case2: DSR & DCD fail");
  else if (ret == 0x100)
   puts ("  --> DCD fail");
  else if (ret == 0x40)
   puts ("  --> DSR fail");
  else
   puts ("  -> RTS fail");
  ret = 7;
  goto clean;
 } else {
  puts ("PASS");
  ret = 0;
 }

clean:
 if (fp)
  fclose (fp);
 if (fd > 0)
  close (fd);
end:
 printf("Return Code: %d\n", ret);
 return ret;
}

參考連結

1 則留言:

  1. 板主您好,因為我只會硬體測試,在讀了您這篇後做了治具,但我不會將您的程式碼生成exe這種執行文件,可以請板主您指點做法,或是可以幫我生成exe再私信給我,我的信箱chungminsho@gmail.com

    回覆刪除