CC2541电脑睡眠模式自动唤醒下,为什么中断无法唤醒

CC2530 睡眠定时器实验1(中断唤醒)
CC2530 睡眠定时器实验1(中断唤醒)
/*****************************************//by 虚幻代码//名称:CC2530 睡眠定时器实验1(中断唤醒) //说明:程序指定S1为外部中断源唤醒CC2530,每次系统唤醒LED1灯亮,LED2闪烁10下后关闭两LED,进入系统睡眠模式PM3。*****************************************//*引用********************************************/#include &iocc2530.h&/*宏定义*****************************************/#define uint unsigned int#define uchar unsigned char#define rled P1_0#define gled P1_1/*函数定义*******************************///延时函数void delay(void){& uint i;& for(i=0;i&15000;i++);& for(i=0;i&15000;i++);& for(i=0;i&15000;i++);& for(i=0;i&15000;i++);& for(i=0;i&15000;i++);}//系统工作模式选择函数void syspowermode(uchar mode){& uchar i,j;& i=mode;& if(mode&4)& {&&& SLEEPCMD &=0XFC;&&& SLEEPCMD |=i;//设置系统睡眠模式&&& for(j=0;j&4;j++);//延时&&& PCON=0X01;//进入睡眠模式& }& else& {&&& PCON=0X00;//系统唤醒& }}&&& //LED初始化void initled(void){& P1SEL &=0XFC;//P1_0,P1_1接口设为通用接口模式& P1DIR|=0X03;//P1_0,P1_1接口设为输出模式& rled=0;& gled=0;}//初始化按键为中断输入方式void initkey(void){& P0SEL &=0XFD;//P0_1设为通用I/O& P0DIR &=0XFD;//P0_1设为输入& P0INP &=0XFD;//P0_1设为上拉/下拉模式& P2INP &=0XDF;//P0引脚设为上拉& & P0IEN |=0X02;//P0_1中断使能& PICTL |=0X01;//P0中断下降沿触发& IEN1 |=0X20;//P0中断使能& EA=1;//总中断开启& P0IFG =0X00;//清除P0所有中断标志位}/*主函数*******************************/void main(void){& uchar count=0;& initled();& initkey();& rled=1;& delay();& & while(1)& {&&& gled=!gled;&&& rled=1;&&& count++;&&& if(count&=20)//闪烁20下,延时20次&&& {&&&&& count=0;&&&&& rled=0;&&&&& syspowermode(3);//进入PM3&&& }&&& delay();& }& }/*中断函数定义********************************///P0中断函数#pragma vector=P0INT_VECTOR__interrupt void P0_ISR(void){& if(P0IFG&0)//P0所有标志位清0& {&&& P0IFG=0;& }& P0IF=0;& syspowermode(4);//激活供电模式}
发表评论:
TA的最新馆藏[转]&[转]&后使用快捷导航没有帐号?
查看: 956|回复: 1
ATmega8 睡眠外部中断0可以唤醒,但定时器2中断不能唤醒,错在那里?
在线时间43 小时
TA的帖子TA的资源
一粒金砂(中级), 积分 20, 距离下一级还需 180 积分
一粒金砂(中级), 积分 20, 距离下一级还需 180 积分
/*********************************************&&
开 发 环 境: ICCAVR 7.22
硬件平台:ATmega8
**********************************************/&&
#include&iom8v.h&&&
#include&macros.h&
#define uint&&unsigned int
#define uchar unsigned char& &
//--------------1ms延时子程序----------------
void delay_nms(uint x)
& & while(x--)
& && &&&for(i=0; i&800; i++)
& && && && &;
/*******************************************
/********************************************/&&
void Port_Init(void)&&
& & PORTB = 0x00;&&
& & DDRB&&= 0xFF;&&
& & DDRD=0X00;&&
& & PORTD=0XFF;&&
/*******************************************
外部中断0ATmega8_4脚
/********************************************/&&
void Power_Init(void)&&
& & MCUCR |= 0X20;//掉电模式,外部中断0低电平触发&&
& & GICR |= 0X40; //外部中断0使能&&
& & SREG |= 0X80;//使能总中断&&
//*********************************************
//T2初始化:CTC模式,匹配中断频率:6Hz
//*********************************************
void Timer2_init(void)
& && &&&TCCR2 = 0x00; //T/C控制寄存器-TCCR2
& && &&&ASSR&&= 0x08; //器ASSR的AS2置位,定时器在T2睡眠时继续运行。
& && &&&TCNT2 = 0x00; //计数器的数值TCNT2
& && &&&OCR2&&= 0x7f;//0x7f;/输出比较寄存器 OCR2
& && &&&TCCR2 = 0x09; //start
& && &&&while(ASSR&0X07);
/*******************************************
4&&定时器 /计数器2比较匹配
5&&定时器 /计数器2溢出
/********************************************/
#pragma interrupt_handler Timer2:5
void Timer2(void)&&
& & for (i=0;i&3;i++)&&
& && &&&PORTB |= BIT(0);&&//ATmega8 _14脚
& && &&&delay_nms(600);&&
& && &&&PORTB &= ~BIT(0);&&
& && &&&delay_nms(600);&&
//**********外部中断0的服务函数*************
#pragma interrupt_handler int0_isr:2&&
void int0_isr(void)
& & for (i=0;i&5;i++)&&
& && &&&PORTB |= BIT(0);&&//ATmega8 _14脚
& && &&&delay_nms(600);&&
& && &&&PORTB &= ~BIT(0);&&
& && &&&delay_nms(600);&&
/*******************************************
函数 名称: Device_Init
功& &&&能: 器件初始化&&
/********************************************/&&
void Device_Init(void)&&
& & Port_Init();& && &&&//IO端口初始化&&
& & Power_Init();& && & //外部中断,省电模式,初始化
& & & & Timer2_& && &&&//定时器2中断,省电模式,初始化
/*******************************************
函数 名称: main&&
/********************************************/&&
void main(void)&&
& & Device_Init();&&
& & while(1)&&
& && && &for (i=0;i&10;i++)&&
& && &&&{&&
& && && && &PORTB |= BIT(1);& &&&//ATmega8_15脚
& && && && &delay_nms(300);&&
& && && && &PORTB &= ~BIT(1);
& && && && &delay_nms(300);&&
& && &&&}&&
& & & & & & & &
& & & & & & & &
& & & & & & & &
& & & & & & & &&&MCUCR |= BIT(SE)|BIT(SM1)|BIT(SM0);//省电模式休眠初始
& && &&&// MCUCR |= 0x80;& && && & //空闲模式休眠初始化
& && && &asm(&sleep&);& && && && & //使能休眠
& && && &for (i=0;i&5;i++)&&
& && &&&{&&
& && && && &PORTB |= BIT(2);& & //ATmega8_16脚
& && && && &delay_nms(300);&&
& && && && &PORTB &= ~BIT(2);
& && && && &delay_nms(300);&&
& && &&&}&&
& & & & & & & &
在线时间591 小时
威望1081 分
芯币7865 枚
E金币280 枚
TA的帖子TA的资源
纯净的硅(中级), 积分 1081, 距离下一级还需 119 积分
纯净的硅(中级), 积分 1081, 距离下一级还需 119 积分
楼主应该先看看数据手册看这款芯片是不是支持定时器2中断唤醒哦,如果不支持,那就不是程序问题了,如果支持,则根据数据手册对程序进行检查,看程序中相关寄存器的配置是否都对了。还有就是建议楼主贴程序的时候尽量规范哦,不然网友看到那么长的代码都跑了
dj的世界一直很好
Powered by
逛了这许久,何不进去瞧瞧?cc2541如何在睡眠模式下开启看门狗? - 无线通信技术专区 -
中国电子技术论坛 -
最好最受欢迎电子论坛!
后使用快捷导航没有帐号?
cc2541如何在睡眠模式下开启看门狗?
16:31:22  
cc2541如何在睡眠模式下开启看门狗?
cc2541做从机,大部分时间处在PM3模式下,使用外部中断唤醒,发现有时候通过中断唤醒时程序会跑飞,所以就开启了看门狗,有一个任务任务定时喂狗。
流程是:外部中断唤醒时,触发定时喂狗任务,当cc2541与主机断开连接时就取消定时喂狗任务(为了能进入PM3),如此循环。
现在的问题是:
设定cc2541广播时间为60s,60s没有连接自动进入PM3,发现喂狗任务一直能执行,也能进入PM3,不会复位
外部中断唤醒时,虽然立刻触发刻定时喂狗任务,但通过仿真发现定时喂狗任务一直没有被执行(看门复位时间设置为1s),程序会复位。
不知问题出在哪里?
16:32:26  
可不可以被唤醒之后马上执行喂狗的代码?不用通过任务来执行
16:32:46  
我发现了问题之所在:
因为我在唤醒之后开启了定向广播,定向广播为GAP_ADTYPE_ADV_HDC_DIRECT_IND,即高速模式,把定向广播改为低速模式之后,喂狗任务就能执行,程序也不会复位了,所以可能是定向广播高速模式下速度太快了,导致osal不能执行喂狗任务导致的
Powered by2693人阅读
学习BLE已有一段时间,从开始时的一片空白到现在的略有领悟。下面来讲讲鄙人学习BLE中的一些领悟。
用BLE的人都知道,BLE的最大亮点是低功耗,实现低功耗的主要方式就是CC2540/CC2541的休眠机制。
& & & &休眠的模式主要分为PM2和PM3两种模式(另一种PM1模式,是用于低于3ms时间的休眠,几乎不用)。唤醒方式主要分为ST睡眠定时器唤醒和外部中断唤醒。唤醒方式和休眠模式的对应关系为:PM2模式是由ST睡眠定时器唤醒,PM3模式是有外部中断唤醒。
许多开发者都想在不用BLE的时候让其进入最低功耗模式:PM3模式,但是在debug程序的时候,发现CC2540工程里的休眠函数都是进入PM2模式的,无法让其自己进入PM3模式。于是,有许多人就想直接编程电源寄存器,让其强行进入PM3。这样的方法是可以达到进入PM3模式,但如果你没有处理好休眠前的现场保护和唤醒后的恢复工作,是会出现溢出,唤醒后程序跑飞的危险,这样反而不会降低功耗的,吃力不讨好。
其实,TI的休眠处理函数已经处理得很好了,只要你掌握了它的休眠机制,你照样可以对其调配自如。下面是我总结的一些浅见。
一、CC2540 or CC2541进入PM3深度休眠的条件
①osal_timeout = 0;
②llTimeout = 0;
只要同时满足上面两个条件,BLE就会自己进入PM3模式,此时,所有内部电路都关闭,只有外部中断和复位电路可以工作,因此,功耗最低,且可通过外部中断对其唤醒。当中的一个不为0,都将进入PM2模式。
下面肯定会有人问上面这两个条件是什么,osal_timeout就是各层的定时事件的某个事件的超时时间,llTimeout是link layer最底层,也就是RF控制器层的定时事件的超时时间。只要其中的一个不等于0,就说明有定时事件存在,需要定时来处理这些事件,因此就需要定时来唤醒芯片来执行这些事件,所以芯片就不能进入PM3(PM3只能是外部中断唤醒),只能进入PM2模式。
所以,也就是说,要想进入PM3模式,就必须清空所有的定时事件,当不存在任何的定时事件时,即osal_timeoout和llTimeout都会为0,这样就直接导致进入PM3模式。清理定时事件,就是深度休眠的前处理。如此,使得整个BLE有良好的鲁棒性。下面从代码的角度来剖析BLE的休眠机制。
二、BLE的休眠函数
下面就是休眠处理函数的源码,里面timeout就是要设置休眠定时器的时间,这个值来自于osal_timeout或者是llTimeout,那个值小,就说明那个事件更紧急,则由小的来赋给timeout设置休眠定时器,执行定时任务。当timeout = 0时,说明没有定时任务了,就可进入PM3深度休眠了。
llTimeout是通过LL_TimeToNextRfEvent( &sleepTimer, &llTimeout )来得到底层的定时事件,LL_TimeToNextRfEvent( &sleepTimer, &llTimeout )函数是link layer的不开源的代码,因此看不到里面的细节,但是可以肯定的是,llTimeout是和RF定时控制事件相关。一般蓝牙广播、连接、初始化,此llTImeout的值就不会为零,当没有广播、断开连接可以使得llTImeout为零。
osal_timeout一般为应用层的定时事件,由osal_start_timeEX(task_id, event, timeout)设定的定时,只要用相应的osal_stop_timeEX( task_id, event )终止所有的事件,就可以使得osal_timeout为零。
void halSleep( uint32 osal_timeout )
uint32 llT
uint32 sleepT
// max allowed sleep time in ms
if (osal_timeout & MAX_SLEEP_TIMEOUT)
osal_timeout = MAX_SLEEP_TIMEOUT;
// get LL timeout value already converted to 32kHz ticks
LL_TimeToNextRfEvent( &sleepTimer, &llTimeout );
// check if no OSAL timeout
// Note: If the next wake event is due to an OSAL timeout, then wakeForRF
will already be FALSE, and the call to LL_TimeToNExtRfEvent will
already have taken a snapshot of the Sleep Timer.
if (osal_timeout == 0)
// use common variable
timeout = llT
// check if there's time before the next radio event
// Note: Since the OSAL timeout is zero, then if the radio timeout is
not zero, the next wake (if one) will be due to the radio event.
wakeForRF = (timeout != 0) ? TRUE : FALSE;
else // OSAL timeout is non-zero
// convet OSAL timeout to sleep time
// Note: Could be early by one 32kHz timer tick due to rounding.
timeout = HAL_SLEEP_MS_TO_32KHZ( osal_timeout );
// so check time to radio event is non-zero, and if so, use shorter value
if ((llTimeout != 0) && (llTimeout & timeout))
// use common variable
timeout = llT
// the next ST wake time is due to radio
wakeForRF = TRUE;
else // OSAL timeout will be used to wake
// so take a snapshot of the sleep timer for sleep based on OSAL timeout
sleepTimer = halSleepReadTimer();
// the next ST wake time is not due to radio
wakeForRF = FALSE;
// HAL_SLEEP_PM3 is entered only if the timeout is zero
halPwrMgtMode = (timeout == 0) ? HAL_SLEEP_DEEP : HAL_SLEEP_TIMER;
// check if sleep should be entered
if ( (timeout & PM_MIN_SLEEP_TIME) || (timeout == 0) )
halIntState_t ien0, ien1, ien2;
HAL_ASSERT( HAL_INTERRUPTS_ARE_ENABLED() );
HAL_DISABLE_INTERRUPTS();
// check if radio allows sleep, and if so, preps system for shutdown
if ( LL_PowerOffReq(halPwrMgtMode) == LL_SLEEP_REQUEST_ALLOWED )
#if ((defined HAL_KEY) && (HAL_KEY == TRUE))
// get peripherals ready for sleep
HalKeyEnterSleep();
#endif // ((defined HAL_KEY) && (HAL_KEY == TRUE))
#ifdef HAL_SLEEP_DEBUG_LED
HAL_TURN_OFF_LED3();
// use this to turn LEDs off during sleep
HalLedEnterSleep();
#endif // HAL_SLEEP_DEBUG_LED
// enable sleep timer interrupt
if (timeout != 0)
// check if the time to next wake event is greater than max sleep time
if (timeout & MAX_SLEEP_TIME )
// it is, so limit to max allowed sleep time (~510s)
halSleepSetTimer( sleepTimer, MAX_SLEEP_TIME );
else // not more than allowed sleep time
// so set sleep time to actual amount
halSleepSetTimer( sleepTimer, timeout );
// prep CC254x power mode
HAL_SLEEP_PREP_POWER_MODE(halPwrMgtMode);
// save interrupt enable registers and disable all interrupts
HAL_SLEEP_IE_BACKUP_AND_DISABLE(ien0, ien1, ien2);
HAL_ENABLE_INTERRUPTS();
// set CC254 interrupts are disabled after this function
// Note: Any ISR that could wake the device from sleep needs to use
CLEAR_SLEEP_MODE(), which will clear the halSleepPconValue flag
used to enter sleep mode, thereby preventing the device from
missing this interrupt.
HAL_SLEEP_SET_POWER_MODE();
// check if ST interrupt pending, and if not, clear wakeForRF flag
// Note: This is needed in case we are not woken by the sleep timer but
by for example a key press. In this case, the flag has to be
cleared as we are not just before a radio event.
// Note: There is the possiblity that we may wake from an interrupt just
before the sleep timer would have woken us just before a radio
event, in which case power will be wasted as we will probably
enter this routine one or more times before the radio event.
However, this is presumably unusual, and isn't expected to have
much impact on average power consumption.
if ( (wakeForRF == TRUE) && !(IRCON & 0x80) )
wakeForRF = FALSE;
// restore interrupt enable registers
HAL_SLEEP_IE_RESTORE(ien0, ien1, ien2);
// power on the LL; blocks until completion
// Note: This is done here to ensure the 32MHz XOSC has stablized, in
case it is needed (e.g. the ADC is used by the joystick).
LL_PowerOnReq( (halPwrMgtMode == CC2540_PM3), wakeForRF );
#ifdef HAL_SLEEP_DEBUG_LED
HAL_TURN_ON_LED3();
#else //!HAL_SLEEP_DEBUG_LED
// use this to turn LEDs back on after sleep
HalLedExitSleep();
#endif // HAL_SLEEP_DEBUG_LED
#if ((defined HAL_KEY) && (HAL_KEY == TRUE))
// handle peripherals
(void)HalKeyExitSleep();
#endif // ((defined HAL_KEY) && (HAL_KEY == TRUE))
HAL_ENABLE_INTERRUPTS();
从上面的代码认真分析,就可以掌握BLE的休眠机制。BLE的所有事件都是间断的,而每个事件间的间歇就是定时休眠的时候。例如,广播可以是每个100ms广播一次,而这100ms就进入了PM2休眠的时间;连接的时候,传输数据是10ms或者100ms连接一次传输,数据的传输也是间断的,这个间歇也是PM2的定时休眠时间。BLE正是因为这种休眠机制而做到了很低的功耗,与传统蓝牙的连续传输相比,功耗降低了许多。
以上粗略地总结了TI源码下PM3深度休眠的条件和简单讲述了BLE的休眠机制,本人菜鸟,此文可能存在错误的理解,斗胆发此文,权当和大家交流学习经验,望吐槽。。。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:2710次
排名:千里之外君,已阅读到文档的结尾了呢~~
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
7.睡眠唤醒(中断唤醒+定时器唤醒)
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口}

我要回帖

更多关于 电脑睡眠模式怎么唤醒 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信