1. 如果你不跑操作系统,CPU肯定一直都是100%使用的,哪怕你里面是延时等待,CPU也是一直在执行空语句nop,因为STM32里面是有一个CPU。
2.对于stm32总是百分百。只是有多少时间空闲,多少时间干活!
3.
楼主的意思是实际CPU用来干正事的时间,在整个时间里的比例,打个比方,如果工作50mS,再等待200mS,完成一个大循环,那么CPU的使用率就是20%。 如果楼主的程序是以大循环方式做的,那么在进入等待前把一个IO口拉低,等待结束,开始工作,把IO口拉高,那么占空比就是使用率,当然这是在各种中断不是很频繁,而且中断里处理的事情很少的情况下有用,我经常这么估算MCU的速率富余度的,然后据此设置一个合适的MCU工作频率,降低不仅仅是CPU的功耗那一点点电能,如果是线性降压,整个功耗下降很多的,发热就低了,而且工作频率下降,CPU稳定性也会增强。 |
4.
首先,我们知道Cortex有几种内核的低功耗工作状态,Sleep, Stop, Standby
这里我用到的是Sleep状态,即设计程序时,当程序的任务处理完后,使单片机进入WFE或WFI的Sleep状态:
使用操作系统时,直接在空闲任务中添加__WFI();或__WFE();即可
裸机程序时,设计程序结构为大main循环为中断或事件触发的形式,即main循环等待队列中的任务,当队列为空时,执行__WFI();或__WFE();。添加队列的操作在串口、按键、计时器中断中进行,等等。
然后,我们采用的是外设的低功耗状态,即STM32的外设可以在内核进入低功耗状态后,手动或自动停止外设的时钟,当退出低功耗状态时手动或自动恢复外设始终。
由于我这方法是在F4上面实现的,采用F1实现时,会显得臃肿一些,大家理解啥意思就行了,采用F4时会方便很多。
这是F1的外设低功耗特性,可见,外设在内核进入低功耗状态时,外设时钟只能手动打开和关闭。
这是F4的外设低功耗特性,可见,外设在内核进入低功耗状态时,外设时钟可以自动关闭。
在使用F4时,我们就可以采用如TIM6和TIM7两个计时器
配置如下
1. void tim6_init(void)
2. {
3. TIM_TimeBaseInitTypeDef TIM_InitStructure;
4.
5. RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM6, ENABLE );
6. RCC_APB1PeriphClockLPModeCmd(RCC_APB1Periph_TIM6, DISABLE);
7.
8. TIM_DeInit(TIM6);
9. TIM_InitStructure.TIM_Prescaler = 180;
10. TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
11. TIM_InitStructure.TIM_Period = 65535;
12. TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
13. TIM_InitStructure.TIM_RepetitionCounter = 0;
14. TIM_TimeBaseInit(TIM6, &TIM_InitStructure);
15. TIM_SetCounter(TIM6, 0);
16. TIM_ITConfig(TIM6, TIM_IT_Update, DISABLE);
17. TIM_Cmd(TIM6, ENABLE);
18. }
19. void tim7_init(void)
20. {
21. TIM_TimeBaseInitTypeDef TIM_InitStructure;
22. NVIC_InitTypeDef NVIC_InitStructure;
23.
24. RCC_APB2PeriphClockCmd (RCC_APB2Periph_SYSCFG, ENABLE);
25. RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM7, ENABLE);
26. RCC_APB1PeriphClockLPModeCmd(RCC_APB1Periph_TIM7, ENABLE);
27.
28. TIM_DeInit(TIM7);
29. TIM_InitStructure.TIM_Prescaler = 180;
30. TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
31. TIM_InitStructure.TIM_Period = 65535;
32. TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
33. TIM_InitStructure.TIM_RepetitionCounter = 0;
34. TIM_TimeBaseInit(TIM7, &TIM_InitStructure);
35. TIM_SetCounter(TIM7, 0);
36. TIM_ITConfig(TIM7, TIM_IT_Update, ENABLE);
37.
38. NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn;
39. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03;
40. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03;
41. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
42. NVIC_Init(&NVIC_InitStructure);
43.
44. TIM_Cmd(TIM7, ENABLE);
45. }
复制代码
TIM7中断代码如下:
1. void TIM7_IRQHandler(void)
2. {
3. TIM7->SR = ~TIM_IT_Update;
4. CPU_TICK_USAGE = TIM6->CNT;
5. TIM6->CNT = 0;
6. }
复制代码
计算CPU使用率(%)如下:
1. CPULoad = (float)CPU_TICK_USAGE*100.0f/65535.0f
复制代码
当采用F1时,那就需要在每个中断的入口处,手动添加代码,使能TIM6时钟
并在每个__WFE();或__WFI();前手动添加代码,关闭TIM6时钟
在每个__WFE();或__WFI();后手动添加代码,使能TIM6时钟
当然,采用F1时,不用__WFE();或__WFI();而只用while循环也是一样的。
5.
围观,个人觉得既然是裸机,就没必要考虑CPU的使用率了 |
6.
在一般的应用中还是可以采用的,如现在我做的变频器项目,可以通过查看CPU的使用率考虑算法的复杂性,并根据CPU使用率确定最高的采样频率和PWM周期,同时确定CPU主频选取的是否合适。按我的感觉是,CPU使用率为75~85%时最合适。 |