如何让ATtiny24A MCU进入睡眠模式?

问题描述 投票:0回答:1

我正在经历一种奇怪的现象。我正在尝试让 ATtiny24A 进入睡眠模式。我之前有一个工作代码,但通过对程序其他部分的修改和测试,新代码似乎不再使 MCU 进入睡眠状态。

我设计了一个用于对 ATtiny24a 进行编程的分线板。编程板有一个板载 LED,连接到 MCU 的引脚 8。它还具有另一个连接到 MCU 引脚 13 的 LED。你可以看到设计: enter image description here

enter image description here

为了仅测试 MCU 的睡眠模式操作,我创建了一个专用于该功能的新文件。我将引脚 8(板载 LED)初始化为输出,将引脚 13 初始化为输入。然后,我使用按下的触觉按钮(从外部面包板)初始化中断配置,以在引脚更改(引脚 13)时触发。接下来,我打开 LED 约 3 秒钟,然后 MCU 应进入睡眠模式。事实并非如此。如果确实如此,我希望它能够使用中断唤醒并继续进入主函数中的 while 循环。我让 LED 每秒闪烁一次。同样在 while 循环中,我有一个向上计数的整数变量,一旦满足条件,MCU 就应该返回睡眠状态。这些都不起作用。这是代码:

#define F_CPU 1000000UL

#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>

#define LED PORTA5 //pin 8
#define BT PINA0  //pin 13

int main(void){
   uint8_t clk = 0;

   //SETUP IO PINS 
   DDRA |= 1 << LED;  //setting up LED pin 
   DDRA &= ~(1 << BT);  //setting up tactile button pin
  
   //SETUP INTERRUPT 
   GIMSK |= 1 << PCIE0;
   PCMSK0 |= 1 << PCINT0;
   sei();
   
   set_sleep_mode(SLEEP_MODE_PWR_DOWN);  //setting sleep mode 
   PORTA |= 1 << LED;  //initialize LED on  

   for(uint8_t i = 0; i < 3; i++ ){
       _delay_ms(1000);
   }
   
   sleep_mode(); //enter sleep mode 
   
   while(1){
      PORTA ^= 1 << LED;
      _delay_ms(500);

      if(clk > 5){
           clk = 0;
           sleep_mode();
      }
      clk += 1;

   }
   return 0;
}

ISR(PCINT0_vect, ISR_NAKED);

当我将此代码上传到 MCU 时。 LED 无限期地保持亮起,在 while 循环之前永远不会进入第一个睡眠指令。

我已经通过github检查了sleep和io文件库内容。我已验证功能和属性有效;我也没有收到任何编译器警告或错误。

然后使用我尝试使用按位运算直接配置寄存器的函数和属性:

set_sleep_mode(SLEEP_MODE_PWR_DOWN);
MCUCR |= 1 << SM1;
sleep_mode();
MCUCR |= 1 << SE;
(这更像是启用睡眠)。

通过这些替换,板上的 LED 会保持亮起 3 秒,然后在 while 循环中开始无限期地闪烁。忽略循环中的睡眠指令。

我还尝试使用指针和取消引用来直接将值分配给寄存器。

*((volatile unsigned char *) 0x55)) |= 1 << 4
4 代表 MCUCR 寄存器的第 4 位(SM1)。
*((volatile unsigned char *) 0x55)) |= 1 << 5
5 代表 MCUCR 寄存器的第 5 位(SE)。

其行为与上述替换相同。

我将继续尝试解决这个问题,但我确实希望有人回复我的解决方案以及我的代码当前不起作用的原因。 我在 MCU 上运行了其他代码,例如 LED 闪烁、引脚 8 上的 Timer1 PWM 输出、引脚更改中断触发,它们工作得很好。我就是无法让MCU进入休眠状态,换MCU也没用。

embedded avr avr-gcc avrdude attiny
1个回答
0
投票

首先,你没有提供可编译的程序。所以我自己完成了必要的线路

#include <util/delay.h>

您没有定义用于中断处理的函数。您只声明了它。结果是 MCU 中断并调用复位。您必须在反汇编窗口的模拟器中看到它。 地址0x0002处有一个中断向量PCINT0_vect。有一个跳转到地址0x0017。 在这个地址处,有一个跳转到地址0x0000,这实际上是一个复位。

由于您没有定义任何中断处理,因此您确实设置了中断向量,但在没有函数体的情况下,翻译器将其替换为跳转到复位地址。

00000000 10.c0                RJMP PC+0x0011        Relative jump 
00000001 15.c0                RJMP PC+0x0016        Relative jump 
00000002 14.c0                RJMP PC+0x0015        Relative jump to 0x0017
00000003 13.c0                RJMP PC+0x0014        Relative jump 
..
..
00000017 e8.cf                RJMP PC-0x0017        Relative jump to 0x0000

如果我将空主体添加到ISR函数中,也会出现有问题的代码,其结果是程序错误。

ISR(PCINT0_vect,  ISR_NAKED){
    
}

ISR_NAKED 意味着您不希望编译器向此函数添加任何内容。奇怪的是,他甚至没有从中断中回来。 我们再看一下模拟器中编译的结果。现在它跳转到主函数之后的地址(0x0170),但是只有NOP指令,然后是一些来自库的链接代码,但它没有被正确调用。这意味着该程序将去往任何地方。

00000000 10.c0                RJMP PC+0x0011        Relative jump 
00000001 15.c0                RJMP PC+0x0016        Relative jump 
00000002 6d.c1                RJMP PC+0x016E        Relative jump to 0x0170
00000003 13.c0                RJMP PC+0x0014        Relative jump 
..
..
    43:     }
0000016F 6f.cf                RJMP PC-0x0090        Relative jump 
    49: }
00000170 00.00                NOP       No operation 
--- No source file -------------------------------------------------------------
00000171 2f.d0                RCALL PC+0x0030       Relative call subroutine 
00000172 08.f4                BRCC PC+0x02      Branch if carry cleared 
00000173 81.e0                LDI R24,0x01      Load immediate 
00000174 08.95                RET       Subroutine return 
00000175 57.d0                RCALL PC+0x0058       Relative call subroutine 
00000176 88.f0                BRCS PC+0x12      Branch if carry set 
00000177 9f.57                SUBI R25,0x7F     Subtract immediate 
00000178 90.f0                BRCS PC+0x13      Branch if carry set 
00000179 b9.2f                MOV R27,R25       Copy register 
0000017A 99.27                CLR R25       Clear Register 
0000017B b7.51                SUBI R27,0x17     Subtract immediate 
0000017C a0.f0                BRCS PC+0x15      Branch if carry set 
0000017D d1.f0                BREQ PC+0x1B      Branch if equal 
0000017E 66.0f                LSL R22       Logical Shift Left 
0000017F 77.1f                ROL R23       Rotate Left Through Carry 
00000180 88.1f                ROL R24       Rotate Left Through Carry 


正确的解决方案是使用

ISR(PCINT0_vect){
    
}

现在调用正确的中断处理程序,并由 RETI 指令正确终止。这意味着程序现在可以在主函数中发生中断的地方正常继续运行。

00000000 10.c0                RJMP PC+0x0011        Relative jump 
00000001 15.c0                RJMP PC+0x0016        Relative jump 
00000002 6d.c1                RJMP PC+0x016E        Relative jump to 0x0170
00000003 13.c0                RJMP PC+0x0014        Relative jump 
..
..
    47: ISR(PCINT0_vect){
00000170 1f.92                PUSH R1       Push register on stack 
00000171 0f.92                PUSH R0       Push register on stack 
00000172 00.90.5f.00          LDS R0,0x005F     Load direct from data space 
00000174 0f.92                PUSH R0       Push register on stack 
00000175 11.24                CLR R1        Clear Register 
00000176 cf.93                PUSH R28      Push register on stack 
00000177 df.93                PUSH R29      Push register on stack 
00000178 cd.b7                IN R28,0x3D       In from I/O location 
00000179 dd.27                CLR R29       Clear Register 
    49: }
0000017A 00.00                NOP       No operation 
0000017B df.91                POP R29       Pop register from stack 
0000017C cf.91                POP R28       Pop register from stack 
0000017D 0f.90                POP R0        Pop register from stack 
0000017E 00.92.5f.00          STS 0x005F,R0     Store direct to data space 
00000180 0f.90                POP R0        Pop register from stack 
00000181 1f.90                POP R1        Pop register from stack 
--- C:\Atmel Studio\7.0\GccApplication1\GccApplication1\Debug/.././main.c 
00000182 18.95                RETI      Interrupt return 

© www.soinside.com 2019 - 2024. All rights reserved.