; ledpwm.asm --- drive a blue LED with PWM 21/04/2006 ; Copyright (c) 2006 John Honniball .include "m8def.inc" .org 0x0000 ; 端口 B 位 2 上的LED .equ LED_PORT = PortB .equ LED_BIT = 2 ; 该程序驱动连接到 AVR 的 I/O 端口的单个 LED。 它将 LED 的阴极连接到 AVR 引脚, ;LED 的阳极通过电阻器。 该电阻的值取决于 LED 的颜色,但通常为几百欧姆。 ;我们通过脉宽调制 (PWM) 控制 LED 的亮度, ; 就像脉动那样地周期运动或变化 从未完全“熄灭昏暗状态”到全亮度再调至昏暗状态,然后再变回来。 ;为此,设置最小亮度、最大亮度值。 .equ MIN_BRIGHT = 15 ;最小亮度 .equ MAX_BRIGHT = 255 ;最大亮度 ; 此值控制 LED 从亮到暗的循环速度。 是的我们为亮度的每一步生成的PWM周期数 ;坡道,上坡和坡道。 数字越大,脉动越慢。 .equ N_CYCLES = 6 ;周期数 ; 重置后开始执行程序 ldi r16,low(RAMEND) ; 初始化堆栈到RAM顶部 out SPL,r16 ldi r16,high(RAMEND) out SPH,r16 ; 初始化硬件 ldi r16,0xff ; 将端口B设置为所有输出 out DDRB,r16 sbi LED_PORT,LED_BIT ;通过将输出引脚设置为高电平关闭蓝色LED ; 从LED处于最低水平开始,然后上升到最大水平 dopwm: ldi r17,MIN_BRIGHT ; R17保持当前亮度水平 adjust_1: ldi r18,N_CYCLES ; R18计算PWM周期,从而计算脉动速度 adjust_2: cbi LED_PORT,LED_BIT ; 输出引脚低,LED亮起 mov r16,r17 ;R16控制延迟长度(=R17) rcall delayn4us ;调用延迟子程序 sbi LED_PORT,LED_BIT ; 输出引脚高,LED熄灭 ldi r16,255 sub r16,r17 ; R16控制延迟长度(=255-R17) rcall delayn4us ; 调用延迟子程序 dec r18 ;递减PWM周期计数器 brne adjust_2 inc r17 ; 亮度增加一步 brne adjust_1 ; 现在逐渐降低到最小亮度 ldi r17,MAX_BRIGHT ;R17 保持当前亮度水平 adjust_3: ldi r18,N_CYCLES ;R18 计算 PWM 周期,从而计算脉动速度 adjust_4: cbi LED_PORT,LED_BIT ;输出引脚低电平,LED 亮起 MOV R16,R17 ;R16 控制延迟长度 (= R17) rcall delayn4us ;呼叫延迟子例程 sbi LED_PORT,LED_BIT ;输出引脚高电平,LED 熄灭 ldi R16,255 sub R16,R17 ;R16 控制延迟长度 (= 255 - R17) rcall delayn4us ;呼叫延迟子例程 dec R18 ;递减PWM周期计数器 brne adjust_4 dec R17 ;亮度降低一级 CPI r17,MIN_BRIGHT ;我们达到最低限度了吗? brne adjust_3 rjmp dopwm ; 循环回到开始 ; delayn 4US ;延迟 (R16 * 4) 微秒 delayn4us: tst r16 ; R16 = 0?(无延迟) breq dly4 dly2: ldi r24,low(16) ldi r25,high(16) dly3: sbiw r24,1 ; 2 个周期 brne dly3 ; 2 个周期 dec r16 brne dly2 dly4: ret ;返回 |