STM32和keil5嵌入式实验:.缩写一个硬件延时函数delay(uint32ms),参数为需要的延时的毫秒数,调用实现任意毫秒延时。
时间: 2024-02-23 20:58:03 浏览: 162
好的,这是一个常见的嵌入式开发问题。以下是一个简单的实现:
```c
void delay(uint32_t ms) {
uint32_t i, j;
for (i = 0; i < ms; i++) {
for (j = 0; j < 8000; j++) {
__NOP(); // 空操作,用于占用 CPU 时间
}
}
}
```
这个函数通过嵌套两个循环来实现延时。外层循环是延时的毫秒数,内层循环是一个空循环,用于占用 CPU 时间。在 STM32 上,每个空循环需要大约 5 个时钟周期,因此 8000 次空循环大约需要 1 毫秒的时间。
请注意,这个函数是一个粗略的延时函数,实际延时时间可能会有一些误差。如果需要更加精确的延时,请使用定时器或者其他更加高级的延时技术。
相关问题
嵌入式实验STM32和keil5:1.缩写一个硬件延时函数delay(uint32ms),参数为需要的延时的毫秒数,调用实现任意毫秒延时。 2.三个灯的引脚都可以设置为某个定时器PWM的输出引脚,当三个灯以不同亮度输出,混合在一起时,就可以混出不同的颜色,即调光功能。尝试将三个引脚都配置这PWM功能,在程序中设置不同的占空比,观察亮度变化。
好的,针对你的问题,我来分别回答。
1. 实现任意毫秒延时的函数如下:
```
void delay(uint32_t ms)
{
uint32_t i, j;
for(i = 0; i < ms; i++) {
for(j = 0; j < 72000; j++); // 在 72MHz 的主频下,大约需要延时 1ms
}
}
```
上面的函数使用了 for 循环来进行延时,每个循环大约需要 1ms 的时间,因此可以根据需要的延时毫秒数来确定循环次数。需要注意的是,这种方式并不是很准确,如果需要更精确的延时,可以使用定时器或者外部中断等方式来实现。
2. 通过 PWM 调光的代码如下:
```
#include "stm32f10x.h"
void PWM_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Period = 999; // PWM 信号频率为 1000Hz
TIM_TimeBaseStructure.TIM_Prescaler = 71; // 时钟预分频为 72
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OC1Init(TIM2, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_OC2Init(TIM2, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_Cmd(TIM2, ENABLE);
}
void PWM_SetDutyCycle(uint16_t channel, uint16_t dutyCycle)
{
switch(channel) {
case 1:
TIM_SetCompare1(TIM2, dutyCycle);
break;
case 2:
TIM_SetCompare2(TIM2, dutyCycle);
break;
case 3:
TIM_SetCompare3(TIM2, dutyCycle);
break;
default:
break;
}
}
int main(void)
{
PWM_Init();
while(1) {
PWM_SetDutyCycle(1, 100); // 设置第一个引脚的占空比为 10%
PWM_SetDutyCycle(2, 500); // 设置第二个引脚的占空比为 50%
PWM_SetDutyCycle(3, 900); // 设置第三个引脚的占空比为 90%
delay(1000); // 延时 1 秒
}
}
```
上面的代码中,我们使用了定时器 TIM2 来产生 PWM 信号,将三个灯的引脚都设置为了 PWM 输出引脚。在主函数中,我们通过调用 PWM_SetDutyCycle 函数来设置不同的占空比,从而实现了三个灯的不同亮度输出。最后,我们加入了一个 delay 函数,延时 1 秒钟,这样可以看到灯的亮度变化。
keil5 stm32里延时函数怎么写
在Keil5 STM32中,可以使用以下方式编写延时函数:
```c
#include "stm32f4xx.h"
void delay_us(uint32_t us) {
uint32_t ticks = us * (SystemCoreClock / 1000000);
volatile uint32_t counter = 0;
while (counter < ticks) {
counter++;
}
}
void delay_ms(uint32_t ms) {
uint32_t ticks = ms * (SystemCoreClock / 1000);
volatile uint32_t counter = 0;
while (counter < ticks) {
counter++;
}
}
```
在这个例子中,我们定义了两个延时函数:`delay_us`和`delay_ms`。这两个函数都接受一个参数,即需要延时的时间(以微秒或毫秒为单位)。函数内部使用一个循环来实现延时,循环的次数根据系统时钟频率和延时时间计算得出。请注意,这里使用了`volatile`关键字来防止编译器优化掉延时循环。
使用这些延时函数时,只需在需要延时的地方调用相应的函数即可。例如,要延时100微秒,可以使用`delay_us(100)`;要延时1毫秒,可以使用`delay_ms(1)`。
请注意,这种延时方式适用于一般的延时需求,对延时精度要求不高的应用场景。如果需要更高精度的延时,可以考虑使用定时器或外部晶振来实现。
#### 引用[.reference_title]
- *1* *2* *3* [STM32延时函数的四种方法](https://blog.csdn.net/huaweibiancheng3/article/details/124956486)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item]
[ .reference_list ]
阅读全文