什么是网站收录,wordpress 中文api,wordpress 导航不可点击,做国内网站花费一、STM32的5种定时器简介
1.独立看门狗#xff08;IWDG#xff09; VS 窗口看门狗#xff08;WWDG#xff09;
1.独立看门狗#xff08;IWDG#xff09; 独立看门狗#xff1a;当没有到设定时间之前#xff0c;给它喂了狗#xff0c;就会回到初始值。 2.窗口看门狗…一、STM32的5种定时器简介
1.独立看门狗IWDG VS 窗口看门狗WWDG
1.独立看门狗IWDG 独立看门狗当没有到设定时间之前给它喂了狗就会回到初始值。 2.窗口看门狗WWDG 窗口看门狗只有在设定的窗口时间范围内喂才可以起效果 最适合哪些要求看门狗在精确计时窗口起作用。 2.Systick定时器
3.高级定时器TIM1TIM8 4.通用定时器TIMx 1输入捕获通过输入电平进行捕获 2产生中断 定时器时间到 触发事件 3正交编码器和霍尔传感器测小车速度 5.基本定时器TIM6 TIM7 1最多只能计数655352的16次方 2预分频器因为在定时器的频率不需要那么快 3可以产生中断 二、SYSTICK定时器
0.SYSTICK的提出 我们之前的51只有一个主线无操作系统一个进程走到死 我们想要多种进程并行工作但是实际上无法这样。因为后面的程序可能还没有等到执行时间就结束了。所以我们将每一个程序都分成多个小进程第一个进程的第一个小部分执行完成在执行第二个进程的第一小部分....【从而实现微观上的串行宏观上的并行】 1.SYSTICK定时器的作用 1专用于生产RTOS的系统滴答时钟【因为RTOS需要多进程执行】 2可用于裸机程序中短时间精确延时函数 3可用于普通定时器中断功能 2.SYSTICK定时器的数据手册
https://www.st.com/resource/en/programming_manual/cd00228163-stm32f10xxx-20xxx-21xxx-l1xxxx-cortex-m3-programming-manual-stmicroelectronics.pdf SYSTICK和NVIC不属于SoC部分【属于内核外设】 1.24个定时器 2.各种寄存器 1.STK_CTRL控制状态 2.STK_LOAD初始值 我们计算出来的值要-1 因为计时是4 3 2 1 0 4 3 2 1 0【0才表示结束】 3.STK_VAL计数值 4.STK_CALIB 校准 3.SYSTICK寄存器在标准库中的封装 SYSTICK放在misc.c中 1. SysTick_CLKSourceConfig--分频设置 本函数在misc.c中 SYSTICK本身没有分频器。所以需要通过本函数进行设置 /*** brief Configures the SysTick clock source.* param SysTick_CLKSource: specifies the SysTick clock source.* This parameter can be one of the following values:* arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source.* arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source.* retval None*/
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
{/* Check the parameters */assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));if (SysTick_CLKSource SysTick_CLKSource_HCLK){SysTick-CTRL | SysTick_CLKSource_HCLK;}else{SysTick-CTRL SysTick_CLKSource_HCLK_Div8;}
}
全局搜索SYSTICK 2.SysTick_Config--触发systick中断 本函数在core_cm3.h中 Systick config函数配置的状况是 默认使用AHB时钟。会产生中断中断优先级为最低并且最末尾启动了定时器 /*** brief Initialize and start the SysTick counter and its interrupt.** param ticks number of ticks between two interrupts* return 1 failed, 0 successful** Initialise the system tick timer and its interrupt and start the* system tick timer / counter in free running mode to generate * periodical interrupts.*//**Systick config函数配置的状况是默认使用AHB时钟。会产生中断中断优先级为最低并且最末尾启动了定时器
*/
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
//检验有没有超过24位寄存器
//SysTick_LOAD_RELOAD_Msk 0xFFFFFFulif (ticks SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
//减一因为我们是从0开始的 但是一般我们都不在乎因为影响不大 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_CLKSOURCE_Msk1默认使用AHB//SysTick_CTRL_TICKINT_Msk默认会产生中断//SysTick_CTRL_ENABLE_Msk启动了定时器SysTick-CTRL SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */return (0); /* Function successful */
3.注意点SysTick_Config VS SysTick_CLKSourceConfig的调用顺序 我们在调用库函数进行初始化的时候要先调用【SysTick_Config】然后再调用【SysTick_CLKSourceConfig】因为再【SysTick_Config】中对Systick_CTRL中是对其中几位bit进行直接赋值而不是位或。所以如果先定义【SysTick_CLKSourceConfig】则相关寄存器的值可能被覆盖掉。 4.SYSTICK定时器的2种工作方式
1.中断方式 使能后到中断处理程序查 2.查询方式 检测STK_VAL因为VAL会不断减少 5.SYSTICK定时器的定时计算
1.公式重装载值systick时钟频率(Hz)*想要定的时间s
2.例子1ms 我们使用原始的频率72MHZ72 000 000HZ 以1s为单位---》1ms0.001s CNT72 000 000*0.00172 000 查看是否超过2的24次方 3.查询方式和中断方式都这样计算
6.SYSTICK中断实现LED每200ms闪烁一次【中断方式-interrupt】
https://www.cnblogs.com/kinson/p/7967332.html
0.注意点 1SYSTICK是自动清除中断不需要手动将其清除 2SYSTICK是内核中的所以不需要打开SYSTICK时钟它一直都是打开的 1.接线 我们将led的j19接到PB0-PB7但是实际上我们就操作led1所以使用到PB0 2.NVIC_Configuration void NVIC_Configuration(void)
{// NVIC_InitTypeDef NVIC_InitStructure;#ifdef VECT_TAB_RAM /* Set the Vector Table base location at 0x20000000 */ NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); //分配中断向量表
#else /* VECT_TAB_FLASH *///表示从FLASH中启动/* Set the Vector Table base location at 0x08000000 */ NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif/* Configure one bit for preemption priority */// NVIC_PriorityGroup_12个抢占优先级8个次优先级/*NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //设置中断优先级// Enable the SYSTICK Interrupt //设置为SYSTICK//这里我们将下面代码注释起来是因为【NVIC_IRQChannel】只接受正整数//但是我们【SysTick_IRQn】是负数所以不能正确输出NVIC_InitStructure.NVIC_IRQChannel SysTick_IRQn; //中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 0; //强占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority 0;//次优先级NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; //通道中断使能NVIC_Init(NVIC_InitStructure);//初始化中断*/
}
3.GPIO_Configuration
//GPIO初始化
void GPIO_Configuration(void){GPIO_InitTypeDef GPIO_InitStructure;//PB0 ---LED1【LED的显示输出】GPIO_InitStructure.GPIO_Pin GPIO_Pin_8;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; //推挽输出GPIO_Init(GPIOB, GPIO_InitStructure);// 默认输出0让LED亮//RESET0//SET1GPIO_WriteBit(GPIOB, GPIO_Pin_8, Bit_RESET); }
4.RCC_Configuration
//RCC的配置
void RCC_Configuration(void){//因为起始代码中已经调用SystemInit将主时钟设置为72MHZ//所以我们这里RCC直接使能时钟就可以//使能GPIO端口//通过PB0控制LED1//因为我们使用到的是PB0所以只使用到GPIOBRCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//因为systick属于cpu部分的所以时钟始终打开的不需要再去打开//所以这里只是打开GPIO的时钟即可}
5. SYSTICK_Configuration
//SysTick_Config是SYSTICK的启动函数
void SYSTICK_Configuration(void){/*这个时间超时了//主频是72MHZ定时时间是500ms//ticks72 000 000*0.5 3600 000SysTick_Config(36000000);//1677 7216*///100毫秒//范围233ms//ticks72 000 000*200ms14400000SysTick_Config(14400000);//SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
}
6.main #include stm32f10x.h // Device header
/**使用SYSTICK控制led的闪烁【中断式】PB8控制LED8
*///函数声明
//RCC的配置
void RCC_Configuration(void);
//GPIO初始化
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void SYSTICK_Configuration(void);//全局变量定义
EXTI_InitTypeDef EXTI_InitStructure;
ErrorStatus HSEStatartUpStatus;int main(){//系统时钟配置RCC_Configuration();//NVIC配置NVIC_Configuration();//配置GPIOGPIO_Configuration();SYSTICK_Configuration();while(1);return 0;
}//RCC的配置
void RCC_Configuration(void){//因为起始代码中已经调用SystemInit将主时钟设置为72MHZ//所以我们这里RCC直接使能时钟就可以//使能GPIO端口//通过PB0控制LED1//因为我们使用到的是PB0所以只使用到GPIOBRCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//因为systick属于cpu部分的所以时钟始终打开的不需要再去打开//所以这里只是打开GPIO的时钟即可}//GPIO初始化
void GPIO_Configuration(void){GPIO_InitTypeDef GPIO_InitStructure;//PB0 ---LED1【LED的显示输出】GPIO_InitStructure.GPIO_Pin GPIO_Pin_8;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; //推挽输出GPIO_Init(GPIOB, GPIO_InitStructure);// 默认输出0让LED亮//RESET0//SET1GPIO_WriteBit(GPIOB, GPIO_Pin_8, Bit_RESET); }void NVIC_Configuration(void)
{// NVIC_InitTypeDef NVIC_InitStructure;#ifdef VECT_TAB_RAM /* Set the Vector Table base location at 0x20000000 */ NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); //分配中断向量表
#else /* VECT_TAB_FLASH *///表示从FLASH中启动/* Set the Vector Table base location at 0x08000000 */ NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif/* Configure one bit for preemption priority */// NVIC_PriorityGroup_12个抢占优先级8个次优先级/*NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //设置中断优先级// Enable the SYSTICK Interrupt //设置为SYSTICK//这里我们将下面代码注释起来是因为【NVIC_IRQChannel】只接受正整数//但是我们【SysTick_IRQn】是负数所以不能正确输出NVIC_InitStructure.NVIC_IRQChannel SysTick_IRQn; //中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 0; //强占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority 0;//次优先级NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; //通道中断使能NVIC_Init(NVIC_InitStructure);//初始化中断*/
}//SysTick_Config是SYSTICK的启动函数
void SYSTICK_Configuration(void){/*这个时间超时了//主频是72MHZ定时时间是500ms//ticks72 000 000*0.5 3600 000SysTick_Config(36000000);//1677 7216*///100毫秒//范围233ms//ticks72 000 000*200ms14400000SysTick_Config(14400000);//SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
}
7.注意点ticks的时间设置 我们已经知道systick有24个寄存器所以我们最大的数值范围不能超过2的24次方。 所以我们计算出来的值不能超过上面那个 而根据我们单片机上面使用的是72MHZ的频率 则我们ticks的范围是16 777 216/72 000 000 举个例子 如果我们想要设置100ms 则ticks72 000 000 *0.17,200,000 8.SYSTICK中断实现LED每200ms闪烁一次【查询方式--delay】
0.解释 我们通过使用delay进行精确的延时 1.代码解析 1.GPIO_Configuration
//GPIO初始化
void GPIO_Configuration(void){GPIO_InitTypeDef GPIO_InitStructure;//PB0 ---LED1【LED的显示输出】GPIO_InitStructure.GPIO_Pin GPIO_Pin_8;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; //推挽输出GPIO_Init(GPIOB, GPIO_InitStructure);// 默认输出0让LED亮//RESET0//SET1GPIO_WriteBit(GPIOB, GPIO_Pin_8, Bit_RESET); }
2.RCC_Configuration
//RCC的配置
void RCC_Configuration(void){//因为起始代码中已经调用SystemInit将主时钟设置为72MHZ//所以我们这里RCC直接使能时钟就可以//使能GPIO端口//通过PB0控制LED1//因为我们使用到的是PB0所以只使用到GPIOBRCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//因为systick属于cpu部分的所以时钟始终打开的不需要再去打开//所以这里只是打开GPIO的时钟即可} 3.delay_us 此代码要根据频率来进行修改 //用systick计数器来帮我们实现us级别的精确延时
//这个函数成立有2个条件
//1.主频必须是72MHZ
//2.us要小于2的24次方1864 135us1.8s
void delay_us(unsigned int us){//记录CTRL的countflag位的值unsigned int tmp0;//思路是先把systick的时钟源设置好然后给一个正确的ticks//然后使能systickwhile循环等待countflag置位则时间到//72MHZ主频我们使用8分频72/89MHZ systickSysTick-LOADus*9;SysTick-VAL0;//我们要先设置上面的LOAD和VAL在进行使能//时钟源是AHB/8禁止中断使能systickSysTick-CTRL 0x01;//检测什么时候时间结束//查看CTRL中的countflagdo{tmpSysTick-CTRL;}while(!(tmp(116)));//时间到关闭定时器SysTick-VAL0;SysTick-CTRL 0x00;
}
4.delay_ms
//不能大于 1864
void delay_ms(unsigned int ms){//记录CTRL的countflag位的值unsigned int tmp0;//思路是先把systick的时钟源设置好然后给一个正确的ticks//然后使能systickwhile循环等待countflag置位则时间到//72MHZ主频我们使用8分频72/89MHZ systickSysTick-LOADms*9000;SysTick-VAL0;//我们要先设置上面的LOAD和VAL在进行使能//时钟源是AHB/8禁止中断使能systickSysTick-CTRL 0x01;//检测什么时候时间结束//查看CTRL中的countflagdo{tmpSysTick-CTRL;}while(!(tmp(116)));//时间到关闭定时器SysTick-VAL0;SysTick-CTRL 0x00;}
5.main
#include stm32f10x.h // Device header
/**使用delay控制led的闪烁--与systick进行等价实现【查询式】PB8控制LED8
*///函数声明
//RCC的配置
void RCC_Configuration(void);
//GPIO初始化
void GPIO_Configuration(void);void delay_ms(unsigned int ms);
void delay_us(unsigned int us);//全局变量定义
EXTI_InitTypeDef EXTI_InitStructure;
ErrorStatus HSEStatartUpStatus;int main(){//系统时钟配置RCC_Configuration();//配置GPIOGPIO_Configuration();while(1){GPIO_WriteBit(GPIOB,GPIO_Pin_8,Bit_RESET);//亮delay_ms(200);GPIO_WriteBit(GPIOB,GPIO_Pin_8,Bit_SET);//灭delay_ms(200);}return 0;
}//RCC的配置
void RCC_Configuration(void){//因为起始代码中已经调用SystemInit将主时钟设置为72MHZ//所以我们这里RCC直接使能时钟就可以//使能GPIO端口//通过PB0控制LED1//因为我们使用到的是PB0所以只使用到GPIOBRCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//因为systick属于cpu部分的所以时钟始终打开的不需要再去打开//所以这里只是打开GPIO的时钟即可}//GPIO初始化
void GPIO_Configuration(void){GPIO_InitTypeDef GPIO_InitStructure;//PB0 ---LED1【LED的显示输出】GPIO_InitStructure.GPIO_Pin GPIO_Pin_8;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; //推挽输出GPIO_Init(GPIOB, GPIO_InitStructure);// 默认输出0让LED亮//RESET0//SET1GPIO_WriteBit(GPIOB, GPIO_Pin_8, Bit_RESET); }//用systick计数器来帮我们实现us级别的精确延时
//这个函数成立有2个条件
//1.主频必须是72MHZ
//2.us要小于2的24次方1864 135us1.8s
void delay_us(unsigned int us){//记录CTRL的countflag位的值unsigned int tmp0;//思路是先把systick的时钟源设置好然后给一个正确的ticks//然后使能systickwhile循环等待countflag置位则时间到//72MHZ主频我们使用8分频72/89MHZ systickSysTick-LOADus*9;SysTick-VAL0;//我们要先设置上面的LOAD和VAL在进行使能//时钟源是AHB/8禁止中断使能systickSysTick-CTRL 0x01;//检测什么时候时间结束//查看CTRL中的countflagdo{tmpSysTick-CTRL;}while(!(tmp(116)));//时间到关闭定时器SysTick-VAL0;SysTick-CTRL 0x00;
}//不能大于 1864
void delay_ms(unsigned int ms){//记录CTRL的countflag位的值unsigned int tmp0;//思路是先把systick的时钟源设置好然后给一个正确的ticks//然后使能systickwhile循环等待countflag置位则时间到//72MHZ主频我们使用8分频72/89MHZ systickSysTick-LOADms*9000;SysTick-VAL0;//我们要先设置上面的LOAD和VAL在进行使能//时钟源是AHB/8禁止中断使能systickSysTick-CTRL 0x01;//检测什么时候时间结束//查看CTRL中的countflagdo{tmpSysTick-CTRL;}while(!(tmp(116)));//时间到关闭定时器SysTick-VAL0;SysTick-CTRL 0x00;}
2.中断 VS 查询
查询和中断方式差异
查询方式是阻塞式的中断方式是非阻塞的