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

定时器

  • 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.mzph.cn/news/881182.shtml

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

相关文章

第十一章 缓存之更新/穿透/雪崩/击穿

目录 一、什么是缓存 二、缓存更新策略 2.1. 缓存主动更新策略 2.1.1. Cache Aside模式&#xff08;主流&#xff09;‌ 2.1.2. Read/Write Through模式‌ 2.1‌.3. Write Behind模式‌ 2.1.4. 总结 三、缓存穿透 四、缓存雪崩 五、缓存击穿 5.1. 互斥锁实现 5.1.1…

C语言复习概要(四)

本文 1. 操作符的分类算术操作符关系操作符逻辑操作符 2. 二进制制和进制转换二进制与十六进制的表示进制转换算法 3. 原码、反码和补码原码反码补码 1. 操作符的分类 C语言中的操作符种类繁多&#xff0c;常用的主要操作符可以按照其功能进行如下分类&#xff1a; 算术操作符…

C++关于链表基础知识

单链表 // 结点的定义 template <class T> struct Node { T data ; Node <T> *next; //指向下一个node 的类型与本node相同 } // 最后一个node指针指向Null 生成结点&#xff1a; Node <T> * p new Node < T>; 为结点赋值: p-> data …

【微服务】服务注册与发现 - Eureka(day3)

CAP理论 P是分区容错性。简单来说&#xff0c;分区容错性表示分布式服务中一个节点挂掉了&#xff0c;并不影响其他节点对外提供服务。也就是一台服务器出错了&#xff0c;仍然可以对外进行响应&#xff0c;不会因为某一台服务器出错而导致所有的请求都无法响应。综上所述&…

LabVIEW机床加工监控系统

随着制造业的快速发展&#xff0c;机床加工的效率与稳定性成为企业核心竞争力的关键。传统的机床监控方式存在效率低、无法远程监控的问题。为了解决这些问题&#xff0c;开发了一种基于LabVIEW的机床加工监控系统&#xff0c;通过实时监控机床状态&#xff0c;改进生产流程&am…

PhotoMaker部署文档

一、介绍 PhotoMaker&#xff1a;一种高效的、个性化的文本转图像生成方法&#xff0c;能通过堆叠 ID 嵌入自定义逼真的人类照片。相当于把一张人的照片特征提取出来&#xff0c;然后可以生成你想要的不同风格照片&#xff0c;如写真等等。 主要特点&#xff1a; 在几秒钟内…

[C语言]指针和数组

目录 1.数组的地址 2.通过指针访问数组 3.数组和指针的不同点 4.指针数组 1.数组的地址 数组的地址是什么&#xff1f; 看下面一组代码 #include <stdio.h> int main() { int arr[5] {5,4,3,2,1}; printf("&arr[0] %p\n", &arr[0]); printf(&qu…

【c++】string类 (一)

简介 由于c的历史包袱&#xff0c;c要兼容c语言&#xff0c;c的字符串要兼容c语言&#xff0c;在 C 中&#xff0c;字符串通常使用两种主要的方式来表示&#xff1a; C风格字符串&#xff08;C-style strings&#xff09;&#xff1a; 依然是以 \0 结尾的字符数组。这种表示方…

设置服务器走本地代理

勾选&#xff1a; 然后&#xff1a; git clone https://github.com/rofl0r/proxychains-ng.git./configure --prefix/home/wangguisen/usr --sysconfdir/home/wangguisen/etcmakemake install# 在最后配置成本地代理地址 vim /home/wangguisen/etc/proxychains.confsocks4 17…

Web安全 - 文件上传漏洞(File Upload Vulnerability)

文章目录 OWASP 2023 TOP 10导图定义攻击场景1. 上传恶意脚本2. 目录遍历3. 覆盖现有文件4. 文件上传结合社会工程攻击 防御措施1. 文件类型验证2. 文件名限制3. 文件存储位置4. 文件权限设置5. 文件内容检测6. 访问控制7. 服务器配置 文件类型验证实现Hutool的FileTypeUtil使用…

计算机网络:计算机网络体系结构 —— OSI 模型 与 TCP/IP 模型

文章目录 计算机网络体系结构OSI 参考模型TCP/IP 参考模型分层的必要性物理层的主要问题数据链路层的主要问题网络层的主要问题运输层的主要问题应用层的主要问题 分层思想的处理方法发送请求路由器转发接受请求发送响应接收响应 计算机网络体系结构 计算机网络体系结构是指将…

简单部署vue+springboot项目

vue 参考博客 先将vue项目打包 npm run build 再创建项目文件夹front,在front中新建nginx.conf server {listen 80;server_name localhost;# 请求体的大小限制client_max_body_size 50m;# 日志文件存放地址access_log /var/log/nginx/host.access.log main;error…

openpnp - 图像传送方向要在高级校正之前设置好

文章目录 openpnp - 图像传送方向要在高级校正之前设置好笔记图像传送方向的确定END openpnp - 图像传送方向要在高级校正之前设置好 笔记 图像传送方向和JOG面板的移动控制和实际设备的顶部摄像头/底部摄像头要一致&#xff0c;这样才能和贴板子时的实际操作方向对应起来。 …

C++ | Leetcode C++题解之第456题132模式

题目&#xff1a; 题解&#xff1a; class Solution { public:bool find132pattern(vector<int>& nums) {int n nums.size();vector<int> candidate_i {nums[0]};vector<int> candidate_j {nums[0]};for (int k 1; k < n; k) {auto it_i upper_…

测试-BUG篇

文章目录 软件测试的生命周期BUGbug的概念描述bug的要素bug级别bug的生命周期 与开发产生争执怎么办&#xff08;高频考题&#xff09; 软件测试的生命周期 软件测试贯穿于软件的整个生命周期 BUG bug的概念 是指计算机程序中存在的一个错误(error)、缺陷(flaw)、疏忽(mista…

docker环境下配置cerbot获取免费ssl证书并自动续期

文章目录 实践场景了解certbot查看nginx的映射情况操作目标配置nginx配置的ssl证书设置自动续签 实践场景 本人使用docker部署了一个nginx容器&#xff0c;通过容器卷&#xff0c;实现本地html&#xff0c;ssl&#xff0c;conf和ngiinx容器映射的&#xff0c; 经常需要手动部署…

适合跑步的开放式耳机哪个品牌好?怎么选?可入的蓝牙耳机推荐

想必很多爱晨跑的朋友&#xff0c;一定都有过这般令人困扰的经历。耳机戴久了总觉得不舒适&#xff0c;或是尺寸不合&#xff0c;或是材质欠佳&#xff0c;反正无论怎样调整&#xff0c;都很难找到最舒适的佩戴方式。而且&#xff0c;有时候戴的时间久了&#xff0c;还很容易掉…

FLUX的ID保持项目也来了! 字节开源PuLID-FLUX-v0.9.0,开启一致性风格写真新纪元!

之前的文章已经和大家介绍过字节开源的ID保持项目PuLID。随着FLUX模型的发布&#xff0c;PuLID也开源了 FLUX 版本的模型&#xff0c;不得不说FLUX的强大&#xff0c;两个月生态就赶上了SDXL。这次新发布PuLID-FLUX-v0.9.0模型&#xff0c;它为FLUX.1-dev提供了无需调整的ID定制…

4S店4S店客户管理系统小程序(lw+演示+源码+运行)

社会的发展和科学技术的进步&#xff0c;互联网技术越来越受欢迎。手机也逐渐受到广大人民群众的喜爱&#xff0c;也逐渐进入了每个用户的使用。手机具有便利性&#xff0c;速度快&#xff0c;效率高&#xff0c;成本低等优点。 因此&#xff0c;构建符合自己要求的操作系统是非…

VirtulBOX Ubuntu22安装dpdk23.11

目录 依赖包安装 Python安装 numa安装 ​编辑Python pip3安装 ​编辑pyelftools安装 meson和ninja安装 ​编辑构建与编译 Meson构建DPDK ​编辑Ninja安装DPDK ​编辑VFIO-PCI驱动安装 大页内存和IOMMU配置 ​编辑VFIO-PCI加载 ​编辑VFIO-PCI驱动绑定 ​编辑dpdk…