STM32沿途教程:【STM32】圭臬库与HAL库对照学习系列教程大全女同 a片
一、引子咱们在单片机顶用的延时基天职为三种, 轮回延时、SysTick滴答定时器延时、SysTick滴答定时器中断延时 ,轮回延时即是让CPU束缚while轮回,while轮回完后,在践诺底下的程序,while轮回的工夫,即是延时的工夫,这么的面目不仅占用CPU资源况兼不好终结延时工夫,因此不论是圭臬库也曾HAL库一般皆使用STM32芯片上的SysTick滴答定时器完成延时。
二、前期准备 STM32开拓板(我使用的是普中的STM32F103ZE的Z200系列)(非必要)STM32cubemx、Keil5(MDK)开拓板旨趣图(非必要) 三、SysTick定时器先容 1、SysTick定时器简介SysTick定时器也叫SysTick滴答定时器,它是Cortex-M3内核的一个外设,被镶嵌在NVIC中。它是一个24位向下递减的定时器,每计数一次所需工夫为1/SYSTICK,SYSTICK是系统定时器时钟,它不错平直取自系统时钟,还不错通过系统时钟8分频后得到。当定时器计数到0时,将从LOAD 寄存器中自动重装定时器初值,重新向下递减计数,如斯周而复始。若是开启SysTick中断的话,当定时器计数到0,将产生一个中断信号。因此惟有知谈计数的次数就不错准确得到它的延时工夫。
2、SysTick定时器寄存器先容 (1) CTRL寄存器CTRL是SysTick定时器的终结及景色寄存器。其相应位功能如下:
图片女同 a片
(2)LOAD寄存器LOAD是SysTick定时器的重装载数值寄存器。其相应位功能如下:
图片
(3)VAL寄存器VAL是SysTick定时器确现时数值寄存器。其相应位功能如下:
图片
(4)CALIB寄存器CALIB是SysTick定时器的校准数值寄存器。其相应位功能如下:
图片
汇总一下:
寄存器态状CTRLSysTick 终结和景色寄存器LOADSysTick 重装载值寄存器CALIBSysTick 校准值寄存器 3、SysTick定时器的时钟开端其在时钟树的位置:
图片
不错看到SysTick定时器的时钟开端由系统频率SYSCLK历程AHB分频,在历程8分频(可遴选)得到。
干系时钟树的造就不错看这篇著述:【STM32】STM32圭臬库与HAL库对照学习教程极端篇–系统时钟RCC详讲
5、SysTick定时器配置智商SysTick定时器的操作好像不错分为 4 步: (1)建树SysTick定时器的时钟源。 (2)建树SysTick定时器的重装出手值(若是要使用中断的话,就将中断使能掀开)。 (3)清零SysTick定时器现时计数器的值。 (4)掀开SysTick定时器。
四、圭臬库的延时 1、圭臬库的配置智商(1)复制上一讲的工程,并定名为4、SysTick定时器延时。
图片
(2)在工程中新建Public文献夹,标明是内部保存的是通用的程序。
图片
汤唯车震(3)在Public文献夹内确立Delay文献夹,用来保存SysTick定时器的程序。
图片
(4)掀开工程,新建两个文献并定名为:Delay.h和Delay.c,保存在刚确立的Delay文献夹内。 ①
图片
②图片
(5)添加文献到目次并添加文献旅途。 ①
图片
②图片
(6)使用SysTick定时器要添加misc.c文献。
图片
2、SysTick定时器配置程序Delay.h的程序:
#ifndef DELAY_H_ #define DELAY_H_ #include "stm32f10x.h" //1s=1000ms=1000000us void SysTick_Init(u8 SYSTICK); //SysTick时钟出手化函数 void Delay_us(u32 nus); //微秒级延时函数 void Delay_ms(u32 nus); //毫秒级延时函数 #endif
Delay.c的程序:
#include "Delay.h" static u16 fac_us; //计fac_us个数为1us - SysTick时钟频率 static u32 fac_ms; //计fac_ms个数为1ms /************************************************* *函数名: SysTick_Init *函数功能: SysTick定时器出手化 *输入: SYSTICK:我方配置的系统时钟,莫得配置时,默出嫁置是72M。 *复返值: 无 **************************************************/ void SysTick_Init(u8 SYSTICK) { SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //遴选8分频 fac_us = SYSTICK/8; //因为进行了8分频 fac_ms = (u16)fac_us*1000; } /************************************************* *函数名: Delay_us *函数功能: 微秒级延时函数 *输入: nus:延时的微秒数 庄重:nus的值,不要大于798915us(最大值即2^24/fac_us@fac_us=21) *复返值: 无 **************************************************/ void Delay_us(u32 nus) { u32 temp; //储存CTRL寄存器的值 SysTick->LOAD = nus*fac_us; //建树要数到值 SysTick->VAL = 0x00; //清空计数器的值 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //SysTick定时器使能 do { temp = SysTick->CTRL; }while((temp&0x01)&&!(temp&(1<<16))); //判断是否计数到达 SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk; //SysTick定时器失能 SysTick->VAL = 0x00; //清空计数器的值 } /************************************************* *函数名: Delay_ms *函数功能: 毫秒级延时函数 *输入: nus:延时nus毫秒 *复返值: 无 **************************************************/ void Delay_ms(u32 nus) { u32 temp; //储存CTRL寄存器的值 SysTick->LOAD = nus*fac_ms; //建树要数到值 SysTick->VAL = 0x00; //清空计数器的值 SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //SysTick定时器使能 do { temp = SysTick->CTRL; }while((temp&0x01)&&!(temp&(1<<16))); //判断是否计数到达 SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk; //SysTick定时器失能 SysTick->VAL = 0x00; //清空计数器的值 }3、主程序图片
#include "LED.h" #include "Delay.h" /************************************************* *函数名: main *函数功能: 主函数 *输入: 无 *复返值: 无 **************************************************/ int main() { SysTick_Init(72); LED_Init(); while(1) { GPIO_SetBits(LED0_GPIO_Port, LED0_Pin); GPIO_ResetBits(LED1_GPIO_Port, LED1_Pin); Delay_ms(1000); GPIO_SetBits(LED1_GPIO_Port, LED1_Pin); GPIO_ResetBits(LED0_GPIO_Port, LED0_Pin); Delay_ms(1000); } }4、软件仿真智商图片
(1)阐发我方开拓板的外部时钟晶振频率参数建树,我的是8MHz。
图片
(2)Debug选项建树。
图片
(3)点击Debug,掀开示波器,建树参数。 ①
图片
②图片
③图片
5、实验后果软件仿真后果: ①
图片
②图片
不错看到LED电平翻转的工夫断绝是1s,发挥延时工夫是1s。
硬件仿真后果(引脚上下电平合手续工夫):
图片
五、HAL库的延时 1、HAL库的配置智商(1)复制2.LED工程并定名为3.SysTick.
图片
(2)在工程中新建Public文献夹,标明是内部保存的是通用的程序。
图片
(3)在Public文献夹内确立Delay文献夹,用来保存SysTick定时器的程序。
图片
(4)掀开工程,新建两个文献并定名为:Delay.h和Delay.c,保存在刚确立的Delay文献夹内。 ①
图片
②
图片
(5)添加文献到目次并添加文献旅途。 ①
图片
②
图片
2、SysTick定时器配置程序Delay.h:
#ifndef DELAY_H_ #define DELAY_H_ #include "stm32f1xx_hal.h" void SysTick_Init(uint8_t SYSCLK); //SysTick定时器出手化函数 void Delay_us(uint32_t nus); //微秒级延时函数 void Delay_ms(uint16_t nms); //毫秒级延时函数 #endif
Delay.c:
#include "Delay.h" static uint32_t fac_us=0; //1us计数fac_us个数 /******************************************************************************* * 函 数 名: SysTick_Init * 函数功能: SysTick出手化函数 * 输 入: SYSCLK:系统时钟频率 * 输 出: 无 *******************************************************************************/ void SysTick_Init(uint8_t SYSCLK) { HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);//SysTick频率为HCLK fac_us=SYSCLK; //保存1us所需的计数次数 } /************************************************* *函数名: Delay_us *函数功能: 微秒级延时函数 *输入: nus:延时nus微秒 庄重:nus的取值为0~190887435(最大值即2^32/fac_us@fac_us=22.5) *复返值: 无 **************************************************/ void Delay_us(uint32_t nus) { uint32_t ticks; uint32_t told,tnow,tcnt=0; uint32_t reload=SysTick->LOAD; //LOAD的值 ticks=nus*fac_us; //需要的节律数 told=SysTick->VAL; //刚干预时的计数器值 while(1) { tnow=SysTick->VAL; if(tnow!=told) { if(tnow<told)tcnt+=told-tnow; //这里庄重一下SYSTICK是一个递减的计数器就不错了. else tcnt+=reload-tnow+told; told=tnow; if(tcnt>=ticks)break; //工夫逾越/等于要延长的工夫,则退出. } }; } /************************************************* *函数名: Delay_ms *函数功能: 毫秒级延时函数 *输入: nus:延时nus毫秒 *复返值: 无 **************************************************/ void Delay_ms(uint16_t nms) { uint32_t i; for(i=0;i<nms;i++) Delay_us(1000); }3、实验后果图片
与圭臬库的实验后果雷同,然而这里也曾放一下测试的图片。
图片
3、对于HAL_Delay()函数 (1)函数情况HAL_Delay()这个函数是HAL库自带的毫秒级延时函数,基本上在以后的工程中,莫得罕见情况,咱们皆不使用我方建的延时函数,基本上皆用HAL_Delay()这个函数,函数使用的是SysTick滴答定时器中断延时。
(2)函数程序__weak void HAL_Delay(uint32_t Delay) { uint32_t tickstart = HAL_GetTick(); uint32_t wait = Delay; /* Add a freq to guarantee minimum wait */ if (wait < HAL_MAX_DELAY) { wait += (uint32_t)(uwTickFreq); } while ((HAL_GetTick() - tickstart) < wait) { } }(3)程序发挥 函数是一个弱界说函数,不错重新被界说。函数通过HAL_GetTick()得到计数值,计数值1ms加1,直到加到你写入的值,跳出终末的while轮回,程序终结。uwTickFreq这个值是为1的,也即是说会多延时1ms,这么作念是为了防卫用户写入延时0ms这种无好奇瞻仰好奇瞻仰好奇瞻仰好奇瞻仰的延时。庄重:这个函数是有中断的,不要把这个函数放到我方的中断回调函数里,若是SysTick定时器中断的优先级小于你使用某个中断的优先级这么可能会导致程序卡在HAL_Delay()这个函数里。
备注:这个我嗅觉我方交融的还不是很澈底,但愿有大佬能出著述,深远商酌一下这个函数的已毕。
到这里著述就终结啦!
图片
本站仅提供存储工作,整个推行均由用户发布,如发现存害或侵权推行,请点击举报。