帕拉丁 发表于 2025-3-17 09:56:25

各位前辈大佬号,小弟遇到一个2次唤醒的情况

小弟使用ADXL345+STC8H1K实现一个简易的小项目,思路流程是:当ADXL345静止以后触发一个ADXL345高电平中断,这个ADXL345高电平中断引脚连接到STC8H1K的INT0 P32引脚上。
当中断被触发以后,唤醒休眠状态的STC8H1K单片机。STC8H1K处理完相关任务以后写ADXL345的一个一个寄存器,这个中断引脚恢复为低电平。 ST 8H1K进入休眠等待下一次的ADXL345静止唤醒。
在实际编写程序中遇到问题。 查阅手册和资料 STC8H1K08 只能把INT0设置为上升沿和下降沿触发。不能单独设置为上升沿触发。似乎是这个原因导致 每次ADXL345唤醒 STC8H1K都会唤醒两次、
我也按照论坛大佬的思路编写了以下代码,依旧会两次触发中断,请问我的问题在哪里?谢谢各位大佬了。

////INT0相关
sbit INT0_PIN = P3^2; // 定义INT0对应的引脚
bit lastState = 0;    // 用于存储上一次的引脚状态
bit currentState ;      // 用于当前的引脚状态



                IT0=0;//设置 INT0 上升沿和下降沿中断

                EX0=1; //启动INT0中断


voidINT0_P32() interrupt 0// 使用INT3 P32引脚唤醒休眠的单片机   启用外部中断以后必须给引脚明确的电平 如果处于高阻态悬空 就会导致死机状态。
{
// 记录当前状态
   currentState = INT0_PIN;
   
    // 判断是上升沿还是下降沿
    if(lastState == 0 && currentState == 1) // 上升沿
    {
      ADXL345_wakeup = 1; // 设置唤醒标志
    }
   
    lastState = currentState;
}


我还进一步尝试了 在STC8H1K休眠前打开总中断 休眠唤醒后立刻关闭总中断后果就是 无法唤醒了


EA=1;//开总中断
   PCON=0x02;                        
//MCU进入掉电模式 进行休眠
      _nop_();
      _nop_();
      _nop_();
      _nop_();
                                EA=0;//开总中断








请问各位大佬 我得问题到底是什么原因导致得 谢谢各位。




_奶咖君_ 发表于 2025-3-17 10:11:33

这个上下沿唤醒是肯定会唤醒的,,

我觉得你应该转换一下思维,不要想着怎么去掉一次中断,应该想一想哪一次唤醒是要我单片机进行操作的,然后不需要操作的那次中断就什么都不做直接睡觉。。

帕拉丁 发表于 2025-3-17 10:15:05

_奶咖君_ 发表于 2025-3-17 10:11
这个上下沿唤醒是肯定会唤醒的,,

我觉得你应该转换一下思维,不要想着怎么去掉一次中断,应该想一想哪一 ...

谢谢大佬 你好 现在是 我在外部中断内判断是否上升沿。。。可是上升沿似乎读取不到?或者是别得原因,现在是每次休眠会唤醒2次 给串口发送2次数据。。。

DebugLab 发表于 2025-3-17 11:06:05

帕拉丁 发表于 2025-3-17 10:15
谢谢大佬 你好 现在是 我在外部中断内判断是否上升沿。。。可是上升沿似乎读取不到?或者是别得原因,   ...

边沿触发,进中断后读IO为1就是上升沿,反之是下降沿
IO高阻需要读外部状态的,禁止悬空,外部电路必须是明确的高低电平,开漏必须要有上拉

帕拉丁 发表于 2025-3-17 14:00:28

DebugLab 发表于 2025-3-17 11:06
边沿触发,进中断后读IO为1就是上升沿,反之是下降沿
IO高阻需要读外部状态的,禁止悬空,外部电路必须是 ...

谢谢大佬 我设置为双向口状态了并且按照你的指点改进程序在中断里读IO如果高电平改变标志位。 现在中断稳定了 但是依旧是触发两次间隔一秒我用示波器看 是一个方波 。程序如下


voidINT0_P32() interrupt 0// 使用INT3 P32引脚唤醒休眠的单片机   启用外部中断以后必须给引脚明确的电平 如果处于高阻态悬空 就会导致死机状态。

{

if (INT0_PIN==1)
{ADXL345_wakeup = 1; // 设置唤醒标志
        }
                               

} void main()
{
   
               
    float x_angle, y_angle, z_angle;   
    IO_init();//io初始化
                Uart1_Init();    // 串口初始化
                iic_init();      //IIC 初始化
               
                EA=1;//开总中断
                UART_Send_String("start......");
                //setup_adxl345_continuous_read() ;// 设置ADXL345为一直工作模式 调试用
               setup_adxl345_auto_sleep();// 设置ADXL345为震动唤醒 然后静止后休眠的模式
                UART_Send_String("set adxl345--ok\r\n");
    while (1)
    {
   

               


                _nop_();_nop_();_nop_();_nop_();_nop_();
                _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();

   //EX0=1; //启动INT0中断
               nop_();
      _nop_();
      _nop_();
      _nop_();
   PCON=0x02;                        
//MCU进入掉电模式 进行休眠
      _nop_();
      _nop_();
      _nop_();
      _nop_();
       
                _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
                                _nop_();_nop_();_nop_();_nop_();_nop_();
////唤醒后执行的工作
                                //Uart1_Init();   //唤醒后串口初始化?
                                //delay(6000);
                               
             
         
                               UART_Send_Hex_txt(0xee); //发送数据给串口
                               UART_Send_HEX(INT0_PIN);// 串口HEX格式发HEX函数
                               UART_Send_HEX(INT0_PIN);// 串口HEX格式发HEX函数
                               UART_Send_HEX(INT0_PIN);// 串口HEX格式发HEX函数
                               UART_Send_HEX(INT0_PIN);// 串口HEX格式发HEX函数
                               UART_Send_HEX(INT0_PIN);// 串口HEX格式发HEX函数
                               UART_Send_Hex_txt(0xee); //发送数据给串口
                               
                          if (ADXL345_wakeup == 1)//
                                {
                                UART_Send_String("testweakup=1 ...\r\n");// 串口发送数据 已经唤醒
                                ADXL345_wakeup=0;//   中断内的唤醒标志位归零
                               
                               
                               adxl345_read_data();//读取ADXL345的数据
             Determine_ADXL345_Orientation();// 判断哪一面向上
                               UART_Send_NewLine() ;// 串口发送换行
             UART_Send_Hex_txt(number); //发送色子面数据给串口
         UART_Send_NewLine();//串口发送换行
                       
                               
                               
                               int_source= Single_Read_ADXL345(0x30); // 读取标志位 用于清除标志位 恢复中端口低电平
                                delay(4000);
                                }
}这段程序很清晰明了啊按说不应该唤醒两次 也不应该给电脑发送2次信息

DebugLab 发表于 2025-3-17 14:12:08

唤醒是硬件决定的,设置双边沿触发,电平变化就一定会唤醒,这是正常的
但只有上升沿执行ADXL345_wakeup = 1
唤醒后继续执行程序(从哪睡眠的就从哪继续)
外部电路如果是推挽输出或有上拉接单片机IO,单片机IO就不用设置准双向或打开4K上拉,高阻就行
如果需要进入省电模式,IO需要设置为高阻或与外部状态相同的电平,不让IO有电流,否则会耗电

帕拉丁 发表于 2025-3-17 14:19:03

DebugLab 发表于 2025-3-17 14:12
唤醒是硬件决定的,设置双边沿触发,电平变化就一定会唤醒,这是正常的
但只有上升沿执行ADXL345_wakeup =...

谢谢大佬 我继续找找 到底是什么原因导致了一个波形两次唤醒。谢谢大佬

ercircle 发表于 2025-3-17 15:50:39

有没有示波器抓波形看下是否真的一个波形~

帕拉丁 发表于 2025-3-18 09:12:01

ercircle 发表于 2025-3-17 15:50
有没有示波器抓波形看下是否真的一个波形~

谢谢大佬昨天下午捣鼓了一下午示波器看波形很多时候 ADXL345 触发了2次波形导致 谢谢大佬 正在深入研究。

xiaocake 发表于 2025-3-19 21:11:22

INT0设置为仅下降沿触发。( IT0=1 )
ADXL345静止后输出高还是低,是你自己定义的吗?
如果是你定义的,你改成输出低。
如果不是你定义的,你把ADXL345输出信号取反再接单片机。

页: [1] 2
查看完整版本: 各位前辈大佬号,小弟遇到一个2次唤醒的情况