stm32for循环几个机械周期,为什么我需要在STM32编程无限循环?

I'm programing a STM32F4 in C (gcc), it's a ARM Cortex M4, I see all examples finish their main() function with an infinite loop, even when the rest of the program will be executed from interruptions. If I try to remove the loop from my program, the interruptions stop being fired too.

Why can't I just remove this loop and exit the main thread?

here is the assembly (I guess it's thumb, but I can't read that, even with the doc):

LoopFillZerobss:

ldr r3, = _ebss

cmp r2, r3

bcc FillZerobss

/* Call the clock system intitialization function.*/

bl SystemInit

/* Call the application's entry point.*/

bl main

bx lr

.size Reset_Handler, .-Reset_Handler

解决方案

Take a look at the setup code that runs before main in your project. It might be some slim assembly code or something more complicated, but in general it's pretty close to the bare minimum amount of processor setup required to initialize a stack and get the C runtime going.

If you were return from main, what is your processor supposed to do? Reset? Hang? There's no one good answer, so you'll have to look at the runtime support code being linked with your program to see what its designers decided. In your case, it sounds like they didn't make any allowances for main to return, so the processor just crashes/takes an exception and your program stops working.

Edit: It seems like what you're actually looking for is a way to enter a low power state during the idle loop. That's certainly possible - since your processor is an ARM Cortex-M4, there's a simple instruction to do just that:

while (1)

{

asm("wfi");

}

If you're using CMSIS (and it looks like you are, given your use of SystemInit), the assembly is probably already done for you:

while(1)

{

__WFI();

}

More details at this link.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用定时器的输入捕获功能来实现按键控制定时器周期。 具体实现步骤如下: 1. 配置定时器为输入捕获模式,并设置计数器的自动重装载值,这个值决定了定时器的周期。 2. 配置按键引脚为输入模式,并启用中断。 3. 在按键中断处理函数中,读取定时器计数器的值,并根据需要修改自动重装载值,从而改变定时器的周期。 4. 在主函数中启动定时器。 下面是一个示例代码,其中TIM2是定时器,PA0是按键引脚: ```c #include "stm32f10x.h" void TIM2_IRQHandler(void) { if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_CC2); // 读取定时器计数器的值 uint32_t cnt = TIM_GetCapture2(TIM2); // 根据需要修改自动重装载值 if (cnt > 1000) { TIM_SetAutoreload(TIM2, 2000); } else { TIM_SetAutoreload(TIM2, 1000); } } } void EXTI0_IRQHandler(void) { if (EXTI_GetITStatus(EXTI_Line0) != RESET) { EXTI_ClearITPendingBit(EXTI_Line0); // 启动定时器 TIM_Cmd(TIM2, ENABLE); } } int main(void) { // 配置定时器 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; TIM_TimeBaseInitStruct.TIM_Prescaler = 7199; // 72MHz / 7200 = 10kHz TIM_TimeBaseInitStruct.TIM_Period = 1000; // 默认周期为1s TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct); // 配置定时器输入捕获 TIM_ICInitTypeDef TIM_ICInitStruct; TIM_ICInitStruct.TIM_Channel = TIM_Channel_2; TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStruct.TIM_ICFilter = 0; TIM_ICInit(TIM2, &TIM_ICInitStruct); // 配置按键引脚 GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStruct); // 配置中断 NVIC_InitTypeDef NVIC_InitStruct; NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); EXTI_InitTypeDef EXTI_InitStruct; EXTI_InitStruct.EXTI_Line = EXTI_Line0; EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStruct.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStruct); // 启动中断 TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE); while (1) { // 主循环 } return 0; } ``` 在这个示例中,按下按键会启动定时器,定时器周期默认为1s,当定时器计数器的值大于1000时,将定时器周期修改为2s。注意,这里的计数器值和自动重装载值都是按照定时器时钟为10kHz来计算的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值