- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
在平时使用单片机的时候,一般不太关心功耗的问题。但是当产品需要使用电池供电的话,那么功耗问题就要必须重视起来。那么如何降低单片机的功耗呢?STM8官方资料上给我们提供了以下几点建议:
如果项目中对系统的时候有要求,那么就不能通过降低系统时钟来降低功耗,此时就可以通过使用低功耗模式来降低功耗。低功耗模式有三种:等待(Wait)
、活跃停机(Active Halt)
、停机(Halt)
。
官方文档中介绍等待模式的设置只需要执行WFI指令即可。
如果需要退出低功耗模式,就需要通过外部中断、内部中断、或者复位来实现。
现在就来演示一下如何通过代码设置等待(Wait)
模式。
这里使用一个LED灯闪烁来表示单片机运行在正常模式中。上电后LED灯开始闪烁,闪烁几秒钟之后使用指令进入 低功耗的 等待(Wait)模式,此时LED灯将不再闪烁,此时如果单片机内部发生了中断或者IO口上出现了外部中断,那么单片机就会退出低功耗模式,LED灯就会继续闪烁。
那么编写程序时就要用到IO口来控制LED灯的亮灭,还需要一个内部中断,这里就使用内部定时器中断,然后还需要一个外部IO的触发中断。
首先初始化LED的IO口,这里使用PB5口来驱动LED灯。为了方便控制,这里使用宏定义将PB5口的输出重新定义为LED,这样给LED赋值的时候,就相当于直接操作了寄存器。
#define LED PB_ODR_ODR5
void LED_GPIO_Init( void )
{
PB_DDR |= ( 1 << 5 ); //PA1 输出 led
PB_CR1 |= ( 1 << 5 ); //PA1 推挽输出
}
接下来初始化内部定时器,这里使用定时器4进行一个1ms的定时。如果单片机进入低功耗模式后,定时器的定时中断就可以将单片机从低功耗模式中唤醒。
void Timer4_Init( void )
{
TIM4_PSCR = 0x07; //2^7= 128 分频 125k --> 8us
TIM4_SR = ( ~0x01 ); //清除更新中断标志
TIM4_ARR = 124; //125--1ms
TIM4_CNTR = 0;
TIM4_CR1 |= 0x01; //使能计数器
TIM4_IER |= 0x01; //更新中断使能
}
#pragma vector = 25 // IAR中的中断号,要在STVD中的中断号上加2
__interrupt void Timer4_Handle( void ) //1ms 定时中断
{
TIM4_SR = ( ~0x01 ); //清除更新中断标志
//可以通过定时器中断,将单片机从等待模式中唤醒。
}
还需要初始化一个外部中断,用于测试通过外部中断将单片机从低功耗唤醒。
//初始化PD2口
void EXTI_GPIO_Init( void )
{
PD_DDR &= ( ~( 1 << 2 ) ); //输入
PD_CR1 &= ( ~( 1 << 2 ) ); //浮空输入
PD_CR2 |= ( 1 << 2 ); //打开外部中断
}
//PD2口为中断输入 低电平触发
void EXTI_Init( void )
{
EXTI_GPIO_Init();
EXTI_CR1 &= ~( 3 << 6 ); //6 7 位清零
EXTI_CR1 |= ( 1 << 6 ); //PD上升沿触发
}
//端口D外部中断 中断号6
#pragma vector = 8 // IAR中的中断号,要在STVD中的中断号上加2
__interrupt void EXTI_PORTC_Handle( void )
{
//外部中断会将单片机从 停机模式唤醒
}
需要的外设准备好之后,接下来就可以编写主函数了。
void SysClkInit( void )
{
CLK_SWR = 0xe1; //HSI为主时钟源 16MHz CPU时钟频率
CLK_CKDIVR = 0x00; //CPU时钟0分频,系统时钟0分频
}
void main( void )
{
unsigned int cnt = 0;
__asm( "sim" ); //禁止中断
SysClkInit();
delay_init( 16 );
LED_GPIO_Init();
EXTI_Init();
// Timer4_Init();
__asm( "rim" ); //开启中断
while( 1 ) //进入低功耗之前,电流5.5mA
{
LED = !LED;
delay_ms( 500 );
cnt++;
if( cnt > 10 ) //进入低功耗之后,电流1.8mA
{
cnt = 0;
__asm("wfi"); //进入等待模式 外部中断 或者 内部中断 或者 复位 唤醒中断
}
}
}
首先初始化系统时钟和需要的外设,然后在循环中给LED取反,当LED灯闪烁5s之后,使用 WFI 命令让单片机进入 等待模式(Wait)
中。此时LED灯将不会再闪烁。如果给PD2口上接一个高电平,那么就会触发外部中断,单片机将会从等待模式中退出。LED灯就继续开始闪烁。
如果要测试内部中断唤醒单片机,就需要将初始化中定时器4的初始化代码取消屏蔽。
Timer4_Init();
如果开启了定时器4的中断之后,就会发现LED灯会一直闪烁,5s之后并没有停止闪烁。这是因为单片机进入低功耗模式之后,定时器4的中断出现了,单片机就又被从低功耗模式中唤醒了。由于定时器4是1ms中断,这个时间非常短,通过肉眼观察不出来。此时只能通过单步调试模式,在程序中打断点来观察单片机进入和退出低功耗模式。
通过万用表来检测单片机的电流,当LED灯闪烁的时候,单片机的电流为5.5mA左右,当LED灯不再闪烁的时候,单片机的电流为1.8mA左右。说明进入低功耗模式之后,单片机的耗电确实减小了很多。
此工程是在IAR编译器上实现的,所以进入低功耗的WFI指令使用的是嵌入汇编指令。
__asm("wfi");
不同的编译器中嵌入汇编的指令方法是不一样的,如果使用的是其他的编译器,进入低功耗模式的命令写法有可能和这个不一样。
完整工程下载链接:STM8单片机低功耗wait模式实现
我正在对 JVM 上的 STM 技术进行一些研究。阅读了一些文档后,我对 Multiverse 的实现有些困惑。 根据 the Multiverse FAQ , Multiverse 不支持检测。然而
我想知道 Clojure 怎么可能已经实现了软件事务内存并且没有发现任何问题,而微软没有完成它的 C# 工作并注意到一些问题使得实现这里描述的 STM 不切实际: http://www.bluebyt
最后,我有以下设置 C:>哪里玩 C:\apps\play-2.2.0\play C:\apps\play-2.2.0\play.bat C:> 哪里 scala C:\apps\scala\bin\
我试图找出 Clojure 所称的 STM 与 Haskell 中实现的 STM 之间的区别。撇开实际的语言语义差异不谈,正如 Rich Hickey 在他的演讲中所说,Clojure 的 STM 实
阅读 Bartosz Milewski 的精彩作品 blog post在 STM 上,我很兴奋地阅读了以下内容: But take into account an important fact: ST
大家好, 在某些时候,我认为这些 stm 实现(我使用过一点点的多元宇宙......),被过度宣传了。因为在某些时候他们使用 CAS 来为他们提供操作的原子性。如果我直接使用 CAS 而不是使用这些实
haskell 的 stm 库中有一个函数,其类型签名如下: alwaysSucceeds :: STM a -> STM () 根据我对 Haskell 中 STM 的了解,在执行 STM 计算时,
在 Clojure 中,我们使用 STM 来实现并发。 我的问题是STM使用数据的时间点值,这是否会带来歧义? 我们如何知道访问了什么值? 最佳答案 Clojure 中的 STM 提供了(通过 ref
我需要有关用作原子更改日志的数据结构的建议。 我正在尝试实现以下算法。有流量传入更改更新内存中的映射。在类似 Haskell 的伪代码中它是 update :: DataSet -> Some
我正在尝试对这两个(软件事务内存和原子操作,我想两者不一样)进行一些基准测试,尽管我没有使用STM做太多事情(它似乎很难使用),但我成功地尝试了对基准测试进行计数,即所有线程将共享计数器递增 5000
我能够使用 STM 初始化状态并将其打印出来: module Main where import Control.Concurrent.STM data State = State {name ::
我读过两个关于 STM 如何实现的完全不同的描述。也许两者都是正确的,或者一个是错误的,我希望有人能阐明这一点。 Take 1(维基百科):允许所有线程修改共享内存,但事务中的每次读写都会被记录下来。
我知道将具有副作用的函数放在 STM 事务中通常是不好的做法,因为它们可能会被重试和调用多次。 然而,在我看来,您可以使用代理来确保只有在事务成功完成后才会执行副作用。 例如 (dosync //
我正在编写一个程序,其中大量代理监听事件并对其使用react。由于Control.Concurrent.Chan.dupChan已弃用我决定使用 TChan 的广告。 TChan 的表现比我预想的差很
我正在研究 Clojure 中的并发编程。 http://clojure.org/concurrent_programming 我了解到atom、ref和agent形式是用来维护程序状态的。 仅ref
你好,我正在阅读《clojure 的乐趣》这本书,在关于 STM 的部分中,他们有一个 2 个事务的图像,其中 A 最初从引用中检索与 B 相同的值,然后事务 A 和 B 都进行计算但 A 首先完成并
我熟悉Database transactions ,并花费了大量的时间调整isolation levels 。我从未在代码中实现过自己的事务模型。 我已通读 the source code对于 Clo
我有一个事务由于某种原因无限期失败,我想在内部使用跟踪指令。例如,要在执行此片段中的事务之前打印 MVar 的状态: data_out do putTMVar
当我们运行 STM 表达式时,它命中了 retry,线程被阻塞,如果条目被修改,事务将再次运行。 但我想知道: 如果我们读取一个 STM 变量,但在导致重试的特定分支中实际未使用该变量,更新它是否会尝
我正在研究 Clojure 中的并发编程。 http://clojure.org/concurrent_programming 我了解到atom、ref 和agent 表单用于维护程序状态。 只有 r
我是一名优秀的程序员,十分优秀!