Linux系统LPT打印口批量产测工具

1 软件功能该软件用于在linux平台测试ch35x/ch38x(pci/pcie转串并口)的并口各引脚功能是否正常。方便对设备进行出厂测试。
2 并口测试硬件治具在测试前,需要制作单独的硬件治具,按下表连接信号线:
引脚连接示意图:

3 软件使用方法插入待测试pci/pcie转并口设备。输入lspci –v命令查看设备的枚举信息,若找到厂商id为[1c00]或[4348]的设备,则表示已经正常识别到该硬件。​
通过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;}


定义结构体的同时声明变量
物联网对于可回收包装能否有用处
引物和扩增子设计对DNA扩增成功有何影响
英飞凌最新技术助力用于工业通用电机驱动的22千瓦参考设计
物联网植保设备助力智慧农业的快速发展
Linux系统LPT打印口批量产测工具
光纤灯原理_光纤灯的优点
EEPROM存储器外设及驱动代码应用设计
华为推出“1+8+N”的总体战略规划
“2020华为生态合作伙伴走进和林格尔新区”活动成功举行
无刷直流电机和有刷直流电机的区别
苹果8上市最新消息:iPhone8价格是多少?它将会带给我们什么黑科技?
电流互感器在开关电源中的应用
填补南极低层大气温度的激光雷达探测空白
探讨国内IC设计行业发展新模式
Silicon Labs优化LifeSmart云起全新推出的智能家居面板,助其轻松实现全屋控制与连接
高通与中国众多行业开展合作将助力中国5G时代早日到来
MAX2170 VHF和L波段输入端口的S11参数
通信技术智能混合助千兆家庭在2013年成为现实
如何通过ESP8266/nodemcu和Arduino IDE来获取时间