小白跟做江科大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.实验结果

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

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

相关文章

2024年心理学研究、现代化教育与社会发展国际学术会议(PRMESD 2024)

2024年心理学研究、现代化教育与社会发展国际学术会议(PRMESD 2024) 2024 International Conference on Psychological Research, Modern Education and Social Development 会议地点:南京,中国 网址:www.prmesd.com 邮箱: prmesdsub-con…

Python 学习 第二册 第10章 标准库的模块

-----用教授的方法学习 目录 10.1 模块 10.1.1模块就是程序 10.1.2 模块是用来下定义的 10.1.3 让模块可用 10.1.4 包 10.2 探索模块 10.2.1 模块包含什么 10.2.2 使用 help 获取帮助 10.2.3 使用源代码 10.3 标准库:一些深受欢迎的模块 10.3.1 sys 10…

【TensorFlow深度学习】使用TensorBoard可视化模型训练过程与性能指标

使用TensorBoard可视化模型训练过程与性能指标 使用TensorBoard可视化模型训练过程与性能指标:深度洞察模型学习之路安装与环境准备编写模型训练代码并集成TensorBoard日志启动TensorBoard解读TensorBoard可视化结果结语 使用TensorBoard可视化模型训练过程与性能指…

.net core使用EPPlus设置Excel的页眉和页脚

废话不表,直接上干货代码: using (ExcelPackage packagenew ExcelPackage()) {//创建一个表ExcelWorksheet workSheet package.Workbook.Worksheets.Add("表一");//设置页眉左边显示内容workSheet.HeaderFooter.OddHeader.LeftAlignedText&qu…

c# webapi 禁用单个方法(Action)与整个控制器(Controller)

在C#中,如果你想要禁用Web API Controller下的所有方法,你可以通过在Controller上应用特定的Attribute来实现。这里有两种常见的方法来禁用所有Controller的方法: 使用[NonAction]属性:这个属性可以被应用到单个的Action方法上&am…

杨氏矩阵和杨辉三角的空间复杂度较小的解题思路

文章目录 题目1 杨氏矩阵题目2 杨辉三角 题目1 杨氏矩阵 有一个数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,请编写程序在这样的矩阵中查找某个数字是否存在。 要求:时间复杂度小于O(N); 思路: 我们可以通过题目…

Java学习-MyBatis缓存

MyBatis缓存 MyBatis一级缓存 一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会去访问数据库一级缓存失效的四种情况 不同的SqlSession对应不同的一级缓存同一…

谷歌重塑Transformer:无限记忆力,无限长输入,登上Nature

Infini-attention机制为Transformer在具有挑战性的长语境任务中释放出了新的能力,对于调整现有模型以适应长输入也非常实用。 谷歌的最新研究成果Infini-attention机制(无限长注意力)将内存压缩引入了传统注意力机制,并在单个Tra…

Github 2024-06-15Rust开源项目日报Top10

根据Github Trendings的统计,今日(2024-06-15统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10TypeScript项目1JavaScript项目1Deno: 现代JavaScript和TypeScript运行时 创建周期:2118 天开发语言:Rust, JavaScript协议类型:M…

重装了mysql,然后安装为服务时,net start 启动一直报错,MySQL服务无法启动的解决

之前写过一篇关于安装mysql的文章,按上面的处理,基本上是可以的。 今天换了下目录,重新安装,一直报错。 然后我们来看一下问题: mysqld -console 这里的目录是有问题的,设置的是:datadird:\to…

个人关于Leecode 49题见解(保姆级)

题目: 49. 字母异位词分组 中等 相关标签 相关企业 给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 示例 1: 输入: strs ["eat", "…

对用户体验的一些思考

任何产品最终的形态,某种意义上来说,成功的标准无非就是以最小的成本,创造出最大的利润,盈利才是最终目的。这也就是说,我们做的产品应该顾及买家的感受,即顾客的感受,这被称为“用户体验”。 用…

React框架资源

React框架资源可以从多个方面获取,包括官方文档、教程、书籍、社区等。以下是一些React框架资源的清晰分点和归纳: 官方文档 新官方文档:React在2023年3月发布了全新的官方文档,位于https://react.dev/​。新文档包含教程、指南…

AI助力密码安全:利用机器学习提升密码安全性

信息安全已经成为了当今数字世界的一个核心问题,随着互联网技术使用场景的不断增加,创建和管理安全的密码已经成为了保证在线账户安全的关键要求。本文将研究和探讨如何利用人工智能(AI)和机器学习技术来提升密码的安全性。 学习目…

「前端+鸿蒙」鸿蒙应用开发-ArkTS语法说明-自定义组件

ArkTS 是鸿蒙(HarmonyOS)应用开发中的一个现代框架,它允许开发者以 TypeScript 的方式来创建和管理 UI 组件。以下是使用 ArkTS 创建自定义组件的基本语法说明和示例代码。 ArkTS 快速入门 - 语法说明 - 自定义组件 定义组件类 自定义组件通常是通过继承 Component 类来定…

GraphQL(9):Spring Boot集成Graphql简单实例

1 安装插件 我这边使用的是IDEA,需要先按照Graphql插件,步骤如下: (1)打开插件管理 在IDEA中,打开主菜单,选择 "File" -> "Settings" (或者使用快捷键 Ctrl Alt S …

运算符有哪些?优先级是怎么样的?转换数据类型的方法?(最少4种)

算术运算符: (加法)-(减法)*(乘法)/(除法)%(取模,返回除法的余数)(自增)--(自减) 赋…

【Qt】xml文件节点读取

1. xml文件 test.xml 文件内容 <?xml version"1.0" encoding"utf-8"?> <library><book1><id>00000001</id><name>1111</name></book1> </library>2. 代码 void DataXml::read() {//打开文件QF…

linux man使用

安装 man-db 提供了 man 命令&#xff0c;less 是 man 的默认分页器。 man-pages 提供了 Linux man 页面的内容。 对于中文可以使用&#xff1a; manpages-zh gnome 桌面下可以使用 gnome-help查询 使用 通过以下命令阅读man手册页&#xff1a; man手册页分为很多段落。…

简说安全分析

安全分析的目的 识别并解决安全漏洞&#xff1a;通过安全分析&#xff0c;可以识别系统、网络或应用程序中的安全漏洞&#xff0c;并提供相应的修复措施&#xff0c;以减少安全威胁。评估安全风险&#xff1a;安全分析帮助组织评估潜在的安全风险&#xff0c;并提供建议和措施…