05:(寄存器开发)定时器一

news2024/11/24 12:41:08

定时器

  • 1、系统定时器SysTick
    • 1.1、SysTick中断的使用
    • 1.2、使用SysTick制作延迟函数
  • 2、基本定时器
    • 2.1、基本定时器中断的使用
    • 2.2、使用基本定时器制作延时函数

1、系统定时器SysTick

1.1、SysTick中断的使用

①SysTcik系统滴答定时器和片上外设定时器不同,它在CPU内核中,如同NVIC和RCC一样,在使用它的时候,不需要在开启时钟,他们都内嵌在AHB系统时钟总线里面,因为一上电都已经开启了。
SysTick是一个24位的向下计数器,而计数器的频率为AHB或者AHB/8。当重装载数值寄存器的值递减到0的时候(COUNTFLAG标志位由0变为1),系统定时器就产生一次中断(开启中断的情况下),以此循环往复。
由于SysTick定时器在CPU内核里面,所以产生的中断源来源于CPU内部,我们在配置NVIC的时候不在需要配置中断源使能函数

由于SysTick在CPU内部,所以使用手册里面没有介绍有关于它的寄存器,有关于它的介绍的手册在如下链接: link

如下图为:SysTick的控制和状态寄存器
在这里插入图片描述如下图为:SysTick的重装载值寄存器
在这里插入图片描述在这里插入图片描述

如下为使用SysTick定时器中断实现LED每隔1s亮灭一次
①SysTick_Timer.c文件代码如下:

#include "stm32f10x.h"        
#include "LED.h"

/*
 * @Function:SysTick定时器的初始化
 */
void SysTick_Timer_Init(void)
{
    /* 1、配置时钟源:1 = AHB(72MHz),0 = AHB/8(9MHz) */
    SysTick->CTRL |= SysTick_CTRL_CLKSOURCE;//选用的72MHz
    
    /* 2、使能中断请求 */
    SysTick->CTRL |= SysTick_CTRL_TICKINT;
        
    /* 3、设置重装值,需要定时1s则重装值为72000000 > 2^24-1
       所以先定时1ms,则定时器1ms重装值为72000
    */
    SysTick->LOAD = 72000 - 1;
    
    /* 4、配置优先级 */
    NVIC_SetPriorityGrouping(4);
    NVIC_SetPriority(SysTick_IRQn,0);
    
    /* 5、使能计数器*/
    SysTick->CTRL |= SysTick_CTRL_ENABLE;
}

/*
 * @Function:中断服务函数:LED间隔1s闪烁
 */
void SysTick_Handler(void)
{
	SysTick->CTRL &= ~SysTick_CTRL_COUNTFLAG;//清除标志位
    static uint16_t count = 0;
    count++;
    if(count == 1000)
    {
        count = 0;
        LED_Turn(LED0);
    }
}

②LED.c文件的代码如下:

#include "stm32f10x.h"                  // Device header
#include "LED.h"

/*
 * PA0~PA7引脚的初始化
 */
void LED_Init(uint32_t PA_x)
{
	/* 1. 打开GPIOA的时钟 */
	RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
	
	/* 2. 将PA0~PA7配置为通用输出开漏模式  */
	if(PA_x != PA_ALL)
	{
		GPIOA->CRL |= PA_x; 
		GPIOA->CRL &= ~(PA_x << 2);
	}else{
		GPIOA->CRL |= PA_ALL;
		GPIOA->CRL &= PA_ALL;
	}
	
}

/*
 * 点亮LEDx
 */
void LED_ON(uint16_t LEDx)
{
	GPIOA->ODR |= LEDx;
}


/*
 * 熄灭LEDx
 */
void LED_OFF(uint16_t LEDx)
{
	GPIOA->ODR &= ~LEDx;
}


/*
 * 翻转LEDx
 */
void LED_Turn(uint16_t LEDx)
{
	/* 如果是关闭那么就打开,如果是打开那么就关闭 */
	if((GPIOA->ODR & LEDx) == 0)//关闭
	{
		LED_ON(LEDx);
	}else{
		LED_OFF(LEDx);
	}
}

主函数文件的代码如下:

#include "stm32f10x.h"                
#include "OLED.h"
#include "SysTick_Timer.h"
#include "LED.h"

int main(void)
{
	OLED_Init();
    LED_Init(PA_0);
    SysTick_Timer_Init();
    
    LED_OFF(LED0);
    OLED_ShowString(1,1,"nihao");
    
	while(1)
	{
        
	}
}

实物演示效果如下:

SysTick_Interrupt

1.2、使用SysTick制作延迟函数

在这里插入图片描述

通过获取计时器里面的值来制作延迟函数,函数的形式参数为我们手动写入的计数器的重装值,当计时器里面的数值还没有减到0时,让其一直等待循环,当计时器里面的数值减到0时,让其跳出循环,任何关闭定时器。

①Delay.c文件的代码如下:

#include "Delay.h" 

/*
 * @Function:延迟函数us
 */
void Delay_us(uint16_t us)
{
    /* 1、设置时钟源 */
    SysTick->CTRL |= SysTick_CTRL_CLKSOURCE;//选用AHB(72MHz)
    
    /* 2、不需要中断 */
    SysTick->CTRL &= ~SysTick_CTRL_TICKINT;
    
    /* 3、给寄存器VAL写入数据,让标志位COUNTFLAG清零 */
    SysTick->VAL = 0;
    
    /* 4、设置重装值 */
    SysTick->LOAD = 72 * us;//1us来一个脉冲计数

    /* 5、使能定时器 */
    SysTick->CTRL |= SysTick_CTRL_ENABLE;
    
    /* 6、等待计数器到0,标准位变为1,跳出循环 */
    while(!((SysTick->CTRL) & SysTick_CTRL_COUNTFLAG));
    
    /* 6、关闭定时器 */
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE;
}

/*
 * @Function:延迟函数ms
 */
void Delay_ms(uint16_t ms)
{
	while (ms--)
	{
		Delay_us(1000);
	}
}

/*
 * @Function:延迟函数s
 */
void Delay_s(uint16_t s)
{
	while (s--)
	{
		Delay_ms(1000);
	}
}

②主函数文件代码如下:

/*
 * LED灯每隔1s闪烁一下,并且OLED上面的数值加1,加到10后重头开始加
 */
#include "stm32f10x.h"                
#include "OLED.h"
#include "LED.h"
#include "Delay.h"

int main(void)
{
    uint16_t Data = 0;
    LED_Init(PA_0);
	OLED_Init();
    OLED_ShowString(1,1,"Data:");
    LED_OFF(LED0);
	while(1)
	{
        LED_Turn(LED0);
        OLED_ShowNum(1,6,Data,2);
        Data++;
        if(Data == 11)
        {
            Data = 0;
        }
        Delay_ms(1000); 
	}
}

实物演示效果如下:

延迟函数

2、基本定时器

片上外设定时器:TIM6和TIM7是基本定时器。TM2~TIM5是通用定时器。TM1和TM8是高级定时器。而stm32f10c8t6只有定时器TIM1,TIM2,TIM3,TIM4。即1个高级定时器,3个通用定时器
基本定时器TIM6和TIM7各包含一个16位自动装载计数器,由各自的可编程预分频器驱动。
这2个定时器是互相独立的,不共享任何资源。这个2个基本定时器只能向上计数,由于没有外部IO,所以只能计时,不能对外部脉冲进行计数。
功能:定时中断,主模式,触发DAC。

在这里插入图片描述由上图所示:定时器TIM2~TIM7挂载中心ABP1上面,其中APB1的Fmax = 36MHz,所以APB1的分配系数 = 2。而由图中蓝色框中所得:给定时器TIM2 ~ TIM7提供时钟脉冲的频率F = 72MHz。下图为基本定时器中的结构图

在这里插入图片描述
由上图所示:传来的时钟脉冲通过PSC预分频器后在传递到计数器,PSC = 0,为1分频;PSC = 1,为2分频。其中PSC为16位的寄存器,所以最大分频系数 = 2^16 = 65536分频。
重装载值 = 99,则需要100个脉冲才能使99重装为),则相当于计数100次。自动重装载寄存器也是16位寄存器,所以最大的计数次数 = 2^16 = 65536次

在这里插入图片描述

预加载寄存器和影子寄存器:
  如上图PSC预分频寄存器和重装寄存器后面有阴影,则阴影部分就是影子寄存器。而时基单元的数据都是看影子寄存器里面的数据,
  那什么是预加载寄存器喃?预加载寄存器是为了在时基单元工作的时候,更新影子寄存器里面的数据,而更新的时机是这个周期计数完成,下个周期计数器值从0开始的时候。例如重装值为20,而在时基单元工作的时候,我们想将重装值更新为15,那么我们将15的数据写入重装载寄存器的预加载寄存器里面,然后预加载寄存器会在下一个计数周期的计数值为0的时候将15更新到影子寄存器里面。当然我们也可以选用不启用预加载寄存器,那么写入的数据会立马更新到影子寄存器里面。
【注意】写入数据都是写入到预加载寄存器里面,影子寄存器是不允许写入数据的
在这里插入图片描述

2.1、基本定时器中断的使用

由于stm32f10c8t6没有基本定时器,所以下面的代码不是使用stm32f103c8t6的支持包,而是使用stm32f103zet6的支持包编辑的。
在这里插入图片描述
下面是有关寄存器的介绍
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

①Basic_Timer文件的代码如下:

#include "stm32f10x.h"   
#include "LED.h"

/*
 * @Function:基本定时器TIM6的初始化
 */
void Basic_Timer_Init(void)
{
    /* 1、开启时钟 */
    RCC->APB1ENR |= RCC_APB1ENR_TIM6EN;
    
    /* 2、选择时钟来源 */
    //基本定时器只有一个时钟源,所以无需我们代码编写
    
    /* 3、设置分频系数 */
    TIM6->PSC = 7200 - 1;//分频系数为7200,则72MHZ/7200 = 10000Hz,1s/10000 = 0.1ms
                         //即每隔0.1ms,来一个脉冲,计数器+1
    
    /* 4、设定重装载值 */
    TIM6->ARR = 10000 - 1;//定时器1s
    
    /* 5、使能定时器中断请求 */
    TIM6->DIER |= 0x01;
    
    /* 6、开始预加载模式 */
    TIM6->CR1 |= TIM_CR1_ARPE;
    
    /* 7、配置NVIC */
    NVIC_SetPriorityGrouping(4);;
    NVIC_SetPriority(TIM6_IRQn,0);
    NVIC_EnableIRQ(TIM6_IRQn);
    
    /* 7、使能计数器 */
    TIM6->CR1 |= TIM_CR1_CEN;
}

/*
 * @Function:基本定时器TIM6中断的服务函数
 */
void TIM6_IRQHandler(void)
{
    if((TIM6->SR) & TIM_SR_UIF)//判断标志位
    {
        TIM6->SR &= ~TIM_SR_UIF;//清除标志位
        LED_Turn(LED0);//LED0的翻转
    }
}

②主函数文件代码如下:

#include "stm32f10x.h"                
#include "OLED.h"
#include "LED.h"
#include "Basic_Timer.h"


int main(void)
{
   
    LED_Init(PA_0);
    LED_OFF(LED0);
    Basic_Timer_Init();
   
    
	while(1)
	{
       
	}
}

综上:总结SysTick定时器和基本定时器的区别如下
①时钟来源不同:滴答定时器的时钟来源于系统总线AHB,基本定时器的时钟来源于APB1
②计数不同:滴答定时器是向下计数(24位),而基本定时器是向上计数(16位)
③所处位置不同:滴答定时器位于芯片内核,使用时不用开启时钟,中断时也不用开启NVIC_EnableIRQ()。基本定时器属于片上外设,使用时要开启时钟,使用中断时也要开启NVIC_EnableIRQ()
④内部结构不同:滴答定时器没有影子寄存器和预加载寄存器,也没有预分频寄存器。

2.2、使用基本定时器制作延时函数

①Delay.c文件的代码如下:

void Delay_us(uint16_t us)
{
    /* 1、开启时钟 */
    RCC->APB1ENR |= RCC_APB1ENR_TIM6EN;
    
    /* 2、选择时钟来源 */
    //基本定时器只有一个时钟源,所以无需我们代码编写
    
    /* 3、设置分频系数 */
    TIM6->PSC = 72 - 1;//分频系数为7200,则72MHZ/72 = 1MHz,1s/1MHz = 1us
                         //即每隔1us,来一个脉冲,计数器+1
    
    /* 4、设定重装载值 */
    TIM6->ARR = us - 1;
    
    /* 5、初始化一下计数器和预分频器 */
    TIM6->EGR |= TIM_EGR_UG;
    
    /* 6、初始化一下计数器和预分频器会使UIF置位,清除标志位 */
    TIM6->SR &= ~TIM_SR_UIF;
    
    /* 7、开启计数器 */
    TIM6->CR1 |= TIM_CR1_CEN;
    
    /* 8、等待循环完成 */
    while(!((TIM6->SR) & TIM_SR_UIF));
    
    /* 9、关闭计数器 */
    TIM6->CR1 &= ~TIM_CR1_CEN;
}

void Delay_ms(uint16_t ms)
{
	while (ms--)
	{
		Delay_us(1000);
	}
}

void Delay_s(uint16_t s)
{
	while (s--)
	{
		Delay_ms(1000);
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2193773.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【c语言——指针详解(3)】

文章目录 一、字符指针变量二、数组指针变量1、 数组指针变量是什么&#xff1f;2、 数组指针变量怎么初始化 三、⼆维数组传参的本质四、函数指针变量1、函数指针变量的创建2、函数指针变量的使⽤3、两段有趣的代码1&#xff09;typedef 关键字2&#xff09;typedef和define的…

<<迷雾>> 第8章 学生时代的走马灯(3)--走马灯 示例电路

几个首尾相连的触发器使用同一个控制端&#xff0c;能同时触发 info::操作说明 鼠标单击开关切换开合状态 注: 其中 CP 为按钮开关, 每点击一次, Q 的输出前进一级 注: 第一个触发器的输出端 Q 需要先置入高电平. 如果重置了电路, 可外接电源先使第一个 Q 置入高电平. 另: 因为…

开源跨平台三维模型轻量化软件osgGISPlugins-2、如何编译

上一篇&#xff1a;开源跨平台三维模型轻量化软件osgGISPlugins-1、简介 1、编译前的准备&#xff1a;安装、配置vcpkg包管理器 1&#xff09;安装及国内镜像替换教程(Windows和Linux环境都有):vcpkg国内镜像源替换 2&#xff09;下载第三方依赖库(Readme文档中所给出的百度网…

DBCCompare_TreeView中的同步查找功能实现方案

引言 在应用程序中&#xff0c;数据的可视化和交互性至关重要。TreeView 控件作为一种层级数据展示工具&#xff0c;能够有效地展示复杂的数据结构。本文将重点探讨如何在 TreeView 中实现同步查找功能&#xff0c;使得使用人员在操作一个树形结构时&#xff0c;能够自动更新另…

2-114 基于matlab的CA模型

基于matlab的CA模型&#xff0c;Singer模型对单机动目标进行跟踪算法&#xff0c;具有10页实验文档。采用蒙特卡罗方法对一个二坐标雷达对一平面上运动的目标进行观测&#xff0c;得到跟踪滤波结果。程序已调通&#xff0c;可直接运行。 下载源程序请点链接&#xff1a;2-114 …

计算机网络面试题——第三篇

1. TCP超时重传机制是为了解决什么问题 因为TCP是一种面向连接的协议&#xff0c;需要保证数据可靠传输。而在数据传输过程中&#xff0c;由于网络阻塞、链路错误等原因&#xff0c;数据包可能会丢失或者延迟到达目的地。因此&#xff0c;若未在指定时间内收到对方的确认应答&…

【大语言模型-论文精读】谷歌-BERT:用于语言理解的预训练深度双向Transformers

【大语言模型-论文精读】谷歌-BERT&#xff1a;用于语言理解的预训练深度双向Transformers Note&#xff1a; 持续更新中&#xff0c;未完。。。 目录 文章目录 【大语言模型-论文精读】谷歌-BERT&#xff1a;用于语言理解的预训练深度双向Transformers目录1. 引言2. 简介 1. …

Linux文件上传下载与压缩解压

首先用yum命令执行 yum install -y lrzsz 下载lrzaz1.文件上传命令: rz(拖曳方式有时行有时不行的)在终端直接输入rz,直接弹出Windows系统的文件,自行找文件进行上传操作2.下载: sz命令(拖曳方式有时行有时不行的) 用法:sz 下载文件或文件路径 默认下载路径在Windows系统相应的…

自然语言处理问答系统

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

C++(11)——vector的具体实现

目录 1.函数的头文件 2.默认成员函数 2.1构造函数 2.1.1无参的构造函数 2.1.2支持迭代器的构造函数 2.1.3支持n个val的构造函数 2.2拷贝构造函数 2.2.1写法一&#xff08;传统写法&#xff09; 2.2.2写法二&#xff08;现代写法&#xff09; 2.3赋值运算符重载函数 2…

PGMP01-概述

1.项目集管理绩效域 2.项目集管理标准的目的 the purpose of the standard for program management 定义&#xff1a;为项目集管理原则、时间和活动提供指导。这些原则、实践和活动被公认为在大多时候适用于大多数项目集&#xff0c;并为项目集管理的良好实践提供了支持。 管理…

tldr命令介绍

tldr命令介绍 安装 TLDR使用 TLDR更新命令仓库 TLDR 是 “Too Long; Didn’t Read” 的缩写&#xff0c;在 Linux中是一个非常有用的工具&#xff0c;旨在为用户提供简洁的命令行工具或程序的使用说明&#xff0c;TLDR的目标是解决传统手册页信息过于繁杂的问题&#xff0c;通过…

独享动态IP是什么?它有什么独特优势吗?

在网络世界中&#xff0c;IP地址扮演着连接互联网的关键角色。随着互联网的发展&#xff0c;不同类型的IP地址也应运而生&#xff0c;其中独享动态ip作为一种新型IP地址&#xff0c;备受关注。本文将围绕它的定义及其独特优势展开探讨&#xff0c;以帮助读者更好地理解和利用这…

使用keras-tuner微调神经网络超参数

目录 随机搜索RandomSearch HyperBand 贝叶斯优化BayesianOptimization 附录 本文将介绍keras-tuner提供了三种神经网络超参数调优方法。它们分别是随机搜索RandomSearch、HyperBand和贝叶斯优化BayesianOptimization。 首先需要安装keras-tuner依赖库,安装命令如…

State of ChatGPT ---- ChatGPT的技术综述

声明&#xff1a;该文总结自AI菩萨Andrej Karpathy在youtube发布的演讲视频。 原视频连接&#xff1a;State of GPT | BRK216HFS 基础知识&#xff1a; Transformer原文带读与代码实现https://blog.csdn.net/m0_62716099/article/details/141289541?spm1001.2014.3001.5501 H…

【GT240X】【06】Linux文本编辑软件vim

目录 一、说明 二、什么是 vim&#xff1f; 三、vi/vim 的使用 3.1 命令模式 3.2 输入模式 3.3 底线命令模式 四、vi/vim 按键说明 4.1 一般模式可用的光标移动、复制粘贴、搜索替换等 4.2 一般模式切换到编辑模式的可用的按钮说明 4.3 一般模式切换到指令行模式的…

案例-博客页面简单实现

文章目录 本文内容只涉及前端1. 内容要求2. 画面展示初始化面演示视频 3. 注意事项4. 代码区js文件夹下的jquery.min.js内容登录代码列表页面创作页面 本文内容只涉及前端 1. 内容要求 登录页面实现博客列表页面实现博客创作页面实现 链接: 开源在线 Markdown 编辑器文本框可…

布草洗涤厂自动统计单据管理打包标签———未来之窗行业应用跨平台架构

一、布草洗涤厂打包标签 二、大酒店楼层送货单 三、独立三联单销售单 四、职员司机统计报表 五、开通方法 扫码开通

大数据新视界 --大数据大厂之 从 Druid 和 Kafka 到 Polars:大数据处理工具的传承与创新

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

[SAP ABAP] 程序调用

示例数据 学生表(ZDBT_STU_437) 程序&#xff1a; Z437_TEST_20241006 代码如下所示 REPORT Z437_TEST_20241006.* 创建跟表或结构同名的工作区 TABLES: zdbt_stu_437.SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001.PARAMETERS: p_1 TYPE c LENGTH 4.SELECT-O…