TestSerial.h /* * TestSerial.h * * Created on: 2009-12-18 * Author: Administrator */ #ifndef TESTSERIAL_H_ #define TESTSERIAL_H_ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <malloc.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <termios.h> #include <sys/time.h> #include <pthread.h> #include <math.h> #include <hw/inout.h> #include "TestDebug.h" // 串口相关端口地址定义 #define SERIAL_PORT_BASE_1 0x000003f8 #define SERIAL_PORT_BASE_2 0x000002f8 #define SERIAL_PORT_BASE_3 0x000003e8 #define SERIAL_PORT_BASE_4 0x000002e8 //#define SERIAL_PORT_BUFFER SERIAL_PORT_BASE #define SERIAL_PORT_IER 1 #define SERIAL_PORT_FIFO 2 #define SERIAL_PORT_LCR 3 #define SERIAL_PORT_MCR 4 #define SERIAL_PORT_LSR 5 #define SERIAL_PORT_MSR 6 #define IIR_MS_ID 0x00 // Modem status #define IIR_RX_ID 0x04 // Rceived data OK,and to read the receive buffer #define IIR_TX_ID 0x02 // Transmitter holding register empty #define IIR_MASK 0x07 // Get the low 3 bits of IIR void test_serial_listener(); unsigned long test_serial_sender(); unsigned long serial_send(); void serial_port_init(unsigned long addr_base); unsigned long serial_port_io_test(unsigned long port_base); unsigned long serial_port_loopmode_test(unsigned long port_num); unsigned long serial_port_self_test(unsigned long port_num); unsigned long serial_port_remote_test(unsigned long port_num); unsigned long serial_port_test(unsigned long device, unsigned long cmd); #endif /* TESTSERIAL_H_ */ TestSerial.c /* * TestSerial.c * * Created on: 2009-12-18 * Author: Administrator */ #include "TestSerial.h" /* * 打开端口,返回端口句柄,为-1时无效(打开失败) * 输入参数:打开端口号,默认为ser1 * 目前仅实现打开ser1 */ int open_serial(int port) { int fd; char str_port[MAX_PATH]; sprintf(str_port, "/dev/ser%d", port); // 读写方式打开串口 if (port > 0) { fd = open(str_port, O_RDWR); } else { fd = open("/dev/ser1", O_RDWR); } return fd; } /* * 设置前面打开的串口波特率 */ void set_serial(int fd, int baud) { struct termios opt; tcgetattr(fd, &opt); cfmakeraw(&opt); cfsetispeed(&opt, baud); //波特率设置为9600bps cfsetospeed(&opt, baud); tcsetattr(fd, TCSANOW, &opt); return; } /* * 接收线程函数 */ void *rec_thread() { // 接收缓冲区 unsigned char buf[MAX_BUFLEN]; // 接收缓冲区长度 int ncount = 0; // 设备描述符 int fd; int i; fd = open_serial(2); if (fd <= 0) { perror("open serial"); return NULL; } set_serial(fd, MY_BAUD); #ifdef __DEBUG__ printf("Serial receiver begins working for receiving data.../n"); #endif while (1) //循环读取数据 { ncount = read(fd, buf, MAX_BUFLEN); if (ncount > 0) { #ifdef __DEBUG__ printf("/nSerial receiver receive data, length is %d, data: /n/t", ncount); for (i = 0; i < ncount; i++) { printf("%#04X ", buf[i]); } printf("/n"); #endif } } } void create_recvthread() { pthread_t thread; memset(&thread, 0, sizeof(thread)); // 创建线程 if (pthread_create(&thread, NULL, rec_thread, NULL) != 0) { perror("Create serial receiver thread failed!/n"); } else { #ifdef __DEBUG__ printf("Create serial receiver thread success!/n"); #endif } return; } /* * 接收数据测试函数,启动接收线程 */ void test_serial_listener() { create_recvthread(); return; } /* * 发送心跳包,发送从串口1发出的预定义格式的心跳包 */ unsigned long serial_send_Tick() { int flag_close; int fd = 0; // 待发送的内容 unsigned char buf[MAX_PATH] ; unsigned long device = DEVICE_SERIAL_01; //设备选定为COM1口 unsigned long cmd = TEST_TICK_SER; unsigned int state = DEVICE_NO_ERROR; unsigned char *pdata = buf; unsigned long buflen = 0; // 清空内存 memset(pdata, 0, MAX_PATH); // 组织发送的内容 memcpy(pdata, COMM_HEADER, strlen(COMM_HEADER)); buflen += strlen(COMM_HEADER); pdata += strlen(COMM_HEADER); memcpy(pdata, &device, sizeof(device)); buflen += sizeof(device); pdata += sizeof(device); memcpy(pdata,&cmd,sizeof(cmd)); buflen += sizeof(cmd); pdata += sizeof(cmd); memcpy(pdata,&state,sizeof(state)); buflen += sizeof(state); pdata +=sizeof(state); int result = 0; unsigned long ret = DEVICE_ERROR; if ((fd = open_serial(1)) == 0) { perror("open serial"); return ret; } set_serial(fd, MY_BAUD); #ifdef __DEBUG__ printf("Serial sender begins sending data.../n"); #endif result = write(fd, buf, buflen); if (result == -1) { perror("write"); } else { if (result == buflen) ret = DEVICE_NO_ERROR; } flag_close = close(fd); if (flag_close == -1) { #ifdef __DEBUG__ perror("Close the Device"); #endif } return ret; } /* * 发送测试结果函数 */ unsigned long serial_send(unsigned long device,unsigned long cmd,unsigned long state ) { int flag_close; int fd = 0; // 待发送的内容 unsigned char buf[MAX_PATH] ; unsigned char *pdata = buf; unsigned long buflen = 0; // 清空内存 memset(pdata, 0, MAX_PATH); // 组织发送的内容 memcpy(pdata, COMM_HEADER, strlen(COMM_HEADER)); buflen += strlen(COMM_HEADER); pdata += strlen(COMM_HEADER); memcpy(pdata, &device, sizeof(device)); buflen += sizeof(device); pdata += sizeof(device); memcpy(pdata,&cmd,sizeof(cmd)); buflen += sizeof(cmd); pdata += sizeof(cmd); memcpy(pdata,&state,sizeof(state)); buflen += sizeof(state); pdata +=sizeof(state); int result = 0; unsigned long ret = DEVICE_ERROR; if ((fd = open_serial(1)) == 0) { perror("open serial"); return ret; } set_serial(fd, MY_BAUD); #ifdef __DEBUG__ printf("Serial sender begins sending data.../n"); #endif result = write(fd, buf, buflen); if (result == -1) { perror("write"); } else { if (result == buflen) ret = DEVICE_NO_ERROR; } flag_close = close(fd); if (flag_close == -1) { #ifdef __DEBUG__ perror("Close the Device"); #endif } return ret; } /* * 发送数据测试函数,自动发送预定义数据测试 */ unsigned long test_serial_sender() { int flag_close; int fd = 0; // 待发送的内容 char buf[MAX_PATH] = { "serial test." }; int length = strlen(buf); int result = 0; unsigned long ret = DEVICE_ERROR; if ((fd = open_serial(1)) == 0) { perror("open serial"); return ret; } set_serial(fd, MY_BAUD); #ifdef __DEBUG__ printf("Serial sender begins sending data.../n"); #endif result = write(fd, buf, length); if (result == -1) { perror("write"); } else { if (result == length) ret = DEVICE_NO_ERROR; } flag_close = close(fd); if (flag_close == -1) { #ifdef __DEBUG__ perror("Close the Device"); #endif } return ret; } // 允许/禁止串口回环模式 void enable_serial_loopmode(unsigned long addr_base, unsigned char enable) { unsigned long port_mcr = addr_base + SERIAL_PORT_MCR; unsigned char status = in8(port_mcr); if (enable) { status = status | 0x10; // out8(port_mcr, 0x13); } else { status = ((status >> 5) << 5) + (status & 0x0F); // out8(port_mcr, 0x0B); } out8(port_mcr, status); return; } // 允许/禁止串口中断 void enable_serial_interrupt(unsigned long addr_base, unsigned char enable) { unsigned long port_mcr = addr_base + SERIAL_PORT_MCR; unsigned char status = in8(port_mcr); if (enable) { status = status | 0x08; // out8(port_mcr, 0x08); } else { status = ((status >> 4) << 4) + (status & 0x07); // out8(port_mcr, 0x00); } out8(port_mcr, status); } //// 检测接收到的数据准备好 //unsigned char wait_serial_data(unsigned long addr_base) { // // unsigned long port_lsr = addr_base + SERIAL_PORT_LSR; // // int count = 0; // unsigned char ch = 0; // do { // ch = in8(port_lsr); // if (ch & 1) // break; // count++; // delay(1); // } while (count < WAIT_TIMES); // //#ifdef __DEBUG__ // printf("Func:Wait_RecvData_Is_Ready ch is %x, count is %d /n", ch, count); //#endif // // return ((count == WAIT_TIMES) ? FALSE : TRUE); //} // //// 读写数据检测串口 //unsigned char serial_port_iotest(unsigned long addr_base, // unsigned char testcode) { // // unsigned long port_buf = addr_base; // // unsigned char temp = 0; // // out8(port_buf, testcode); // //#ifdef __DEBUG__ // printf("Func:IoTest Write to BUFFER is %x/n", testcode); //#endif // // if (!wait_serial_data(port_buf)) // return FALSE; // temp = in8(port_buf); // //#ifdef __DEBUG__ // printf("Func:IoTest read from BUFFER is %x/n", temp); //#endif // // if (temp == testcode) // return TRUE; // return FALSE; //} // 串口初始化代码, 设置波特率、数据位、停止位、数据流控制等选项 void serial_port_init(unsigned long addr_base) { unsigned char Setting = 0; unsigned long port_ier = addr_base + SERIAL_PORT_IER; unsigned long port_lcr = addr_base + SERIAL_PORT_LCR; unsigned long port_mcr = addr_base + SERIAL_PORT_MCR; // 设置波特率9600 out8(port_lcr, 0x80); out8(addr_base,(115200 / MY_BAUD) & 0xff); out8(port_ier,((115200 / MY_BAUD)>>8) & 0x00ff); // 8位数据位 // 停止位1 // 无奇偶校验 // 无流量控制 Setting = 0x03; out8(port_lcr, Setting); // 置DTR和RTS位 out8(port_mcr, 0x0B); // 关闭中断(打开置0x0F) out8(port_ier, 0); return ; } // 发送数据 unsigned long send_data(unsigned long addr_base, unsigned char data) { unsigned long port_lsr = addr_base + SERIAL_PORT_LSR; int counts = 0; unsigned char tmp = in8(port_lsr); // 等待发送寄存器状态为空 while (counts != WAIT_TIMES) { counts++; if ((tmp & 0x60) == 0x60) break; tmp = in8(port_lsr); delay(1); } if (counts == WAIT_TIMES) return DEVICE_ERROR; out8(addr_base, data); return DEVICE_NO_ERROR; } // 接收数据 unsigned long recv_data(unsigned long addr_base, unsigned char* pdata) { int counts = 0; unsigned long port_lsr = addr_base + SERIAL_PORT_LSR; unsigned char status; status = in8(port_lsr); // why interrupt was called while (((status & 0x01) == 0x00) && (counts != WAIT_TIMES)) { status = in8(port_lsr); counts++; delay(1); } if (counts == WAIT_TIMES) return DEVICE_ERROR; else { *pdata = in8(addr_base);// read character into inbuffer return DEVICE_NO_ERROR; } } // IO读写方式检测串行端口 unsigned long serial_port_io_test(unsigned long addr_base) { unsigned long port_lcr; unsigned char status_lcr; unsigned char divisor_l; unsigned char divisor_h; unsigned long baud; // enable_serial_interrupt(addr_base, FALSE); /* * 读取预设波特率 */ port_lcr = addr_base + SERIAL_PORT_LCR; // 读取LCR状态 status_lcr = in8(port_lcr); // 设置LCR状态(B7置1)使得可以读取波特率 out8(port_lcr, 0x80); // 读取divisor(波特率因子) divisor_l = in8(addr_base); divisor_h = in8(addr_base + SERIAL_PORT_IER); // 计算波特率 baud = 115200 / ((divisor_h << 8) + divisor_l); // 还原LCR状态 out8(port_lcr, status_lcr); // enable_serial_interrupt(addr_base, TRUE); if (baud != MY_BAUD) return DEVICE_ERROR; return DEVICE_NO_ERROR; } // 回环模式检测串行端口 unsigned long serial_port_loopmode_test(unsigned long addr_base) { //int counts = 0; unsigned char data = 0x00; unsigned int res; // unsigned long port_lsr = addr_base + SERIAL_PORT_LSR; //clear interrupts //_asm cli // enable_serial_interrupt(addr_base, FALSE); enable_serial_loopmode(addr_base, TRUE); // Turn on DTR, RTS, and OUT2 ,set LoopMode // 测试值 res = send_data(addr_base, TEST_DATA); delay(5); if (res == DEVICE_NO_ERROR) { res = recv_data(addr_base, &data); if (data != TEST_DATA) res = DEVICE_ERROR; } enable_serial_loopmode(addr_base, FALSE); //set interrupts //_asm sti // enable_serial_interrupt(addr_base, TRUE); #ifdef __DEBUG__ printf("res is %d /n", res); #endif return res; } // 内循环方式检测串行端口 unsigned long serial_port_self_test(unsigned long addr_base) { unsigned char test_data = TEST_DATA; unsigned char return_data = 0; if (send_data(addr_base, test_data) == DEVICE_ERROR) return DEVICE_ERROR; delay(5); if (recv_data(addr_base, &return_data) == DEVICE_ERROR) { return DEVICE_ERROR; } else { if (return_data != test_data) return DEVICE_ERROR; } return DEVICE_NO_ERROR; } // 外循环方式检测串行端口 unsigned long serial_port_remote_test(unsigned long addr_base) { unsigned char return_data = 0; delay(5); if (recv_data(addr_base, &return_data) == DEVICE_ERROR) { return DEVICE_ERROR; } else { if (return_data != TEST_DATA) return DEVICE_ERROR; } return DEVICE_NO_ERROR; } /* * port_num--检测设备 * cmd--检测项 */ unsigned long serial_port_test(unsigned long device, unsigned long cmd) { // 基地址 unsigned long addr_base; unsigned long res; switch (device) { case DEVICE_SERIAL_01: addr_base = SERIAL_PORT_BASE_1; break; case DEVICE_SERIAL_02: addr_base = SERIAL_PORT_BASE_2; break; case DEVICE_SERIAL_03: addr_base = SERIAL_PORT_BASE_3; break; case DEVICE_SERIAL_04: addr_base = SERIAL_PORT_BASE_4; break; default: addr_base = SERIAL_PORT_BASE_1; } switch (cmd) { case TEST_SERIAL_IO: res = serial_port_io_test(addr_base); break; case TEST_SERIAL_LOOP: res = serial_port_loopmode_test(addr_base); break; case TEST_SERIAL_SELF: res = serial_port_self_test(addr_base); break; case TEST_SERIAL_COMM: res = serial_port_remote_test(addr_base); break; default: res = serial_port_io_test(addr_base); } return res; }