资讯详情

STM32延时函数分析

Cortex-M3内核处理器有个systick 24位倒计时定时器,当计数到0时,重新装载初值. delay_init(u8 SYSCLK) //定时初始化函数分析 { Systick->CTRL&=0xfffffffb; //bit2清空,选择外部时钟 HCLK/8 fac_us=SYSCLK/8; fac_ms=(u16)fac_us*1000; } 摘自M32手册 6.2.6

系统时钟(S CLK)选择 系统复位后,HSI 被选为系统时钟。当时钟源被直接或通过PLL间接作为系统时钟时,它将不能被停止。 只有当目标时钟源准备就绪了(经过启动稳定阶段的延迟或PLL稳定),从一个时钟源到另一个时钟源的切换才会发生。在被选择时钟源没有就绪时,系统时钟的切换不会发生。直至目标时钟源就绪,才发生切换。 在时钟控制寄存器(RCC_CR)里的状态位指示哪个时钟已经准备好了,哪个时钟目前被用作系统时钟。 Systick时钟那里来? Systick时钟由系统时钟8分频后决定. 解析delay_us(u32 nus)函数 void delay_us(u32 nus) { u32 temp; Systick->LOAD=nus*fac_us; //装入定时值 Systick-> L=0x00; //清空 值 Systick-> L=0x01; //开启倒计时定时器 do { temp=Systick->CTRL; //定时器状态赋给变量 }while((temp&0x01)&&(temp&(1<<16))); //判断开启和是否计数到了0 (到达设定值) Systick->CTRL=0x00; //关闭定时 Systick->VAL=0x00; //清空计数值 } 定时1us分析: 由于Systick时钟设置为是系统时钟的8分频 ,假设SYSCLK=72M 则Systick=9MHZ 因为fac_us是基数无单位 fac_us=SYSCLK/8; 即72/8=9 则Systick->LOAD=nus*fac_us, 假设定时1us 则Systick->LOAD=9. 因为Systick是9M的速度倒计时 所以9个计数时间为9*(1/9M) 就是1us 必须保证nus<=(2^24)/fac_us 编程实例: I/O口输出500us方波 #include <stm32f10x_lib.h> #include "sys.h" #include "delay.h" #include "usart.h" #define LED0 PBout(0) #define LED1 PBout(1) void led_init(void) { RCC->APB2ENR|=1<<3; GPIOB->CRL&=0xffffff00; GPIOB->CRL|=0x00000033; //推挽输出 GPIOB->ODR|=0xffff; } int main(void) { Stm32_Clock_Init(9); delay_init(72); led_init(); while(1) { LED0=0; delay_us(500); LED0=1; delay_us(500); } } delay_ms(u16 nms)函数分析: void delay_ms(u16 nms) { u32 temp; SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit) SysTick->VAL =0x00; //清空计数器 SysTick->CTRL=0x01 ; //开始倒数 do { temp=SysTick->CTRL; } while(temp&0x01&&!(temp&(1<<16)));//等待时间到达 SysTick->CTRL=0x00; //关闭计数器 SysTick->VAL =0X00; //清空计数器 } 由于fac_ms基数为9000 所以假设nms=1则 倒计时时间9000/9M=0.001s=1ms就是延时1ms 所以最大定时时间 T=2^24/9000=1864ms 延时实例: while(1) { LED0=0; delay_ms(500); LED0=1; delay_ms(500); } 改变最大延时方法: 降低PLL倍频,计算得到系统新频率. int main(void) { Stm32_Clock_Init(4); delay_init(32); led_init(); while(1) { LED0=0; delay_ms(3000); LED0=1; delay_ms(3000); } } 此时最大延时 由于SYSCLK=32M 所以Systick=4M 既fac_ms=4000 Tmax=2^24/4000=4194ms 如果设置超过4194发生溢出,定时就不准了 例子: int main(void) { Stm32_Clock_Init(4); delay_init(32); led_init(); while(1) { LED0=0; delay_ms(4200); LED0=1; delay_ms(4200); } } 参考文献:<<例说STM32>> <<STM32手册>> -电子元器件采购网(www.ruidan.com)是本土元器件目录分销商,采用“小批量、现货、样品”销售模式,致力于满足客户多型号、高质量、快速交付的采购需求。 自建高效智能仓储,拥有自营库存超过50,000种,提供一站式正品现货采购、个性化解决方案、选型替代等多元化服务。
锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台