8088单板机8259中断的软件触发测试

1.工作原理

  8086和8088的中断设计的是很巧妙的,比如给8259的IR1配置了一个中断,中断号为21H,那么当真个引脚出现高电平的时候,就会触发相应上的中断响应。但,这不是唯一能够触发21H中断的方法,还可以通过软件指令 INT  21H,实现这个中断的触发。

2.实现细节

3.测试结果

 

4.完整程序


; You may customize this and other start-up templates; 
; The location of this template is c:\emu8086\inc\0_com_template.txt; =============================================
; PC16550 UART接收中断程序 + LED闪烁 + 中断计数器
; 硬件配置:
;   - UART基地址: 100H
;   - LED端口: 800H
;   - 8259 PIC端口: 400H(命令), 402H(数据)
;   - 中断请求线: IRQ1 (8259 IR1)
;   - 中断向量号: 21H
;   - 时钟频率: 18.432MHz
;   - 波特率: 9600 bps (除数78H)
; =============================================ORG 100H
JMP INITIALIZATION      ; 跳过数据区到初始化代码; 数据段定义
BUFFER_SIZE EQU 256     ; 接收缓冲区大小
recv_buffer DB BUFFER_SIZE DUP(0)  ; 接收缓冲区
buffer_head DW 0        ; 缓冲区头指针
buffer_tail DW 0        ; 缓冲区尾指针
buffer_count DW 0       ; 缓冲区中字符计数; LED控制变量
led_state DB 0FFH       ; LED状态: FFH=亮, 00H=灭
flash_counter DW 0      ; 闪烁计数器
FLASH_INTERVAL EQU 50  ; 闪烁间隔(约0.5秒); 中断计数器
interrupt_counter DW 0  ; 中断次数计数器
last_report DW 0        ; 上次报告时间
REPORT_INTERVAL EQU 1000 ; 报告间隔(主循环次数); 16550寄存器偏移
UART_BASE EQU 100H
RBR_THR EQU UART_BASE + 0  ; 接收缓冲/发送保持寄存器
IER     EQU UART_BASE + 1  ; 中断使能寄存器
IIR_FCR EQU UART_BASE + 2  ; 中断标识/FIFO控制寄存器
LCR     EQU UART_BASE + 3  ; 线路控制寄存器
MCR     EQU UART_BASE + 4  ; 调制解调器控制寄存器
LSR     EQU UART_BASE + 5  ; 线路状态寄存器
DLL     EQU UART_BASE + 0  ; 除数锁存低字节 (DLAB=1)
DLM     EQU UART_BASE + 1  ; 除数锁存高字节 (DLAB=1); 8259 PIC端口 (修改为400H/402H)
PIC_CMD  EQU 400H
PIC_DATA EQU 402H; 中断向量号
UART_IRQ EQU 21H        ; IRQ1对应中断21H; =============================================
; UART初始化子程序
; =============================================
INIT_UART:; 设置波特率除数 (9600 @ 18.432MHz)MOV DX, LCRMOV AL, 80H         ; 设置DLAB=1OUT DX, ALMOV DX, DLL         ; 除数锁存低字节MOV AL, 78H         ; 120 = 78H (18.432MHz / (16 * 9600))OUT DX, ALMOV DX, DLM         ; 除数锁存高字节MOV AL, 00HOUT DX, AL; 设置线路参数: 8位数据, 1停止位, 无校验MOV DX, LCRMOV AL, 03H         ; 8N1, DLAB=0OUT DX, AL; 启用并复位FIFOMOV DX, IIR_FCRMOV AL, 0C7H        ; 启用FIFO, 14字节触发点, 清除接收FIFOOUT DX, AL; 设置调制解调器控制MOV DX, MCRMOV AL, 0BH         ; 启用OUT2(中断使能), RTS和DTROUT DX, AL; 启用接收数据中断MOV DX, IER; MOV AL, 01H         ; 仅启用接收数据中断MOV AL, 00H         ; 仅启用接收数据中断OUT DX, ALRET; =============================================
; 8259 PIC初始化 (适配400H/402H端口)
; =============================================
INIT_PIC:; 保存原始中断屏蔽字MOV DX, PIC_DATAIN AL, DXMOV [original_mask], AL; 初始化8259MOV DX, PIC_CMDMOV AL, 17H         ; ICW1: 边沿触发, 级联, 需要ICW4OUT DX, ALMOV DX, PIC_DATAMOV AL, UART_IRQ-1   ; ICW2: 中断向量基值OUT DX, ALMOV AL, 01H         ; ICW4: 8086模式, 非缓冲, 正常EOIOUT DX, AL; 允许IRQ1中断IN AL, DXAND AL, 0FDH        ; 清除IRQ1屏蔽位(11111101)OUT DX, ALRET; =============================================
; 设置中断向量
; =============================================
SET_INTERRUPT_VECTOR:CLI                 ; 关中断XOR AX, AXMOV ES, AX          ; ES = 0 (中断向量表段地址); 计算中断向量位置 (中断号 * 4)MOV AX, UART_IRQSHL AX, 2           ; 乘以4; 设置中断向量MOV DI, AXMOV AX, OFFSET UART_ISRCLDSTOSW               ; 存储偏移地址MOV AX, CSSTOSW               ; 存储段地址STI                 ; 开中断RET; =============================================
; UART中断服务程序 (IRQ1) - 增加中断计数器
; =============================================
UART_ISR PROC FARPUSH AXPUSH BXPUSH DXPUSH DS; 设置DS为当前数据段MOV AX, CSMOV DS, AX; 增加中断计数器INC [interrupt_counter]ISR_LOOP:; 检查中断源MOV DX, IIR_FCRIN AL, DXTEST AL, 01H        ; 检查是否有待处理中断 (bit0=1表示无中断)JNZ ISR_EXIT        ; 无中断则退出; 检查是否为接收数据中断TEST AL, 04H        ; 检查中断类型位 (bit1-2)JNZ CHECK_OTHER     ; 不是接收中断则检查其他; 处理接收数据中断MOV DX, RBR_THRIN AL, DX           ; 读取接收到的字符; 将字符存入缓冲区CALL BUFFER_STORE; 继续检查其他中断JMP ISR_LOOPCHECK_OTHER:; 处理其他中断类型 (可选); 这里可以添加发送中断或错误中断的处理; ...ISR_EXIT:; 发送EOI到8259 (使用新端口)MOV AL, 20HMOV DX, PIC_CMD     ; PIC_CMD = 400HOUT DX, ALPOP DSPOP DXPOP BXPOP AXIRET
UART_ISR ENDP; =============================================
; 串口发送字符子程序
; 输入: AL = 要发送的字符
; =============================================
SEND_CHAR:PUSH AXPUSH DX; 保存字符MOV AH, ALSEND_WAIT:; 检查发送保持寄存器是否为空MOV DX, LSRIN AL, DXTEST AL, 20H        ; 检查THRE位(bit5)JZ SEND_WAIT        ; 不为空则等待; 发送字符MOV DX, RBR_THRMOV AL, AHOUT DX, ALPOP DXPOP AXRET; =============================================
; LED控制子程序
; =============================================
UPDATE_LED:PUSH AXPUSH DX; 更新闪烁计数器INC [flash_counter]CMP [flash_counter], FLASH_INTERVALJB LED_DONE         ; 未达到间隔; 重置计数器MOV [flash_counter], 0; 切换LED状态XOR [led_state], 0FFH; 输出到LED端口MOV DX, 800HMOV AL, [led_state]OUT DX, ALLED_DONE:POP DXPOP AXRET; =============================================
; 将字符存入缓冲区
; =============================================
BUFFER_STORE:PUSH BX; 检查缓冲区是否已满MOV BX, buffer_countCMP BX, BUFFER_SIZEJAE BUFFER_FULL     ; 缓冲区已满,丢弃字符; 存储字符MOV BX, buffer_tailMOV [recv_buffer + BX], AL; 更新尾指针INC BXCMP BX, BUFFER_SIZEJB NO_WRAP_TAILXOR BX, BX          ; 回绕到缓冲区开头NO_WRAP_TAIL:MOV buffer_tail, BX; 更新字符计数INC buffer_countBUFFER_FULL:POP BXRET; =============================================
; 从缓冲区读取字符
; =============================================
BUFFER_READ:PUSH BX; 检查缓冲区是否为空CMP buffer_count, 0JE BUFFER_EMPTY; 读取字符MOV BX, buffer_headMOV AL, [recv_buffer + BX]; 更新头指针INC BXCMP BX, BUFFER_SIZEJB NO_WRAP_HEADXOR BX, BX          ; 回绕到缓冲区开头NO_WRAP_HEAD:MOV buffer_head, BX; 更新字符计数DEC buffer_count; 设置成功标志STCJMP READ_DONEBUFFER_EMPTY:XOR AL, AL          ; 返回0CLC                 ; 清除进位标志 (失败)READ_DONE:POP BXRET; =============================================
; 串口发送字符串
; 输入: SI = 字符串偏移地址
; =============================================
SEND_STRING:PUSH AXPUSH SISEND_STR_LOOP:LODSB               ; 加载字符到ALOR AL, AL           ; 检查是否结束(0)JZ SEND_STR_DONE    ; 是则结束CALL SEND_CHAR      ; 发送字符JMP SEND_STR_LOOP   ; 继续发送SEND_STR_DONE:POP SIPOP AXRET; =============================================
; 将数字转换为字符串并发送
; 输入: AX = 要发送的数字
; =============================================
SEND_NUMBER:PUSH AXPUSH BXPUSH CXPUSH DXPUSH DI; 准备数字转换MOV CX, 0           ; 数字位数计数器MOV BX, 10          ; 除数; 处理0特殊情况TEST AX, AXJNZ CONVERT_LOOPMOV AL, '0'CALL SEND_CHARJMP SEND_NUM_DONECONVERT_LOOP:XOR DX, DX          ; 清零DXDIV BX              ; AX = AX/10, DX = 余数ADD DL, '0'         ; 转换为ASCIIPUSH DX             ; 保存数字字符INC CX              ; 增加位数计数TEST AX, AX         ; 检查商是否为0JNZ CONVERT_LOOP    ; 不为0则继续SEND_LOOP:POP AX              ; 获取数字字符CALL SEND_CHAR      ; 发送字符LOOP SEND_LOOP      ; 循环发送所有数字SEND_NUM_DONE:POP DIPOP DXPOP CXPOP BXPOP AXRET; =============================================
; 报告中断计数器状态
; =============================================
REPORT_COUNTER:PUSH AXPUSH SI; 发送前缀消息MOV SI, OFFSET counter_msgCALL SEND_STRING; 发送中断计数MOV AX, [interrupt_counter]CALL SEND_NUMBER; 发送后缀消息MOV SI, OFFSET counter_endCALL SEND_STRINGPOP SIPOP AXRET; =============================================
; 初始化系统
; =============================================
INIT_SYSTEM:; 初始化缓冲区MOV buffer_head, 0MOV buffer_tail, 0MOV buffer_count, 0; 初始化LED状态MOV [led_state], 0FFH  ; 初始状态: 亮MOV [flash_counter], 0; 初始化LED端口MOV DX, 800HMOV AL, [led_state]OUT DX, AL; 初始化计数器MOV [interrupt_counter], 0MOV [last_report], 0RET; =============================================
; 主初始化程序
; =============================================
INITIALIZATION:; 初始化系统CALL INIT_SYSTEM; 初始化UARTCALL INIT_UART; 初始化8259 PICCALL INIT_PIC; 设置中断向量CALL SET_INTERRUPT_VECTOR; 通过串口发送启动消息MOV SI, OFFSET startup_msgCALL SEND_STRING; =============================================
; 主程序循环
; =============================================
MAIN_LOOP:; 更新LED状态CALL UPDATE_LED                     INT   21H                       ; 更新报告计数器INC [last_report]CMP [last_report], REPORT_INTERVALJB SKIP_REPORT; 重置报告计数器MOV [last_report], 0; 报告中断计数CALL REPORT_COUNTER   ;INT 21  SKIP_REPORT:; 检查是否有接收到的字符CALL BUFFER_READJNC NO_DATA         ; 无数据则继续等待; 通过串口回显接收到的字符CALL SEND_CHAR; 检查是否为退出命令;CMP AL, 1BH         ; ESC键;JE EXIT_PROGRAMNO_DATA:; 短延时以控制闪烁频率MOV CX, 3000        ; 延时参数
DELAY_SHORT:LOOP DELAY_SHORT         ;INT 21HJMP MAIN_LOOP; =============================================
; 退出程序
; =============================================
EXIT_PROGRAM:; 发送最终中断计数报告CALL REPORT_COUNTER; 恢复原始中断屏蔽字MOV DX, PIC_DATAMOV AL, [original_mask]OUT DX, AL; 禁用UART中断MOV DX, IERMOV AL, 00HOUT DX, AL; 关闭LEDMOV DX, 800HMOV AL, 00HOUT DX, AL; 通过串口发送退出消息MOV SI, OFFSET exit_msgCALL SEND_STRING; 返回DOSMOV AH, 4CHINT 21H; =============================================
; 数据区
; =============================================
original_mask DB 0     ; 原始8259中断屏蔽字
startup_msg DB 0Dh, 0Ah, 'UART Interrupt Counter Program Started', 0Dh, 0AhDB 'Press ESC to exit...', 0Dh, 0Ah, 0
exit_msg    DB 0Dh, 0Ah, 'Program terminated.', 0Dh, 0Ah, 0
counter_msg DB 0Dh, 0Ah, 'Interrupt count: ', 0
counter_end DB ' times', 0Dh, 0Ah, 0  end_flag    DB  55h,55h,55h,55h,55hEND INITIALIZATION

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/news/909408.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TC3xx中PFLASH缓存对XCP标定常量的影响

1、TC3xx中PFLASH缓存(Cache)对XCP标定的影响 XCP的映射用到TC3XX的Overlay功能需要使用一段Pflash内存。 Pflash数据有两个段区。分别为0x80000000和0xA0000000为起始地址的PFLASH段。 如上,两段数据的区别是一个段8有CACHE缓存,…

代码审计服务:如何解决误报与漏报难题,保障软件安全?

代码审计服务在保障软件质量、安全合规等方面扮演着关键角色,特别是在数字化浪潮席卷而来的今天,其重要性日益显著。它能揭露代码中的不足,进而为软件开发提供有力的效率和安全性保障。 误报与漏报难题 常规的代码审查工具,其错…

web方向第一次考核内容

一.考核内容 Web组大一下考核之HTML、CSS 1.为什么要清除浮动(4),清除浮动的方法有哪些?(6)(至少两种) 2.怎么实现左边左边宽度固定右边宽度自适应的布局?(10) 3.讲讲flex:1;(10) 4.怎么实现移动端适配不同…

HarmonyOS 5 Cordova有哪些热门插件?

以下是 HarmonyOS 5 环境下 Cordova 的热门插件及核心代码实现(综合实际开发场景高频使用): 一、核心工具类插件 1. ‌高性能图片压缩插件‌ ‌功能‌:直接调用鸿蒙 ImageSource API 实现硬件级加速压缩 ‌代码实现‌&#xff…

Cesium圆锥渐变色实现:融合顶点着色器、Canvas动态贴图与静态纹理的多方案整合

在Cesium中渲染圆锥体时,无论采用顶点着色器、Canvas动态贴图还是静态图片贴图,其渐变色均需满足以下条件: 圆形结构:渐变范围限定在圆锥底面的圆形区域内。径向扩散:颜色从圆心向外逐步变化(如红→黄→蓝…

周末复习1

质量管理包括质量规划,质量保证,质量控制。质量管理体系要定期执行内部审核和管理评审。二者都属于质量保证过程。 实施质量保证的方法很多,过程分析属于实施质量保证的常用方法。 采购管理过程包括编制采购计划,实施采购,控制采购和结束采购…

英飞凌亮相SEMICON China 2025:以SiC、GaN技术引领低碳化与数字化未来

在刚刚落幕的SEMICON China 2025上,全球半导体行业再度汇聚上海,共同探讨产业未来。本届展会以“跨界全球•心芯相联”为主题,覆盖芯片设计、制造、封测、设备及材料等全产业链,充分展现了半导体技术的最新突破与创新趋势。 作为…

工业路由器赋能仓库消防预警,智慧消防物联网解决方案

在现代物流与仓储行业蓬勃发展的当下,仓库的规模与存储密度不断攀升,消防预警的重要性愈发凸显。传统消防系统在应对复杂仓库环境时,预警滞后、设备联动不畅、数据管理困难等弊端逐渐暴露。为了有效解决这些问题,工业路由器作为物…

【开发常用命令】:服务器与本地之间的数据传输

服务器与本地之间的数据传输 本地给服务器上传数据 scp /path/to/local_file usernameremotehost:/path/to/remote_directory例如 scp test.txt root192.168.1.xxx:/test # test.txt 需要上传到服务器的文件,如果非当前路径,使用文件的相对路径或绝对…

springboot + nacos + k8s 优雅停机

1 概念 优雅停机是什么?网上说的优雅下线、无损下线,都是一个意思。 优雅停机,通常是指在设备、系统或应用程序中止运作前,先执行一定的流程或动作,以确保数据的安全、预防错误并保证系统的整体稳定。 一般来说&…

Python 标准库之 math 模块

1. 前言 math 模块中包含了各种浮点运算函数,包括: 函数功能floor向下取整ceil向上取整pow指数运算fabs绝对值sqrt开平方modf拆分小数和整数fsum计算列表中所有元素的累加和copysign复制符号pi圆周率e自然对数 2. math.floor(n) 函数 math.floor(n) 的…

6.14星期六休息一天

Hey guys, Today’s Saturday, and I didn’t have to go to work, so I let myself sleep in a bit — didn’t get up until 8 a.m. My cousin invited me over to his place. He lives in a nearby city, about 80 kilometers away. But honestly, after a long week, I …

event.target 详解:理解事件目标对象

event.target 详解&#xff1a;理解事件目标对象 在 JavaScript 事件处理中&#xff0c;event.target 是一个关键属性&#xff0c;它表示最初触发事件的 DOM 元素。下面我将通过一个可视化示例详细解释其工作原理和使用场景。 <!DOCTYPE html> <html lang"zh-C…

Flutter 小技巧之:实现 iOS 26 的 “液态玻璃”

随着 iOS 26 发布&#xff0c;「液态玻璃」无疑是热度最高的标签&#xff0c;不仅仅是因为设计风格大变&#xff0c;更是因为 iOS 26 beta1 的各种 bug 带来的毛坯感让 iOS 26 冲上热搜&#xff0c;比如通知中心和控制中心看起来就像是一个半成品&#xff1a; 当然&#xff0c;…

Android工程中FTP加密传输与非加密传输的深度解析

详细的FTP传输实现方案&#xff0c;包括完整代码、安全实践、性能优化和实际应用场景分析。 一、FTP传输类型对比表&#xff08;增强版&#xff09; 特性非加密FTPFTPS (FTP over SSL/TLS)SFTP (SSH File Transfer Protocol)协议基础FTP (RFC 959)FTP SSL/TLS (RFC 4217)SSH…

C# 枚 举(枚举)

枚举 枚举是由程序员定义的类型&#xff0c;与类或结构一样。 与结构一样&#xff0c;枚举是值类型&#xff1a;因此直接存储它们的数据&#xff0c;而不是分开存储成引用和数据。枚举只有一种类型的成员&#xff1a;命名的整数值常量。 下面的代码展示了一个示例&#xff0c…

一文详解前缀和:从一维到二维的高效算法应用

文章目录 一、一维前缀和​1. 基本概念​2. C 代码实现​3. 应用场景​ 二、二维前缀和1. 基本概念​2. C 代码实现​3. 应用场景​ 三、总结​ 在算法竞赛和日常的数据处理工作中&#xff0c;前缀和是一种极其重要的预处理技术。它能够在常数时间内回答多次区间查询&#xff0…

windows 开发

文章目录 环境搭建数据库关键修改说明&#xff1a;在代码中使用该连接字符串&#xff1a;注意事项&#xff1a;实际使用 都说几天创造一个奇迹&#xff0c;现在是真的这样了&#xff0c;Just do it! 环境搭建 数据库 需要下载这个SQL Server数据库&#xff0c;然后每次Visua…

免费OCPP协议测试工具

免费OCPP 1.6J协议测试工具&#xff0c;简单实用。除加密功能外&#xff08;后续版本支持&#xff09;&#xff0c;支持所有消息调试。 后续将添加2.01和和2.1协议支持. 欢迎使用 Charge-Test

高等数学基础(行列式和矩阵的秩)

行列式主要用于判断矩阵是否可逆及计算特征方程 初见行列式 行列式起源于线性方程组求解 { a 11 x 1 a 12 x 2 b 1 a 21 x 1 a 22 x 2 b 2 \begin{cases} a_{11}x_1 a_{12}x_2 b_1 \\ a_{21}x_1 a_{22}x_2 b_2 \end{cases} {a11​x1​a12​x2​b1​a21​x1​a22​x2…