ATtiny167与Attiny87因JMP/RJMP指令不兼容,如何实现自动适配?
自动适配ATtiny87/167的汇编程序方案
可以通过读取芯片签名字节识别硬件,进而自动选择对应的跳转指令,实现同一hex文件兼容两款芯片。核心思路是运行时判断芯片型号,动态选择跳转指令,具体实现如下:
1. 读取芯片签名字节
AVR芯片的签名字节存储在程序空间固定地址,ATtiny87与ATtiny167的签名字节有明确区别:
- ATtiny87:制造商
0x1E、系列0x93、型号0x0B - ATtiny167:制造商
0x1E、系列0x94、型号0x0A
使用LPM指令读取签名字节,示例代码:
; 读取系列字节(0x0001地址)并保存到r20寄存器 reset_check: ldi r30, 0x01 ; Z寄存器低8位指向签名字节地址 ldi r31, 0x00 ; Z寄存器高8位 lpm r20, Z ; r20 = 系列字节(0x93=ATtiny87,0x94=ATtiny167) sei ; 开启中断 rjmp main ; 跳转到主程序
2. 中断向量表的动态适配
将所有中断向量入口设置为跳转到分发函数,分发函数根据预存的芯片型号选择RJMP或JMP指令跳转到处理逻辑:
; 复位向量(程序起始地址0x0000) rjmp reset_check ; INT0中断向量(0x0002) rjmp int0_dispatch ; --- 中断分发逻辑 --- int0_dispatch: ; 保存现场寄存器 push r20 in r20, SREG push r20 ; 根据芯片型号选择跳转指令 cpi r20, 0x93 breq tiny87_int0_jump ; 默认适配ATtiny167 jmp int0_handler tiny87_int0_jump: rjmp int0_handler ; 恢复现场寄存器 pop r20 out SREG, r20 pop r20 reti ; --- 共用中断处理函数 --- int0_handler: ; 此处编写INT0中断的处理逻辑 ; ... reti ; --- 主程序 --- main: ; 主程序逻辑 ; ... rjmp main
3. 注意事项
- 若中断处理函数的地址在
RJMP的±2K范围内,两款芯片都可使用RJMP;若超出范围,ATtiny167必须使用JMP覆盖全32K程序空间。 - 可同时检查系列+型号字节提高识别准确性,避免误判。
- 所有中断向量都需要类似的分发逻辑,确保硬件触发中断时能正确适配。
内容的提问来源于stack exchange,提问作者goofson
相关产品推荐
相关产品推荐

