1 軟件功能
該軟件用于在Linux平臺測試CH35X/CH38X(PCI/PCIe轉串并口)的并口各引腳功能是否正常。方便對設備進行出廠測試。
2 并口測試硬件治具
引腳連接示意圖:
?
3 軟件使用方法
?
- 通過lsmod命令查看設備關聯驅動是否已加載,設備所需驅動包括:parport、parport_pc、lp驅動。驅動加載后,查看系統/dev目錄,會多出parportX(X為數字)節點,示例:
?
- 編譯測試程序,生成目標可執行程序,輸入./parport_test -D /dev/parport0 –h命令查看幫助,輸出其他命令無效。運行程序:[可執行文件名] -D [設備節點名稱] –s
?
4 測試錯誤碼說明
根據輸出的錯誤碼和終端輸出信息可判斷故障信號線,下表為錯誤碼和說明。
錯誤碼 | 錯誤碼說明 |
---|---|
0 | STB-D0通訊錯誤 |
1 | AFD-D1通訊錯誤 |
2 | INIT-D2通訊錯誤 |
3 | SIN-D3通訊錯誤 |
4 | D6-ERR通訊錯誤 |
5 | D4-SELT通訊錯誤 |
6 | D5-PE通訊錯誤 |
7 | D6-ACK通訊錯誤 |
8 | D7-BUSY通訊錯誤 |
5 測試實例
測試成功實例
測試錯誤實例
?
根據輸出信息,D4-SELT、D5-PE、D6-ACK和D7-BUSY信號通訊存在錯誤。
?
根據輸出信息,STB-D0信號通訊存在錯誤。
6、wchparporttest工具源碼
/*
* parport factory test utility.
*
* Copyright (C) 2023 Nanjing Qinheng Microelectronics Co., Ltd.
* Web: http://wch.cn
* Author: WCH
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define GET_BIT(x, y) ((x >> y) & 0x01) /* get y bit value of x */
#define CTRL_REG_INITVAL_OUT 0xc0 /* control reg value(allow D7-D0 output) */
#define CTRL_REG_INITVAL_IN 0xe0 /* control reg value(forbid D7-D0 output) */
static unsigned char ctrlval = 0;
static char device_name[20];
/**
* ctrl_reg_update: update PCR reg
* @fd: file descriptor
* @mask: bits to update
* @val: 0->clear, 1->set
*/
void ctrl_reg_update(int fd, unsigned char mask, unsigned char val)
{
int ret;
ctrlval &= ~mask;
ctrlval |= val & mask;
ret = ioctl(fd, PPWCONTROL, &ctrlval);
if (ret < 0) {
perror("ioctl");
return;
}
}
/**
* data_line_init: data signals direction initialization
* @fd: file descriptor
* @dir: direction value
*
* The function return 0 if successful, others if fail.
*/
int data_line_init(int fd, int dir)
{
int ret;
if (dir == 0)
ctrlval = CTRL_REG_INITVAL_IN;
else
ctrlval = CTRL_REG_INITVAL_OUT;
ret = ioctl(fd, PPWCONTROL, &ctrlval);
if (ret < 0) {
perror("ioctl");
return -1;
}
return 0;
}
/**
* data_reg_read: read data signals
* @fd: file descriptor
*
* The function return positive if successful, negative if fail.
*/
unsigned char data_reg_read(int fd)
{
int ret;
unsigned char data_r;
ret = ioctl(fd, PPRDATA, &data_r);
if (ret < 0) {
perror("ioctl");
return -1;
}
return data_r;
}
/**
* print_err_msg: print message according to error code
* @err_code: error number
*
*/
static void print_err_msg(int err_code)
{
switch (err_code) {
case 0:
printf("[error code: %d] STB-D0 ERROR
", err_code);
break;
case 1:
printf("[error code: %d] AFD-D1 ERROR
", err_code);
break;
case 2:
printf("[error code: %d] INIT-D2 ERROR
", err_code);
break;
case 3:
printf("[error code: %d] SIN-D3 ERROR
", err_code);
break;
case 4:
printf("[error code: %d] D6-ERR ERROR
", err_code);
break;
case 5:
printf("[error code: %d] D4-SELT ERROR
", err_code);
break;
case 6:
printf("[error code: %d] D5-PE ERROR
", err_code);
break;
case 7:
printf("[error code: %d] D6-ACK ERROR
", err_code);
break;
case 8:
printf("[error code: %d] D7-BUSY ERROR
", err_code);
break;
default:
break;
}
}
/**
* check_result: detect whether the current register value matches the target value related bits, and print in case of error
* @type: test type, 0x01: control line output, data line input, 0x02: data line output, status line input
* @val: current register value
* @cmp_val: target register value
*
* The function return 0 if successful, negative if fail.
*/
static int check_result(int type, unsigned char val, unsigned char cmp_val)
{
int i;
int ret = 0;
if (type == 0x01) {
for (i = 0; i < 4; i++) {
if (GET_BIT(val, i) != GET_BIT(cmp_val, i)) {
ret = -1;
print_err_msg(i);
}
}
} else if (type == 0x02) {
for (i = 3; i < 8; i++) {
if (GET_BIT(val, i) != GET_BIT(cmp_val, i)) {
ret = -1;
print_err_msg(i + 1);
}
}
} else {
printf("type error.n");
return -1;
}
return ret;
}
static const struct option lopts[] = {
{ "device name", required_argument, 0, 'd' },
{ "start test", no_argument, 0, 's' },
{ "view the usage method", no_argument, 0, 'h' },
{ NULL, 0, 0, 0 },
};
static void print_usage(const char *prog)
{
printf("Usage: %s [-dsh]
", prog);
puts(" -d device name
"
" -s start test
"
" -h view the usage method");
exit(1);
}
static void help_msg(void)
{
puts("Pin connection mode of parport test:
"
"test1(PDR OUT/PSR IN): D6-ERR D4-SELT D5-PE D6-ACK
"
"test2(PCR OUT/PIR IN): STB-D0 AFD-D1 INIT-D2 SIN-D3 D7-BUSY");
exit(1);
}
static void parse_opts(int argc, char *argv[])
{
char c;
if (argc != 4)
print_usage(argv[0]);
while (1) {
c = getopt_long(argc, argv, "d:sh", lopts, NULL);
if (c == -1)
break;
switch (c) {
case 'd':
memcpy(device_name, argv[2], strlen(argv[2]));
break;
case 's':
printf("start test...
");
break;
case 'h':
help_msg();
break;
default:
print_usage(argv[0]);
break;
}
}
}
int main(int argc, char **argv)
{
int fd;
int retval;
int ret_check1, ret_check2, ret_check3, ret_check4;
unsigned char data_w, status_r;
parse_opts(argc, argv);
/* Open parport device */
fd = open(device_name, O_RDWR);
if (fd < 0) {
perror("open");
return -1;
}
/* Claim the port */
if ((retval = ioctl(fd, PPCLAIM)) < 0) {
perror("PPCLAIM failed");
goto exit;
}
/* Set the direction of D0-D7 to output */
if ((retval = data_line_init(fd, 0x01)) < 0)
goto exit;
/* Set D0-D7 output low level */
data_w = 0x00;
if ((retval = ioctl(fd, PPWDATA, &data_w)) < 0) {
perror("PPWDATA ioctl");
goto exit;
}
/* Read BUSY, ACK, PE, SELT and ERR signal, judge whether they are all low */
if ((retval = ioctl(fd, PPRSTATUS, &status_r)) < 0) {
perror("PPRSTATUS ioctl");
goto exit;
}
ret_check1 = check_result(0x02, status_r, 0x87);
/* Set D4-D7 output high level */
data_w = 0xf0;
if ((retval = ioctl(fd, PPWDATA, &data_w)) < 0) {
perror("PPWDATA ioctl");
goto exit;
}
/* Read BUSY, ACK, PE, SELT and ERR signal, judge whether they are all high */
if ((retval = ioctl(fd, PPRSTATUS, &status_r)) < 0) {
perror("PPRSTATUS ioctl");
goto exit;
}
ret_check2 = check_result(0x02, status_r, 0x7b);
/* Set the direction of D0-D7 to input */
if ((retval = data_line_init(fd, 0x00)) < 0)
goto exit;
/* Set SIN, INIT, AFD and STB output low level */
ctrl_reg_update(fd, 0x0f, 0x0b);
/* Read D0-D4 signal, judge whether they are all low */
ret_check3 = check_result(0x01, data_reg_read(fd), 0xf0);
/* Set SIN, INIT, AFD and STB output high level */
ctrl_reg_update(fd, 0x0f, 0x04);
/* Read D0-D4 signal, judge whether they are all high */
ret_check4 = check_result(0x01, data_reg_read(fd), 0xff);
if ((ret_check1 == 0) && (ret_check2 == 0) && (ret_check3 == 0) && (ret_check4 == 0))
printf("Parport pin test passed
");
else
printf("Parport pin test failed
");
exit:
/* Release the port */
if (ioctl(fd, PPRELEASE) < 0)
perror("PPRELEASE failed");
close(fd);
return retval;
}
?審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
Linux
+關注
關注
87文章
11229瀏覽量
208927 -
PCIe
+關注
關注
15文章
1217瀏覽量
82445 -
命令
+關注
關注
5文章
678瀏覽量
21984 -
并口
+關注
關注
0文章
32瀏覽量
17519 -
LPT
+關注
關注
0文章
6瀏覽量
3942
發布評論請先 登錄
相關推薦
南京沁恒微USB 轉打印口芯片 CH340
CH340 是一個 USB 總線的轉接芯片,實現 USB 轉串口或者 USB 轉打印口。
在打印口方式下,CH340 提供了兼容 USB 規范和 Windows 操作系統的標準 USB 打印口
發表于 05-16 13:51
求助各位大俠主板上25針LPT口連接并口編程器問題
確定以下條件是否滿足:1. 與編程器通訊前,接通編程器電源.2. 編程器與計算機的打印口相連.3. 計算機打印口地址為0x278,0x378或0x3bc.我確認我接了電源,接線沒有出錯,并口地址是0x378.哪位大俠知道這是為什么,求指教啊!!
發表于 06-28 10:00
如何利用單片機和USB總線接口芯片實現LPT-USB打印機的驅動器設計
本文利用單片機和USB總線接口芯片實現LPT-USB打印機的驅動器設計。利用該設計將能夠實現并行打印口數據可以在USB打印機上的直接打印工作
發表于 04-26 06:36
基于VB6.0的打印口(LPT)的應用
在 VB6.0 編程環境下,調用動態鏈接庫,通過打印口(LPT)實現PC 機對89C2051 單片機的編程。關鍵詞: VB6.0 語言 89C2051 單片機動態鏈接庫(DL
發表于 09-11 09:13
?39次下載
PC機打印口與便攜式數據采集系統接口設計
介紹了PC 機打印口與外設的接口設計方法,巧妙地解決了打印口對大容量存儲器的數據讀取問題,并利用雙端口RAM 在板存儲技術,設計了基于PC 機打印口的便攜式數據采集系統。文章闡
發表于 07-19 15:11
?36次下載
評論