📄 power.s
字号:
.module power.c
.area text(rom, con, rel)
.dbfile D:\M16开发板实验教程\icc-avr\POWERM~1/delay.h
.dbfunc e delay_1us _delay_1us fV
.even
_delay_1us::
.dbline -1
.dbline 10
; /*
; Title: icc-avr power management
; Author: dushibiao
; Date: 2007 10 22
; Purpose: study how to magage power
; Frequency: Ext 8M
; Software: icc-avr to compile
; Hardware: AVR mega16 BOARD
; Connect: dushibiao@126.com
; */
.dbline 11
; /*
nop
.dbline -2
L1:
.dbline 0 ; func end
ret
.dbend
.dbfunc e delay_nus _delay_nus fV
; i -> R20,R21
; n -> R22,R23
.even
_delay_nus::
xcall push_gset2
movw R22,R16
.dbline -1
.dbline 15
; 本程序简单的示范了如何令AVR ATMEGA16进入睡眠状态及唤醒
; 电源管理及睡眠模式的介绍
; 进入最低耗电的掉电模式
; 关闭各种模块
.dbline 16
; 外部中断唤醒
clr R20
clr R21
.dbline 17
;
xjmp L6
L3:
.dbline 18
xcall _delay_1us
L4:
.dbline 17
subi R20,255 ; offset = 1
sbci R21,255
L6:
.dbline 17
cp R20,R22
cpc R21,R23
brlo L3
.dbline -2
L2:
xcall pop_gset2
.dbline 0 ; func end
ret
.dbsym r i 20 i
.dbsym r n 22 i
.dbend
.dbfunc e delay_1ms _delay_1ms fV
; i -> R16,R17
.even
_delay_1ms::
.dbline -1
.dbline 22
; M16掉电模式的耗电情况(看门狗关闭),时钟为内部RC 1MHz
; 0.9uA@Vcc=5.0V [手册的图表约为1.1uA]
; 0.3uA@Vcc=3.3V [手册的图表约为0.4uA]
; //测量的数字万用表是FLUKE 15B,分辨率0.1uA
;
.dbline 24
clr R16
clr R17
xjmp L11
L8:
.dbline 24
L9:
.dbline 24
subi R16,255 ; offset = 1
sbci R17,255
L11:
.dbline 24
; 这个程序需要MCU进入休眠状态,为实现最低功耗,JTAG接口会被关闭,只能通过LED的变化来观察程序的运行。
; 这个实验里面,用STK500(AVRISP) ISP下载线来烧录更方便。
cpi R16,116
ldi R30,4
cpc R17,R30
brlo L8
.dbline -2
L7:
.dbline 0 ; func end
ret
.dbsym r i 16 i
.dbend
.dbfunc e delay_nms _delay_nms fV
; i -> R20,R21
; n -> R22,R23
.even
_delay_nms::
xcall push_gset2
movw R22,R16
.dbline -1
.dbline 28
;
; 熔丝位设置
; 1 关断BOD功能 BODEN=1
; 2 如果用ISP方式烧录,就可以完全关闭JTAG口了 OCEEN=1,JTAGEN=1
.dbline 29
;
clr R20
clr R21
.dbline 30
; */
xjmp L16
L13:
.dbline 31
xcall _delay_1ms
L14:
.dbline 30
subi R20,255 ; offset = 1
sbci R21,255
L16:
.dbline 30
cp R20,R22
cpc R21,R23
brlo L13
.dbline -2
L12:
xcall pop_gset2
.dbline 0 ; func end
ret
.dbsym r i 20 i
.dbsym r n 22 i
.dbend
.dbfile D:\M16开发板实验教程\icc-avr\POWERM~1\power.c
.dbfunc e main _main fI
; i -> R20
.even
_main::
.dbline -1
.dbline 41
;
; #include<iom16v.h>
; #include <macros.h>
; #include "delay.h"
;
; //管脚定义
; #define LED 0 //PA0 驱动LED,低电平有效
; #define KEY_INT0 2 //PB2 按键, 低电平有效
;
; int main(void)
; {
.dbline 44
; unsigned char i;
; //上电默认DDRx=0x00,PORTx=0x00 输入,无上拉电阻
; PORTB=0xFF; //不用的管脚使能内部上拉电阻。
ldi R24,255
out 0x18,R24
.dbline 45
; PORTC=0xFF;
out 0x15,R24
.dbline 46
; PORTD=0xFF;
out 0x12,R24
.dbline 48
;
; PORTA=0xFF;
out 0x1b,R24
.dbline 49
; DDRA =(1<<LED); //PB0设为输出高电平,灯灭
ldi R24,1
out 0x1a,R24
.dbline 71
; /*
; 端口引脚
; 进入休眠模式时,所有的端口引脚都应该配置为只消耗最小的功耗。
; 最重要的是避免驱动电阻性负载。
; 在休眠模式下I/O 时钟clkI/O 和ADC 时钟clkADC 都被停止了,输入缓冲器也禁止了,从而保证输入电路不会消耗电流。
; 在某些情况下输入逻辑是使能的,用来检测唤醒条件。用于此功能的具体引脚请参见“ 数字输入使能和休眠模式” 。
; 如果输入缓冲器是使能的,此时输入不能悬空,信号电平也不应该接近VCC/2,否则输入缓冲器会消耗额外的电流。
;
; IO作输出(DDR=1)时,维持状态不变
; */
;
; /*
; 看门狗定时器(上电默认是关闭的)
; 如果系统无需利用看门狗,这个模块也可以关闭。
; 若使能,则在任何休眠模式下都持续工作,从而消耗电流。
; 在深层次的睡眠模式下,这个电流将占总电流的很大比重。
;
; 假设看门狗定时器使能了,关闭程式如下
; 1. 在同一个指令内对WDTOE 和WDE 写"1“,即使WDE 已经为"1“
; 2. 在紧接的4 个时钟周期之内对WDE 写"0”
; */
; WDTCR=(1<<WDTOE)|(1<<WDE);
ldi R24,24
out 0x21,R24
.dbline 72
; WDTCR=(0<<WDE);
clr R2
out 0x21,R2
.dbline 83
; //或使用wdt.h里面的wdt_disable()函数
;
; /*
; 模数转换器(上电默认是关闭的)
; 使能时, ADC在睡眠模式下继续工作。
; 为了降低功耗,在进入睡眠模式之前需要禁止ADC。
; 重新启动后的第一次转换为扩展的转换。
;
; 假设模数转换器使能了,关闭程式如下
; */
; ADCSRA=(0<<ADEN);
out 0x6,R2
.dbline 92
; /*
; 模拟比较器(上电默认是打开的,需要手工关闭)
; 在空闲模式时,如果没有使用模拟比较器,可以将其关闭。在ADC 噪声抑制模式下也是如此。
; 在其他睡眠模式模拟比较器是自动关闭的。
; 如果模拟比较器使用了内部电压基准源,则不论在什么睡眠模式下都需要关闭它。否则内部电压基准源将一直使能。
;
; 关闭程式如下
; */
; ACSR=(1<<ACD);
ldi R24,128
out 0x8,R24
.dbline 134
; /*
; 掉电检测BOD (由熔丝位BODEN控制)
; 如果系统没有利用掉电检测器BOD,这个模块也可以关闭。
; 如果熔丝位BODEN 被编程,从而使能了BOD 功能,它将在各种休眠模式下继续工作。
; 在深层次的休眠模式下,这个电流将占总电流的很大比重。
;
; 设置熔丝位BODEN=1 关断BOD功能
; */
;
; /*
; 片内基准电压
; 使用BOD、模拟比较器和ADC 时可能需要内部电压基准源。
; 若这些模块都禁止了,则基准源也可以禁止。
; 重新使能后用户必须等待基准源稳定之后才可以使用它。
; 如果基准源在休眠过程中是使能的,其输出立即可以使用。
;
; 当BOD、模拟比较器和ADC都禁止了,则基准源也自动禁止了。
; */
;
; /*
; JTAG 接口与片上调试系统
; 如果通过熔丝位OCDEN使能了片上调试系统,当芯片进入掉电或省电模式时主时钟保持运行。
; 在休眠模式中这个电流占总电流的很大比重。
; 下面有三种替代方法:
; 1 不编程OCDEN
; 2 不编程JTAGEN
; 3 置位MCUCSR 的JTD
; 当JTAG 接口使能而JTAG TAP 控制器没有进行数据交换时,引脚TDO 将悬空。
; 如果与TDO 引脚连接的硬件电路没有上拉电阻,功耗将增加。
; 器件的引脚TDI 包含一个上拉电阻,因此在扫描链中无需为下一个芯片的TDO 引脚设置上拉电阻。
; 通过置位MCUCSR寄存器的JTD 或不对JTAG 熔丝位编程可以禁止JTAG 接口。
;
; JTD: 禁止JTAG 接口(MCU控制与状态寄存器MCUCSR Bit7)
; 此位为0 时,如果JTAGEN熔丝位被编程则JTAG 接口使能。
; 如果这位为1, JTAG接口禁止。
; 为了避免无意的禁止或使能JTAG接口,必须通过一个时间序列来改变JTD 位。
; 应用软件必须在四个时钟周期内将期望的数值两次写入JTD。
; 如果JTAG 接口没有与其他JTAG电路连接, JTD应该置位。这样做的原因是为了避免JTAG接口TDO引脚的静态电流。
;
; 在软件中关闭JTAG接口的方法
; */
; MCUCSR=(1<<JTD);
out 0x34,R24
.dbline 135
; MCUCSR=(1<<JTD);
out 0x34,R24
.dbline 150
;
; /*
; 掉电模式
; 当SM2..0 为010 时, SLEEP 指令将使MCU 进入掉电模式。
; 在此模式下,外部晶体停振,而外部中断、两线接口地址匹配及看门狗(如果使能的话)继续工作。
; 只有外部复位、看门狗复位、BOD 复位、两线接口地址匹配中断、外部电平中断INT0 或INT1,或外部中断INT2 可以使MCU 脱离掉电模式。
; 这个睡眠模式停止了所有的时钟,只有异步模块可以继续工作。
; 当使用外部电平中断方式将MCU 从掉电模式唤醒时,必须保持外部电平一定的时间。
; 从施加掉电唤醒条件到真正唤醒有一个延迟时间,此时间用于时钟重新启动并稳定下来。
; 唤醒周期与由熔丝位CKSEL 定义的复位周期是一样的。
;
; 如果在睡眠过程中发生了复位,则MCU 唤醒后从中断向量开始执行
; 使能的中断可以将进入睡眠模式的MCU 唤醒, 经过启动时间,外加4个时钟周期后,MCU就可以运行中断例程了。然后返回到SLEEP 的下一条指令。
; */
; MCUCSR=(0<<ISC00); //INT0 的下降沿激活中断(默认的,这句话可以不写)
out 0x34,R2
.dbline 151
; GICR=(1<<INT0); //使能外部中断INT0
ldi R24,64
out 0x3b,R24
.dbline 152
; SEI(); //使能全局中断
sei
xjmp L19
L18:
.dbline 154
; while(1)
; {
.dbline 155
; for (i=0;i<10;i++) //LED闪动10次后进入掉电模式的睡眠状态
clr R20
xjmp L24
L21:
.dbline 156
.dbline 157
ldi R16,300
ldi R17,1
xcall _delay_nms
.dbline 158
cbi 0x1b,0
.dbline 159
ldi R16,300
ldi R17,1
xcall _delay_nms
.dbline 160
sbi 0x1b,0
.dbline 161
L22:
.dbline 155
inc R20
L24:
.dbline 155
cpi R20,10
brlo L21
.dbline 164
ldi R24,96
out 0x35,R24
.dbline 165
SLEEP
.dbline 167
L19:
.dbline 153
xjmp L18
X0:
.dbline -2
L17:
.dbline 0 ; func end
ret
.dbsym r i 20 c
.dbend
.area vector(rom, abs)
.org 4
jmp _int0pro
.area text(rom, con, rel)
.dbfile D:\M16开发板实验教程\icc-avr\POWERM~1\power.c
.dbfunc e int0pro _int0pro fV
.even
_int0pro::
xcall push_lset
.dbline -1
.dbline 173
; {
; delay_nms(300);
; PORTA&=~(1<<LED); //点亮LED
; delay_nms(300);
; PORTA|=(1<<LED); //熄灭LED
; }
;
;
; MCUCR=(1<<SE)|(0<<SM2)|(1<<SM1)|(0<<SM0); //设定为掉电模式
; asm("SLEEP"); //进入睡眠状态
;
; }
; }
;
;
; #pragma interrupt_handler int0pro: iv_INT0
; void int0pro(void) //外部中断0服务程序 唤醒源
; {
.dbline 174
; PORTA&=~(1<<LED); //点亮LED
cbi 0x1b,0
.dbline 175
; delay_nms(5000);
ldi R16,5000
ldi R17,19
xcall _delay_nms
.dbline 176
; PORTA|=(1<<LED); //熄灭LED
sbi 0x1b,0
.dbline 177
; delay_nms(1000);
ldi R16,1000
ldi R17,3
xcall _delay_nms
.dbline -2
L25:
xcall pop_lset
.dbline 0 ; func end
reti
.dbend
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -