#include #include #include #include #include #include #define PORT_80 0x80 #define SCAN_DELAY 5000 // 5ms扫描延时 // 7段数码管段码表 (共阴极) const unsigned char segment_codes[] = { 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, // 0-7 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, // 8-F 0x00, 0x40 // 熄灭, 横杠 }; typedef struct { int running; int display_value; } DisplayContext; DisplayContext ctx = {1, 0}; // 信号处理函数 void signal_handler(int sig) { printf("\n正在退出...\n"); ctx.running = 0; outb(0x00, PORT_80); // 清空显示 } // 初始化I/O权限 int init_io() { if (iopl(3) < 0) { perror("iopl failed"); return -1; } // 或者使用ioperm(更精确的权限控制) // if (ioperm(PORT_80, 2, 1) < 0) { // perror("ioperm failed"); // return -1; // } return 0; } // 显示单个数字在指定位置 void display_digit(int digit, int position) { unsigned char code; if (digit < 0 || digit > 15) { code = segment_codes[16]; // 熄灭 } else { code = segment_codes[digit]; } // 位置0使用低4位,位置1使用高4位(取决于硬件连接) if (position == 0) { outb(code, PORT_80); } else { outb(code, PORT_80); } } // 显示两位数字 void display_two_digits(int num) { char value = num & 0xff; outb(value, PORT_80); return; int tens = num / 10; int ones = num % 10; int scan_count = 50; // 扫描次数 for (int i = 0; i < scan_count && ctx.running; i++) { // 显示十位 outb(segment_codes[tens], PORT_80); usleep(SCAN_DELAY); // 显示个位 outb(segment_codes[ones], PORT_80); usleep(SCAN_DELAY); } } // 显示16进制数字 void display_hex(int value) { char values = value & 0xff; outb(values, PORT_80); return; // for (int i = 0; i < 50 && ctx.running; i++) { // outb(segment_codes[high], PORT_80); // usleep(SCAN_DELAY); // outb(segment_codes[low], PORT_80); // usleep(SCAN_DELAY); // } } // 特效显示:闪烁 void blink_display(int num, int times) { for (int i = 0; i < times && ctx.running; i++) { display_two_digits(num); usleep(500000); // 500ms outb(0x00, PORT_80); usleep(300000); // 300ms } } // 特效显示:滚动 void scroll_display(const char *text) { int len = strlen(text); for (int i = 0; i <= len && ctx.running; i++) { for (int j = 0; j < 20 && ctx.running; j++) { if (i < len) { int digit = text[i] - '0'; if (digit >= 0 && digit <= 9) { outb(segment_codes[digit], PORT_80); } } usleep(SCAN_DELAY); } } } int main(int argc, char *argv[]) { int choice = 0; int value; printf("\n=== Intel ADL N97 Port 80 数码管控制程序 ===\n"); printf("版本: 1.0\n"); printf("平台: Ubuntu 22.04\n\n"); // 初始化I/O权限 if (init_io() < 0) { printf("错误: 无法获取I/O权限,请使用sudo运行\n"); return 1; } // 设置信号处理 signal(SIGINT, signal_handler); // 测试硬件连接 printf("正在测试硬件连接...\n"); for (int i = 0; i < 3 && ctx.running; i++) { outb(0xFF, PORT_80); // 全亮 usleep(300000); outb(0x00, PORT_80); // 全灭 usleep(200000); } printf("测试完成\n\n"); while (ctx.running) { printf("\n请选择模式:\n"); printf("1. 显示数字 (0-99)\n"); printf("2. 显示16进制 (00-FF)\n"); printf("3. 闪烁显示\n"); printf("4. 滚动显示\n"); printf("5. 计数器\n"); printf("6. 退出\n"); printf("选择: "); if (scanf("%d", &choice) != 1) { while(getchar() != '\n'); continue; } switch(choice) { case 1: printf("输入数字 (0-99): "); scanf("%d", &value); if (value >= 0 && value <= 99) { printf("显示 %d\n", value); display_two_digits(value); } break; case 2: printf("输入16进制值 (00-FF): "); scanf("%x", &value); if (value >= 0 && value <= 0xFF) { printf("显示 0x%02X\n", value); display_hex(value); } break; case 3: printf("输入数字和闪烁次数: "); scanf("%d %d", &value, &choice); blink_display(value, choice); break; case 4: printf("输入数字串: "); char text[10]; scanf("%s", text); scroll_display(text); break; case 5: printf("计数器模式 (按Ctrl+C退出)\n"); for (int i = 0; i <= 99 && ctx.running; i++) { printf("\r计数: %d", i); fflush(stdout); display_two_digits(i); } printf("\n"); break; case 6: ctx.running = 0; break; default: printf("无效选择\n"); } } // 清理 outb(0x00, PORT_80); printf("\n程序退出\n"); return 0; }