本人初学stm32,今天,昨天,前天分别做了三个实验。
分别是滴答定时器精确延迟,TIM定时器与pwm波,TIM定时器+串口通讯+led灯实现精确时间跳变;
先一个一个讲我的实验、
先贴出滴答定时器精确延迟的程序
这个是SysTick.c源程序
[mw_shl_code=cpp,true]#include "SysTick.h"
#include "main.h"
int TimingDelay;
void SysTick_Init(void)
{
/* SystemFrequency / 1000 1ms中断一次
* SystemFrequency / 100000 10us中断一次
* SystemFrequency / 1000000 1us中断一次
*/
//对以下函数的解释
//SysTick_Config();是一个配置滴答计时器的函数
//我们打开其函数原型
//static __INLINE uint32_t SysTick_Config(uint32_t ticks)
//{
// if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
//
// SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */
// NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */
// SysTick->VAL = 0; /* 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 (0); /* Function successful */
//}
//if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); 而其中这一句是判断传来的数据是否小于2的24次方(如果超过,则会处理不正常,因为STK_LOAD寄存器是24位的)。
//则可知,如果你的配置是正确的话,SysTick_Config(uint32_t ticks)的返回值是零,程序会跳过空循环,直接执行关闭滴答定时器。
//如果你的配置错误(即传来的数据是大于2的24次方),SysTick_Config(uint32_t ticks)的返回值是一,则程序if语句成立,程序会进入空循环,防止进一步出错。
//再解释SysTick_Config()的主要作用(自己理解,不标准请海涵):
//它使用芯片自带的滴答定时器记录时钟周期进行操作:
//将获取的参数传递给LOAD寄存器,LOAD寄存器检查后传递给STK_VAL寄存器
//然后每一个时钟周期就使STK_VAL寄存器的值减一
//当减到0的时候,就会触发中断。进入中断函数。
//if(SysTick_Config(SystemFrequency / 1000))//ST3.0.0库版本
if(SysTick_Config(SystemCoreClock / 1000))//ST3.5.0库版本
{
while(1);
}
SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;//关闭滴答定时器
}
//该函数的作用是有多少个ms
void Delay_ms(int nTime)
{
TimingDelay=nTime;
//使能滴答计时器
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
while(TimingDelay!=0);
}
void TimingDelay_Decrement(void)
{
if(TimingDelay !=0)
{
TimingDelay--;
}
}
[/mw_shl_code]
这个是位于stm32f10x_it.c内的源程序
[mw_shl_code=applescript,true]extern void TimingDelay_Decrement(void);//采用的外部函数此处一定要写
void SysTick_Handler(void)
{
if(TimingDelay!=1)
TimingDelay_Decrement();
if(TimingDelay==1)
Led_Usart(num++);
Delay_ms(1000);
}[/mw_shl_code]
请允许我大概总结一下,这个TICK的原理就是,时钟不分频,然后
通过SysTick_Config(SystemCoreClock / 1000))这句话分将用户需要的中断配置给STK_LOAD寄存器,
SystemCoreCLock:
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz; /*!< System Clock Frequency (Core Clock) */
即时钟的频率,也就是说滴答定时器只能配置STK_LOAD寄存器,无法配置定时器分频和重载周期值,
即:TIM_Prescaler和TIM_Period,(属于TIM定时器的)
而且由于STK_LOAD寄存器是24位的,也就是说STK_LOAD的最大值1677,7216
也就是说滴答定时器最多能撑到1677,7216个以72MHz为频率的时钟周期。72MHz=7200,0000;即不到一秒;
而滴答定时器采用的是向下减的方式,就是当STK_LOAD寄存器传给STK_VAL寄存器后,STK_VAL每经一个时钟周期进行一次自减运算。
直到STK_VAL减到零,引发中断。
综上可述:如果只凭滴答定时器的中断,是无法进行1秒的延迟的,所以,我的程序里有一个外部空循环函数,而且选择每1ms进入一次滴答定时器中断的方式进行1000向下的自减运算。当1000减到零时,跳出空循环,回到主函数。
这就是整个tick滴答定时器进行精确延迟的原理。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
一周热门 更多>