中断系统是嵌入式实时控制的核心枢纽,就像城市交通中的应急通道,允许关键事件优先获得处理权。PIC16系列采用多级中断架构,其中断逻辑设计极具代表性。
所有PIC微控制器都采用固定中断向量机制。当中断发生时,硬件自动跳转到0x0004地址执行ISR。观察示例代码中的中断服务程序开头部分:
assembly复制org 0x0004
isr:
movwf r_isr_w ; 保存W寄存器
swapf r_status, w ; 保存STATUS寄存器
clrf r_status ; 清除状态(避免bank切换问题)
movwf r_isr_status ; 存储原始STATUS值
这里有几个关键细节需要注意:
实际项目中我曾遇到因bank切换导致的中断bug——ISR中访问了错误bank的寄存器。解决方案就是像示例这样在ISR开头统一清除STATUS的bank位。
示例代码展示了典型的多中断处理框架:
assembly复制isr_rac: ; PORTA变化中断
btfss r_intcon, RAIF ; 检查标志位
goto isr_rbc_x ; 非此中断则跳过
;...处理代码...
bcf r_intcon, RAIF ; 必须手动清除标志
isr_t1: ; Timer1中断
btfss r_pir1, TMR1IF ; 检查标志位
goto isr_t1_x
bcf r_pir1, TMR1IF ; 清除标志
中断处理的最佳实践包括:
脉宽调制技术如同精准的"数字模拟"转换器,通过调节占空比实现等效电压输出。PIC16系列通常集成增强型CCP模块支持PWM。
PWM初始化涉及三个核心寄存器:
assembly复制pwm_config:
bsf r_status, RP0 ; 切换到Bank1
movlw 0xff
movwf r_pr2 ; 设置周期寄存器PR2
bcf r_status, RP0 ; 返回Bank0
movlw 0x80
movwf r_ccpr1l ; 初始占空比50%
movlw 0x04
movwf r_t2con ; 启用Timer2(TMR2ON=1)
movlw CCP1CON_DEFAULT
movwf r_ccp1con ; 配置PWM模式
PWM频率计算公式为:
code复制Fpwm = Fosc / (4 * (PR2+1) * TMR2预分频)
例如:
实时调节PWM的关键在于正确处理10位分辨率:
assembly复制pwm_set:
rrf r_pwm_H, w ; 处理高2位
movwf r_accA_H
rrf r_pwm_L, w ; 处理低8位
movwf r_accA_L
rrf r_accA_H, f
rrf r_accA_L, w
movwf r_ccpr1l ; 写入CCPR1L(bits 9:2)
swapf r_pwm_L, w
andlw 0x30
iorlw CCP1CON_DEFAULT
movwf r_ccp1con ; 配置CCPxCON<5:4>
常见问题排查:
定时器如同嵌入式系统的心跳,示例中展示了多定时器协同的经典设计。
Timer1作为16位定时器常用于精确计时:
assembly复制; 初始化
movlw tmr1_default
movwf r_t1con ; 预分频1:8,内部时钟
bsf r_t1con, TMR1ON ; 启动定时器
; ISR中的处理
isr_t1:
btfss r_pir1, TMR1IF
goto isr_t1_x
bcf r_pir1, TMR1IF
bcf r_t1con, TMR1ON
bsf flag_comm_timeout ; 设置超时标志
定时器重装载技巧:
assembly复制comm_timer_load:
bcf r_t1con, TMR1ON ; 暂停定时器
movwf r_tmr1l ; 写入目标值(取反)
comf r_tmr1l, f
movlw 0xff
movwf r_tmr1h ; 高字节全1(倒计时)
bsf r_t1con, TMR1ON ; 重启定时器
示例中的分层定时器系统值得借鉴:
assembly复制timer_svc:
btfss flag_timer_0 ; 基准时标
goto timer_svc_x
bcf flag_timer_0
; A类定时器(快速)
incf r_timer_a1, f
movlw TIMER_A1_TA
subwf r_timer_a1, w
btfss r_status, C
goto timer_svc_a1_x
clrf r_timer_a1
bsf flag_reg_timer ; 触发事件
; B类定时器(中速)
incf r_timer_b, f
movlw TIMER_B_TA
subwf r_timer_b, w
btfss r_status, C
goto timer_svc_x
clrf r_timer_b
bsf flag_led_timer ; 触发LED刷新
这种设计实现了:
嵌入式通信如同设备间的"摩斯密码",需要精确的时序控制。
示例展示了一种高效的GPIO通信方案:
assembly复制comm_isr_rcv:
btfsc flag_comm_timeout ; 超时检测
goto comm_reset ; 复位通信
btfsc flag_comm_pin ; 检测边沿
goto comm_isr_rcv_1
bsf flag_comm_bit ; 起始位
movlw TIME_COMM_BREAK_T
call comm_timer_load
goto comm_isr_x
comm_isr_rcv_1:
btfss flag_comm_bit
goto comm_isr_x
call comm_timer_off
bcf flag_comm_bit
comf r_tmr1l, w ; 计算脉冲宽度
通信协议处理状态机示例:
assembly复制comm_isr_rcv_bit:
rrf r_comm_data, f ; 移位接收
decfsz r_comm_count, f
goto comm_isr_x
movf r_comm_data, w
btfsc flag_comm_cmnd ; 判断命令/数据阶段
goto comm_isr_rcv_data
comm_isr_rcv_cmnd:
bsf flag_comm_cmnd ; 进入数据阶段
movwf r_comm_data_cmnd
安全可靠的GPIO配置流程:
assembly复制start:
clrf r_port_a ; 清除输出锁存
clrf r_port_b
clrf r_port_c
bsf r_status, RP0 ; 切换到Bank1
movlw TRIS_A_COMM
movwf r_tris_a ; 设置方向寄存器
movlw IOCA_DEFAULT
movwf r_ioca ; 中断使能
movlw WPUA_DEFAULT
movwf r_wpua ; 弱上拉
ADC和比较器的典型配置:
assembly复制 movlw ANSEL0_DEFAULT
movwf r_ansel0 ; 模拟输入选择
movlw ANSEL1_DEFAULT
movwf r_ansel1
movlw CM1CON0_DEFAULT
movwf r_cm1con0 ; 比较器配置
movlw CM2CON0_DEFAULT
movwf r_cm2con0
充电控制状态机的经典实现:
assembly复制chg_state_svc_jumptable:
movlw HIGH chg_state_table
movwf r_pclath
movf r_chg_state, w
addwf r_pcl, f ; 计算跳转地址
chg_state_table:
goto chg_state_0 ; 状态0
goto chg_state_1 ; 状态1
;...其他状态...
chg_state_0:
; 状态处理代码
btfss flag_charge_complete
return
movlw .1
movwf r_chg_state ; 状态转移
可靠的EEPROM操作流程:
assembly复制ee_write:
bcf r_status, RP1
bsf r_status, RP0
btfsc r_eecon1, WR ; 等待前次写入完成
goto $-1
movf r_ee_addr, w
movwf r_eeadr
movf r_ee_data, w
movwf r_eedata
bsf r_eecon1, WREN ; 使能写入
bcf r_intcon, GIE ; 关键段开始
movlw 0x55
movwf r_eecon2 ; 解锁序列
movlw 0xaa
movwf r_eecon2
bsf r_eecon1, WR
bsf r_intcon, GIE ; 关键段结束
利用闲置引脚输出调试信号:
assembly复制#ifdef DEBUG_ENABLE_TOGGLE
blink_1:
bsf r_port_c, 1 ; 置高
bcf r_port_c, 1 ; 置低
return
#endif
RAM访问优化技巧:
assembly复制ram_clear:
clrf r_indf ; 使用间接寻址清零
incf r_fsr, f
addlw 0xff ; 优化循环计数
btfss r_status, Z
goto ram_clear
通过示波器观察GPIO调试信号,可以准确测量中断响应时间和关键代码段执行周期。在我的一个电机控制项目中,通过这种方法发现并修复了PWM中断响应延迟问题。