小白跟做江科大32单片机之定时器

原理部分

1.

计数器每遇到一个上升沿就会计数值+1,。

72MHZ=72000000

72000000/65536/65536=0.01676380634307861328125=59.652323555555554  (s) 

2.

3.

计数时钟每来一个上升沿,计数值+1,自动运行。如果计数值与存储在自动重装载寄存器中的值相等,计数器清0,产生更新中断和更新事件,然后更新到NVIC,向上的那个表示中断,向下的表示更新事件。

这个主模式触发DAC的功能,就是直接通过更新事件直接映射到别的设备。

4.通用定时器

滤波信号之后会给触发控制器或者TRGI

外部时钟模式1输入:ETR,其他定时器,CH1引脚,CH1边沿引脚,CH2

5.主要看这个

6.

这个主要是由预分配缓冲器使得本次计数周期结束时,改变分频值不会受影响

7.RCC时钟树左边是系统时钟,右边是时钟频率

时钟树左边

时钟树右边

时钟树右边部分电路

这就是我们在程序中写RCC APB2/1Periphclockgmd作用的地方,打开时钟,就是在这个位置写1/让左边的时钟能够通过与门输出给外设


代码编写

实验一

1.根据江科大老师给的电路图进行连接

2.创建新项目

3.将显示屏相关代码复制到新项目中

3.思路

①写一个TIMER_init函数,其中包括

开启RCC时钟,

内部时钟模式,

配置时基单元

定时器中断控制

NVIC

配置运行控制

②在main函数中写一个定时器中断函数代码

4.编写TIMER.c代码

#include "stm32f10x.h"                  // Device header

void TIMER_Init()
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);    //开启GPIOB的时钟,通用定时器
    
    /*配置时钟源*/
    TIM_InternalClockConfig(TIM2);        //选择TIM2为内部时钟,若不调用此函数,TIM默认也为内部时钟
    /*时基单元初始化*/
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;                //定义结构体变量
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;        //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;    //计数器模式,选择向上计数
    TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;                //计数周期,即ARR的值
    TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;                //预分频器,即PSC的值
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;            //重复计数器,高级定时器才会用到
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);                //将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元    
    
    /*中断输出配置*/
    TIM_ClearFlag(TIM2, TIM_FLAG_Update);                        //清除定时器更新标志位
                                                                //TIM_TimeBaseInit函数末尾,手动产生了更新事件
                                                                //若不清除此标志位,则开启中断后,会立刻进入一次中断
                                                                //如果不介意此问题,则不清除此标志位也可
    
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);                    //开启TIM2的更新中断
    
    /*NVIC中断分组*/
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                //配置NVIC为分组2
                                                                //即抢占优先级范围:0~3,响应优先级范围:0~3
                                                                //此分组配置在整个工程中仅需调用一次
                                                                //若有多个中断,可以把此代码放在main函数内,while循环之前
                                                                //若调用多次配置分组的代码,则后执行的配置会覆盖先执行的配置
    
    /*NVIC配置*/
    NVIC_InitTypeDef NVIC_InitStructure;                        //定义结构体变量
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;                //选择配置NVIC的TIM2线
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                //指定NVIC线路使能
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;    //指定NVIC线路的抢占优先级为2
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;            //指定NVIC线路的响应优先级为1
    NVIC_Init(&NVIC_InitStructure);                                //将结构体变量交给NVIC_Init,配置NVIC外设
    
    /*TIM使能*/
    TIM_Cmd(TIM2, ENABLE);            //使能TIM2,定时器开始运行
}

    
 

5.编写TIMER.h代码

#ifndef _TIMER__H
#define _TIMER__H

void TIMER_Init(void);


#endif

6.实验结果

实验二

1.接线

2.修改TIMER.c代码

#include "stm32f10x.h"                  // Device header

/**
  * 函    数:定时中断初始化
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数配置为外部时钟,定时器相当于计数器
  */
void Timer_Init(void)
{
    /*开启时钟*/
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);            //开启TIM2的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);            //开启GPIOA的时钟
    
    /*GPIO初始化*/
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);                        //将PA0引脚初始化为上拉输入
    
    /*外部时钟配置*/
    TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F);
                                                                //选择外部时钟模式2,时钟从TIM_ETR引脚输入
                                                                //注意TIM2的ETR引脚固定为PA0,无法随意更改
                                                                //最后一个滤波器参数加到最大0x0F,可滤除时钟信号抖动
    
    /*时基单元初始化*/
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;                //定义结构体变量
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;        //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;    //计数器模式,选择向上计数
    TIM_TimeBaseInitStructure.TIM_Period = 10 - 1;                    //计数周期,即ARR的值
    TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;                //预分频器,即PSC的值
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;            //重复计数器,高级定时器才会用到
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);                //将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元    
    
    /*中断输出配置*/
    TIM_ClearFlag(TIM2, TIM_FLAG_Update);                        //清除定时器更新标志位
                                                                //TIM_TimeBaseInit函数末尾,手动产生了更新事件
                                                                //若不清除此标志位,则开启中断后,会立刻进入一次中断
                                                                //如果不介意此问题,则不清除此标志位也可
                                                                
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);                    //开启TIM2的更新中断
    
    /*NVIC中断分组*/
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);                //配置NVIC为分组2
                                                                //即抢占优先级范围:0~3,响应优先级范围:0~3
                                                                //此分组配置在整个工程中仅需调用一次
                                                                //若有多个中断,可以把此代码放在main函数内,while循环之前
                                                                //若调用多次配置分组的代码,则后执行的配置会覆盖先执行的配置
    
    /*NVIC配置*/
    NVIC_InitTypeDef NVIC_InitStructure;                        //定义结构体变量
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;                //选择配置NVIC的TIM2线
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                //指定NVIC线路使能
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;    //指定NVIC线路的抢占优先级为2
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;            //指定NVIC线路的响应优先级为1
    NVIC_Init(&NVIC_InitStructure);                                //将结构体变量交给NVIC_Init,配置NVIC外设
    
    /*TIM使能*/
    TIM_Cmd(TIM2, ENABLE);            //使能TIM2,定时器开始运行
}

/**
  * 函    数:返回定时器CNT的值
  * 参    数:无
  * 返 回 值:定时器CNT的值,范围:0~65535
  */
uint16_t Timer_GetCounter(void)
{
    return TIM_GetCounter(TIM2);    //返回定时器TIM2的CNT
}

3.修改TIMER.h代码

#ifndef __TIMER_H
#define __TIMER_H

void Timer_Init(void);
uint16_t Timer_GetCounter(void);

#endif
 

4.修改main.c代码

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"

uint16_t Num;            //定义在定时器中断里自增的变量

int main(void)
{
    /*模块初始化*/
    OLED_Init();        //OLED初始化
    Timer_Init();        //定时中断初始化
    
    /*显示静态字符串*/
    OLED_ShowString(1, 1, "Num:");            //1行1列显示字符串Num:
    OLED_ShowString(2, 1, "CNT:");            //2行1列显示字符串CNT:
    
    while (1)
    {
        OLED_ShowNum(1, 5, Num, 5);            //不断刷新显示Num变量
        OLED_ShowNum(2, 5, Timer_GetCounter(), 5);        //不断刷新显示CNT的值
    }
}

/**
  * 函    数:TIM2中断函数
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  *           函数名为预留的指定名称,可以从启动文件复制
  *           请确保函数名正确,不能有任何差异,否则中断函数将不能进入
  */
void TIM2_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)        //判断是否是TIM2的更新事件触发的中断
    {
        Num ++;                                                //Num变量自增,用于测试定时中断
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);            //清除TIM2更新事件的中断标志位
                                                            //中断标志位必须清除
                                                            //否则中断将连续不断地触发,导致主程序卡死
    }
}
5.实验结果

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

养猫发现猫毛过敏?宠物空气净化器真的能拯救猫毛过敏吗?

广东省 猫咪是许多人梦寐以求的伴侣,但对于轻度猫毛过敏和鼻炎患者来说,养猫似乎是个遥不可及的梦想。我常在社交媒体上羡慕地观看朋友们的吸猫日常,却因过敏无法亲自养猫。这种遗憾驱使我寻找解决方案,从研究低过敏猫种到尝试空气…

通过语言大模型来学习LLM和LMM(四)

一、大模型学习 新的东西,学习的东西就是多,而且最简单最基础的都需要学习,仿佛一点基础知识都要细嚼慢咽,刨根问底,再加上一顿云里雾里的吹嘘,迷迷糊糊的感觉高大上。其实就是那么一回事。再过一段时日&a…

注解 - @ResponseStatus

注解简介 在今天的每日一注解中,我们将探讨ResponseStatus注解。ResponseStatus是Spring框架中的一个注解,用于为控制器方法指定HTTP响应状态码和理由短语。 注解定义 ResponseStatus注解用于标记控制器方法或异常类,以指示HTTP响应的状态码…

R语言数据分析案例28-对数据集可视化和T检验

一、分析主题: 本分析旨在对数据集进行可视化和 T 检验,以探索数据集中的变量之间的关系和差异。通过可视化数据,我们可以直观地了解数据的分布和趋势,而 T 检验则可以帮助我们确定这些差异是否具有统计学意义。 二、具体分析 …

pyrouge(ROUGE-1.5.5)的安装步骤和使用说明(适用于Linux 系统)

摘要:本文讲解了如何配置和使用文本摘要的评价指标ROUGE(linux 系统)。 ✅ NLP 研 1 选手的学习笔记 简介:小王,NPU,2023级,计算机技术 研究方向:摘要生成、大语言模型生成 文章目录 一、为啥要写这篇博客&…

uniapp 开发版小程序之间跳转

uni.navigateToMiniProgram({appId: urL,path: patH,envVersion: release,//我使用develop会给我返回:开发版小程序已过期,请在开发者工具重新扫码确定success(res) {console.log(res);// 打开成功uni.showToast({title: 跳转成功})},fail(err) {console…

【CS.AL】算法核心之贪心算法:从入门到进阶

文章目录 1. 概述2. 适用场景3. 设计步骤4. 优缺点5. 典型应用6. 题目和代码示例6.1 简单题目:找零问题6.2 中等题目:区间调度问题6.3 困难题目:分数背包问题 7. 题目和思路表格8. 总结References 1000.1.CS.AL.1.4-核心-GreedyAlgorithm-Cre…

Linux Source命令及脚本的执行方式解析

Linux Source命令及脚本的执行方式解析 当修改了/etc/profile文件,想让它立刻生效,而不用重新登录,这时就想到用source命令,如:source /etc/profile source命令: 也称为“点命令”,也就是一个点符号&…

显著提高iOS应用中Web页面的加载速度 - 提前下载页面的关键资源(如JavaScript、CSS和图像)

手动下载并缓存资源是一种有效的方式,可以确保在需要时资源已经在本地存储,这样可以显著提高加载速度。 缓存整个 web 页面的所有资源文件 具体实现步骤 下载和缓存资源:包括 HTML 文件、CSS、JavaScript 和图像。在应用启动时预加载资源。…

鸿蒙 游戏来了 鸿蒙版 五子棋来了 我不允许你不会

团队介绍 作者:徐庆 团队:坚果派 公众号:“大前端之旅” 润开鸿生态技术专家,华为HDE,CSDN博客专家,CSDN超级个体,CSDN特邀嘉宾,InfoQ签约作者,OpenHarmony布道师,电子发烧友专家博客,51CTO博客专家,擅长HarmonyOS/OpenHarmony应用开发、熟悉服务卡片开发。欢迎合…

【复旦邱锡鹏教授《神经网络与深度学习公开课》笔记】梯度的反向传播算法

矩阵微积分(Matrix Calculus) 在开始之前,需要先了解矩阵微积分的一些计算规则。 首先,对于矩阵微积分的表示,通常由两种符号约定: 分母布局 标量关于向量的导数为列向量 向量关于标量的导数为行向量 N维…

如何应对pcdn的流量攻击?

面对PCDN的流量攻击,可以采取以下措施来应对: 一.配置防火墙: 1.禁止未授权的PCDN域名访问:根据网络需求,配置防火墙规则,只允许特定的PCDN域名进行访问,从而防止未经授权的PCDN节…

shell编程基础(第16篇:命令是什么?有哪些注意事项)

前言 前面我们已经使用过各种各样的命令,那么命令到底是什么呢?我们又该怎么理解该术语? 什么是命令? 命令是command的中文翻译,能在命令行中执行的是命令。因为早期的计算机只有文字界面,命令是程序&#…

【Kafka】Kafka生产者-04

【Kafka】Kafka生产者-04 1. 生产者发送消息流程1.1 发送原理 2. 相关文档 1. 生产者发送消息流程 1.1 发送原理 在消息发送的过程中,涉及到了两个线程——main 线程和 Sender 线程。 在 main 线程中创建了一个双端队列 RecordAccumulator。 main 线程将消息发送给…

CSS实现经典打字小游戏《生死时速》

🌻 前言 CSS 中有这样一个模块:Motion Path 运动模块,它可以使元素按照自定义的路径进行移动。本文将为你讲解这个模块属性的使用,并且利用它实现我小时候电脑课经常玩的一个打字游戏:金山打字的《生死时速》。 &…

【免费Web系列】大家好 ,今天是Web课程的第二一天点赞收藏关注,持续更新作品 !

这是Web第一天的课程大家可以传送过去学习 http://t.csdnimg.cn/K547r 员工管理 1. 条件分页查询 1.1 概述 在页面原型中,我们可以看到在查询员工信息列表时,既需要根据条件动态查询,还需要对查询的结果进行分页处理。 那要完成这个页面…

计算机组成原理历年考研真题对应知识点(计算机系统层次结构)

目录 1.2计算机系统层次结构 1.2.2计算机硬件 【命题追踪——冯诺依曼计算机的特点(2019)】 【命题追踪——MAR 和 MDR 位数的概念和计算(2010、2011)】 1.2.3计算机软件 【命题追踪——三种机器语言的特点(2015)】 【命题追踪——各种翻译程序的概念(2016)】 1.2.5计算…

四十五、openlayers官网示例Icon modification解析——在地图上添加标记图形并随意移动它的位置

官网demo地址: Icon modification 这篇讲了如何随意移动地图上的矢量点。 先在地图上添加一个矢量点,其中anchorXUnits 和 anchorYUnits: 指定锚点的单位。fraction 表示相对于图标的宽度(0到1之间),pixels 表示以像素…

关于Unity四种合批技术详解

文章目录 一.静态合批(StaticBatching)1.启用静态合批2.举例说明3.静态合批的限制4.静态合批的优点缺点5.动态指定物品合批 二.动态合批(Dynamic Batching)1.启用动态合批2.合批规则3.举例说明4.使用限制 三.GPU Instancing1.启用GPU Instancing2.启用限制3.举例说明 四.SRP Ba…