新乡微信网站建设,助君网络怎么样,中山网站建设模板网络公司,aspx网站架设教程更多细节参考这篇
1. 什么是时钟以及作用
1.1 什么是时钟
时钟是由电路产生的周期性的脉冲信号#xff0c;相当于单片机的心脏
1.2 时钟对于STM32的作用
指令同步#xff1a;cpu和内核外设使用时钟信号来进行指令同步数据传输控制#xff1a; 时钟信号控制数据在内部总…更多细节参考这篇
1. 什么是时钟以及作用
1.1 什么是时钟
时钟是由电路产生的周期性的脉冲信号相当于单片机的心脏
1.2 时钟对于STM32的作用
指令同步cpu和内核外设使用时钟信号来进行指令同步数据传输控制 时钟信号控制数据在内部总线上的传输时机外设操作很多外设比如 GPIO USART ADC等需要时钟来控制频率和时序节能管理 调整时钟的频率可以管理MCU的功耗实现节能
2. 关于Sys_Tick 定时器
Sys_Tick 是 ARM Cortex-M4 内核的一部分 他提供24位递减计数器 可以用来生成周期性的中断适合用来左滴答定时器或者提供时间基准
2.1 Sys_Tick 定时器配置步骤
首先初始化SysTick 调用 SysTick_Config(SystemCoreClock/1000 ) ; //位与CMSIS 下的core_cm4.h 1760 行函数来配置SysTick定时器的重载值 该值基于系统时钟频率和中断频率所需的值来确定 我这里设置的是1ms中断一次STM32F4 的系统时钟是100MHZ 一个时钟周期有 1 / 100 000 000 s 也就是10 ns 实现1ms 需要 100 000 个 10ns ) 2. 选择时钟源 选择SysTick的时钟源 一般选择系统时钟 2. 中断使能
extern volatile uint32_t SysTickUptime ;
void SysTick_Handler(void)
{SysTickUptime ;
}2.2 使用 SysTick 实现毫秒级定时器以及延时
/* 毫秒级运行定时器 返回的是毫秒
SysTickUptime 溢出时间大概49天 */
uint32_t millis(void)
{return SysTickUptime ;
}/* 毫秒级延时函数 */
void delay_ms(uint32_t ms)
{uint32_t now_time millis();while(millis() - now_time ms) { } }2.3 使用 SysTick 实现微秒级定时器以及延时
使用 SysTick 实现微秒级定时器以及延时 为什么不直接SysTick_Config(SystemCoreClock/1000000 ) ;来实现呢
中断开销 如果SysTick定时设置成微妙产生一次中断 那么中断的频率会非常高可能导致花大量的时间处理中断从而影响程序的执行效率。对于一个100MHz的系统时钟这意味着每秒会有100万次中断这对于任何系统来说都是不切实际的。中断优先级 处理中断具有一定的优先级 过高的中断频率可能会导致低优先级任务或者中断得不到及时的处理24位计数器限制 SysTick 是一个24位递减计数器 这意味着最大的计数是2的24次方-1 如果系统时钟频率非常高比如180MHz或更高设置SysTick每微秒递减一次将导致它在很短的时间内溢出限制了可以生成的最长定时周期。
读取当前SysTick 来计算微妙
设置一个1us所需的滴答数
static uint32_t usTicks ;
// SystemCoreClock 100 MHZ
usTicks SystemCoreClock/1000000 ; //1us的滴答数 usTicks 100 捕捉一致的读数 循环读取SysTickUptime 和 SysTick- VAL 的值 直到他们在循环中两次读取之间保持一致。这是为了确保在读取的时候没有SysTick发生 以为如果读取 SysTick- VAL 之后 而在 SysTick- VAL 之前发生中断 SysTickUptime 会递增 而SysTick- VAL 会重置
uint32_t ms , cycle_cnt ;do{ms SysTickUptime ; cycle_cnt SysTick-VAL ; }while(ms ! SysTickUptime ) ;计算微妙 (ms * 1000 ) ( ( (SystemCoreClock/1000) - cycle_cnt ) / usTicks ) ;
1. 通过将ms毫秒计数* 1000 得到了系统启动以来的时间以微妙为单位
2. 计算 SystemCoreClock/1000 - cycle_cnt 得到自上次中断以来经过的时钟周期数 SystemCoreClock/1000 是SysTick 定时器的重装值 表示1ms内的时钟周期数 从这个值减去 SysTick- VAL 得到了自从上次中断以来经过的时钟周期数
3. 最后 将这个值除以 usTicks每 微秒的时钟周期数 将周期转换成微妙最后 函数的返回值也就是自系统启动以来的总微秒
/* 微秒级计数函数 */
uint32_t micros ( void )
{uint32_t ms , cycle_cnt ;do{ms SysTickUptime ; cycle_cnt SysTick-VAL ; }while(ms ! SysTickUptime ) ;return (ms * 1000 ) ( ( (SystemCoreClock/1000) - cycle_cnt ) / usTicks ) ;}/* 微秒级延时函数 */
void delay_us(uint32_t us)
{uint32_t now_time micros();while(micros() - now_time us) { }
}这里的关键是SysTick是递减计数的 并在到达零时重置和触发中断 cycle_cnt 变量存储的时从前的计数器值到下一个零点的周期数 这个值要用 SysTick定时器的重载值减去 才是已经过去的时钟周期数
3. 完整代码
3.1 Delay.h
#ifndef DELAY_H
#define DELAY_H
#include stm32f4xx.hvoid Delay_Init(void);uint32_t millis(void) ; //毫秒级运行定时器
uint32_t micros(void) ; //微秒级运行定时器 void delay_ms(uint32_t ms) ; //毫秒级延时函数
void delay_us(uint32_t us) ; //毫秒级延时函数 #endif3.1 Delay.c
#include stm32f4xx.h
#include Delay.h
#include stm32f4xx_it.hstatic uint32_t usTicks ;
volatile uint32_t SysTickUptime 0 ; //systick 每1ms 中断一次 void Delay_Init(void)
{ SysTick_Config(SystemCoreClock/1000 ) ; /* 这里的系统时钟是100mhz一个时钟周期有 1 / 100 000 000 s 也就是一个时钟周期有 10ns 我们需要计数到1ms也就是100 000个周期也就是100 000个10ns所以 SystemCoreClock/1000 1ms 开启systick中断一次*/usTicks SystemCoreClock/1000000 ; //1us的滴答数 usTicks 100
}/* 毫秒级运行定时器 返回的是毫秒
SysTickUptime 溢出时间大概49天 */
uint32_t millis(void)
{return SysTickUptime ;
}/* 毫秒级延时函数 */
void delay_ms(uint32_t ms)
{uint32_t now_time millis();while(millis() - now_time ms) { } }/* 微秒级计数函数 */
uint32_t micros ( void )
{uint32_t ms , cycle_cnt ;do{ms SysTickUptime ; cycle_cnt SysTick-VAL ; }while(ms ! SysTickUptime ) ;return (ms * 1000 ) ( ( (SystemCoreClock/1000) - cycle_cnt ) / usTicks ) ;}/* 微秒级延时函数 */
void delay_us(uint32_t us)
{uint32_t now_time micros();while(micros() - now_time us) { }
}/*举个简单的例子理解一下 假如 我们这里选择 100mhz 此时SysTickUptime 100 表示自系统启动以来已经过了100ms在某一时刻我们调用micros函数SysTick-VAL当前的值是50000表示自上次SysTick中断以来已经过了50000个周期那么此时是多少毫秒呢
也就是计算 SysTickUptime * 1000 1000000 - SysTick-VAL / usTicks
1000000 - SysTick-VAL / usTicks 表示走过的50000个周期 有少个usTicks 1个usTicks 也就是1us*/3.3 void SysTick_Handler(void)
位于