在stm32调试过程中加入一个延时,有两种方式:一种是纯计数方式,另一种是使用系统计数器的方式。
现使用系统计数器产生中断的方式实现,查阅STM32的编程手册可知,STM32有一个24bit的系统计时器,并有STK_CTRL、STK_LOAD、STK_VAL、STK_CALIB寄存器供读写配置。
而CORTEX_M3有提供了一些函数可以供我们调用来控制这几个寄存器。
在编写延时函数时需要的库函数:
/**
brief System Tick Configuration
details Initializes the System Timer and its interrupt, and starts the System Tick Timer.
Counter is in free running mode to generate periodic interrupts.
param [in] ticks Number of ticks between two interrupts.
return 0 Function succeeded.
return 1 Function failed.
note When the variable __Vendor_SysTickConfig is set to 1, then the
function SysTick_Config is not included. In this case, the file device.h
must contain a vendor-specific implementation of this function.
*/
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
{
return (1UL); /* Reload value impossible */
}
SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
return (0UL); /* Function successful */
}
它将延时计数写入LOAD寄存器,设置时钟源为AHB并启动计数器。
如果我们使用的系统时钟为72MHz,那么如果ticks的值设置为72,000,000,则完成一个计数周期为1s,那么如果ticks值为72,000则计数周期为1ms,ticks值为72则计数周期为1us。
在计数器运行的过程中,每次计数都会产生一个系统中断,如果我们在中断中进行计数,就可以得到一个“准确”的延时了。
源码如下:
volatile unsigned long time_delay; // 延时时间,注意定义为全局变量,并且要在中断中做自减
/*********************************************************************************************
函 数 名: delay_ms
实现功能: 延时一定的毫秒数
输入参数: volatile unsigned long nms: 延时的毫秒数
输出参数: 无;
返 回 值: 0 发送成功,
其他 发送失败;
说 明: 无;
*********************************************************************************************/
void delay_ms(volatile unsigned long nms)
{
//设置计数器 若失败则返回1
if (SysTick_Config(SYS_FREQ/1000))
{
while (1)
{
printf("delay_ms init errorn");
}
}
time_delay=nms;//读取定时时间
while(time_delay);
SysTick->CTRL=0x00; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
/*********************************************************************************************
函 数 名: delay_us
实现功能: 延时一定的微秒数
输入参数: volatile unsigned long nus: 延时的微秒数
输出参数: 无;
返 回 值: 0 发送成功,
其他 发送失败;
说 明: 无;
*********************************************************************************************/
void delay_us(volatile unsigned long nus)
{
//设置计数器 若失败则返回1
if (SysTick_Config(SYS_FREQ/1000000))
{
while (1)
{
printf("delay_us init errorn");
}
}
time_delay=nus;//读取定时时间
while(time_delay);
SysTick->CTRL=0x00; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
extern __IO unsigned long time_delay; // 延时时间,注意定义为全局变量,并且要在中断中做自减
void SysTick_Handler(void)
{
if(time_delay > 0)
{
time_delay--;
}
}
需要注意的是,SysTick_Config()函数的使用需要调用core_cm3.h,而单独包含 core_cm3.h则会产生error:#20:identifier"IRQn_Type"isundefined 错误,这是因为数据类型RQn_Type是在stm32f10x.h中声明的,而core_cm3.h并没有进行包含,所以我们应用程序需要在包含core_cm3.h之前包含stm32f10x.h才可以。
上一篇:stm32的启动文件--startup_stm32f10x_hd.s
下一篇:STM32 HAL库 硬件I2C 从机主机防BUG程序
推荐阅读最新更新时间:2024-11-09 10:55
设计资源 培训 开发板 精华推荐
- 【RA】流水灯
- 使用 NXP Semiconductors 的 TDA8559 的参考设计
- LTC3735EG 演示板,IMVP4 电源(钢崖模块),Vin = 5V 至 24V,Vout = 0.6V-1.75V@32A
- 使用 Analog Devices 的 LTC4162IUFD-FSTM 的参考设计
- DEVKIT-S12VR64: S12VR64 MCU评估开发板
- LTC6990HDCB#TRMPBF 隔离式 V-F 转换器的典型应用。 VIN 由隔离测量电路提供。隔离器的 5 us 上升/下降时间将 fMAX 限制为 60kHz
- LT3091EFE 12V 至 ±3.3V 低噪声电源的典型应用
- LT8315EFE 12V 高输入电压隔离反激式转换器的典型应用电路
- 【牡师院】懂你的自拍杆
- 用于开/关控制应用的 AM2G-4824SZ 24V 2 瓦 DC-DC 转换器的典型应用