首页 > 其他分享 >学习笔记STMF4 TIMER定时器(使用开发板立创天空星STMF4)

学习笔记STMF4 TIMER定时器(使用开发板立创天空星STMF4)

时间:2024-06-19 23:29:05浏览次数:13  
标签:定时器 USART TIMER 开发板 NVIC TIM InitStructure GPIO STMF4

目录

                                                #定时器的介绍

             #怎么去理解定时器的预分频系数

        

                                            #使用定时器实现完成触发中断

  #定时器触发中断基本函数配置

#在使用TIMER  触发中断的时候为什么不需要配置EXTI中断这个选项

                                    

                                                #使用定时器完成输出PWM

#PWM基本知识介绍

#函数配置生成PWM


        这个系列所有笔记用来记录,笔者学习过程中,产生的疑惑,个人的理解,同时掺杂着个人理解,希望对各位读者姥爷有帮助,参考文章连接在最后

                                                #定时器的介绍

        这是一张,数据手册里面的定时器框图,里面是定时器这个外设的整体运作模式,比较重要。

         TIMER   定时器  单片机开发的一种常用外设,定时器类型分为   高级定时器  通用定时器  基本定时器  这三种,这里需要注意的是,只有高级定时器,通用定时器,具有四个输出通道,这四个通道对应四个引脚,总的来说就是一个定时器,可以作用四个引脚,让这四个引脚,使用定时器的功能,具体功能注释如下。

                               输入捕获(input captuer)测量输入PWM 频率 间隔  波形

                               输出比较(input compare)用于输出PWM

                               PWM输出(pwm generation) 用于输出PWM,与上者相同

                               单脉冲模式(one-pluse mode output)

        同时这里要注意,基本定时器,没有能力使用以上四个功能,主要用于驱动DAC,可以参考下文数据手册,读者姥爷们,那有的读者姥爷就要问了,定时器不同的类型,到底有什么具体的不同,具体参考中文数据手册,手册连接放在最后

        高/普 定时器,上面这个多功能描述,最为常用的定时器,作用其实是,输出比较输出PWM,定时器触发中断,本篇主要简单介绍,定时器,以及使用STMF4完成举例。

             #定时器预分频系数,周期相关介绍

        

        这一部分其实对应着时基单元,PSC:预分频系数 ,对timer时钟(CK_PSC)进行分频结果为cnt  CNT:计时器时钟(这里注意不是,定时器时钟)ARR:自动重装载值,当CNT的值达到ARR的值就会触发中断,具体计算公式如下

                                                CK_CNT=CK_PSC/(PSC+1)

        这里解释一下为什么PSC要+1,PSC预分频系数 16位寄存器取值0~65535之间,在软件中赋值结构体变量 PSC 后面通常是跟-1的,所以在公式中,给+1了(个人看法)所以就+1,这些东西就是 TIM_TimeBaseInitTypeDef,这个结构体变量需要配置的东西,需要注意的是,ARR就是TIM_Period,也就是自动重装载值,当CNT计数到达,ARR,会重头开始计数。

                                            #使用定时器实现完成触发中断

  #定时器触发中断基本函数配置

        首先,我们来看一下,timer.c文件中的介绍配置流程 ,然后我们按照这个流程进行,函数配置,

void Timer_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//EBABLE TIMER3 Clock

TIM_TimeBaseInitTypeDef TimerBaseInitStructure;//配置  timer  struct 变量
TimerBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;	
TimerBaseInitStructure.TIM_CounterMode =TIM_CounterMode_Up;
TimerBaseInitStructure.TIM_Period  = 10000;
TimerBaseInitStructure.TIM_Prescaler  = 8400 - 1; 

TIM_TimeBaseInit(TIM3, &TimerBaseInitStructure);//初始化  timer

NVIC_InitTypeDef NVIC_InitStructure;//配置 inturputer control 管理器
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;

NVIC_Init(&NVIC_InitStructure);
	
TIM_ITConfig(TIM3,TIM_IT_Update, ENABLE);//开启  timer3 中断	
TIM_Cmd(TIM3,ENABLE);
}
void TIM3_IRQHandler(void)
{
        if(TIM_GetITStatus(TIM3, TIM_IT_Update) == SET)
        { // {}中为中断处理
                printf("IRQHandler!!!\r\n");
                
                // 反转LED灯
                if( flag == 0 )
                {
                        GPIO_SetBits(GPIOB, GPIO_Pin_2);
                        flag = 1;
                }
                else
                {
                        GPIO_ResetBits(GPIOB, GPIO_Pin_2);
                        flag = 0;
                }
        }
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}

        按照上述流程,这边配置好了,timer的初始化,然后配置,timer3 中断的响应函数,然后下面在配置,一下串口和板载LED

void uart1_init(uint32_t __Baud)
{
	GPIO_InitTypeDef GPIO_InitStructure;	

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);	

	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);//IO口用作串口引脚要配置复用模式
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);

	GPIO_StructInit(&GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin           = GPIO_Pin_9;//TX引脚
	GPIO_InitStructure.GPIO_Mode          = GPIO_Mode_AF;//IO口用作串口引脚要配置复用模式
	GPIO_InitStructure.GPIO_Speed         = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_OType         = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd          = GPIO_PuPd_UP;
	GPIO_Init(GPIOA,&GPIO_InitStructure);

	GPIO_StructInit(&GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin           = GPIO_Pin_10;//RX引脚
	GPIO_InitStructure.GPIO_Mode          = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed         = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_OType         = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd          = GPIO_PuPd_UP;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
  
	USART_InitTypeDef USART_InitStructure;//定义配置串口的结构体变量

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);//开启串口1的时钟

	USART_DeInit(USART1);//大概意思是解除此串口的其他配置

	USART_StructInit(&USART_InitStructure);
	USART_InitStructure.USART_BaudRate              = __Baud;//设置波特率
	USART_InitStructure.USART_WordLength            = USART_WordLength_8b;//字节长度为8bit
	USART_InitStructure.USART_StopBits              = USART_StopBits_1;//1个停止位
	USART_InitStructure.USART_Parity                = USART_Parity_No ;//没有校验位
	USART_InitStructure.USART_Mode                  = USART_Mode_Rx | USART_Mode_Tx;//将串口配置为收发模式
	USART_InitStructure.USART_HardwareFlowControl   = USART_HardwareFlowControl_None; //不提供流控 
	USART_Init(USART1,&USART_InitStructure);//将相关参数初始化给串口1
	
	USART_ClearFlag(USART1,USART_FLAG_RXNE);//初始配置时清除接受置位

	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//初始配置接受中断

	USART_Cmd(USART1,ENABLE);//开启串口1
	
	NVIC_InitTypeDef NVIC_InitStructure;//中断控制结构体变量定义

	NVIC_InitStructure.NVIC_IRQChannel                    = USART1_IRQn;//中断通道指定为USART1
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority  = 0;//主优先级为0
	NVIC_InitStructure.NVIC_IRQChannelSubPriority         = 1;//次优先级为1
	NVIC_InitStructure.NVIC_IRQChannelCmd                 = ENABLE;//确定使能
	NVIC_Init(&NVIC_InitStructure);//初始化配置此中断通道
		
}

void LED_GPIO_Init(void)
{

	//板载LED引脚初始化配置
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

	GPIO_InitTypeDef  GPIO_InitStructure;

	GPIO_InitStructure.GPIO_Pin 	= GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType 	= GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_PuPd 	= GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	GPIO_ResetBits(GPIOB,GPIO_Pin_2);
}

        这里基本配置完成之后,然后扔到main()里面去调用,然后实验现象是,串口每秒打印IRQHandler,同时板载LED每秒进行闪烁。

#include "board.h"
#include "bsp_uart.h"
#include <stdio.h>
#include  "button.h"
#include  "exti.h"
#include "timer.h"
extern uint8_t  flag;//
void TIM3_IRQHandler(void);//声明末尾定义的函数

int main(void)
{
	
	LED_GPIO_Init();
	board_init();
	uart1_init(9600);
	flag = 0;
	Timer_Init();
	
	while(1)
	{
		
	}
	

}
#在使用TIMER  触发中断的时候为什么不需要配置EXTI中断这个选项

       EXTI(External interrupt/event controller)外部中断/事件控制器,片上外设之一,能够检测外部输入信号边沿产生变化时(上升  下降  ),并由此产生中断,通常用于GPIO这种不能自己产生中断源 的片上外设,而timer定时器  这个片上外设本身可以产生 中断源,自然也就使用不到   exti 在此产生中断源进行配置  timer  产生中断源  nvic 在进行配置  在编写  中断响应函数  然后就能使用  ,所以timer定时器  配置使用不到  exti 这个片上外设  功能   使用 exti 的配置流程如下  本文实验中断流程如

 GPIO (电平发声变化)-> EXTI(产生中断源) ->NVIC(配置中断优先级)  ->IRQ(定义函数)

        TIMER(产生中断源) ->NVIC(配置中断优先级)  ->IRQ(编写中断响应函数)

       总结:TIMER 片上外设本身可以产生中断源  不需要在使用 EXTI 这个片上外设  在此产生中断源  所以不需要使用  EXTI 这个片上外设去产生中断源   EXTI这个片上外设 一般用于检测 GPIO

引脚出现电平 变化的时候  触发产生中断源  进行触发中断使用  

                                    

                                                #使用定时器完成输出PWM

#PWM基本知识介绍

         冲量相等而形状不同的窄脉冲加在具有惯性的环节上时,其效果基本相同。

        这句话描述的是物理学中的动量守恒原理,同时也是PWM能够生成指定电压的原理,特别是在信号处理或控制系统分析中的应用。当两个形状不同的窄脉冲(可以理解为短暂且强度大的力或者能量输入)对一个具有惯性的系统施加作用时,如果它们的总冲量(即在时间上的力与持续时间的乘积,等于物体动量的变化量)相等,那么最终系统的行为——比如位移、速度或加速度变化——将基本相似,尽管输入的脉冲形状不同。

        这反映了无论输入信号如何变化,只要总的动量转移是相同的,系统的响应将是类似的,因为系统的动态响应主要取决于冲量,而不是脉冲的具体形状。这也是工程设计中经常考虑的一种简化模型,PWM就像是BUCK电路,通过开关来控制电压稳定在指定的范围,而PWM是控制占空比,就是高电平的在整个周期内的占比,来控制整体输出电压,控制在指定范围输出,PWM(Pulse Width Modulation脉宽调制)

                                        频率:PWM的频率是整个周期的倒数。

                                        占空比:占空比是指一个周期内高电平所占的比例。

        单片机 高电平是 3.3V  低电平是   0V  那么问题来了,如果需要输出1.65V,那么就需要使用PWM这个模式输出电平,简单原理阐述,PWM输出不同电压电平,是利用高电平在一段时间周期里面的占比,这一段时间周期通常     ms为单位,从而显示出不同的电平,

                                                        50%   对应  3.3*0.5 =1.65V  

                                                        60%   对应 3.3*0.6 = 1.98V

        具体不同占空比,对应多少V电压就是这么换算的,

#函数配置生成PWM

        timer,外设输出PWM,也就是定时器框图的这一部分,一个定时器的OC(输出比较),有四个引脚可以使用,进行输出PWM,也就是 TIM_CH1 TIM_CH2 TIM_CH3 TIM_CH4 ,

void PWM_GPIO_Init(void)
{

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
	
	GPIO_Init(GPIOB,&GPIO_InitStruct);
	
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource5,GPIO_AF_TIM3);
	//开启复用模式 GPIOB5不在作为 普通GPIO引脚使用  而是作为timer 输出PWM通道使用 
	
}
void Time_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;
TIM_TimeBaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStruct.TIM_Period = 1000;
TIM_TimeBaseStruct.TIM_Prescaler = 500 - 1; 

TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStruct); 

}
void Timer_OCInit(void)
{
TIM_OCInitTypeDef TIM_OCInitStruct;
TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStruct.TIM_OutputState = ENABLE;
TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;

TIM_OC2Init(TIM2,&TIM_OCInitStruct);//输出通道2 Init
	
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  
//enable  CC2R 也就是 TIM_SetCompare2(timx,cc2r)	就是开启这个函数
	
TIM_Cmd(TIM3, ENABLE);  //使能TIM3
	}
void pwm_breathing_lamp(void)
{
        uint32_t brightness = 0;// 当前亮度
        int step = 10;          // 亮度改变的步长
        
        // 逐渐增加亮度
        for(brightness = 0; brightness < 1000; brightness += step)
        {
                TIM_SetCompare2(TIM3, brightness); // 使用TIM3的Channel 2
                delay_ms(10);
        }
        
        // 逐渐减少亮度
        for(brightness = 1000; brightness > 10; brightness -= step)
        {
                TIM_SetCompare2(TIM3, brightness); // 使用TIM3的Channel 2
                delay_ms(10);
        }
}   
int main(void)
{
	board_init();
	uart1_init(9600);
	PWM_GPIO_Init();
	Time_Init();
	Timer_OCInit();
	while(1)
	{
		pwm_breathing_lamp();
	}
}

        【立创·天空星STM32F407VET6】入门手册 - 飞书云文档 (feishu.cn)

        链接:https://pan.baidu.com/s/12SM_KSvwXXyTqAvosVA-gQ 
        提取码:zhiy

        最后希望对你有所帮助!!!个人理解,如有失误,欢迎指出,核实立改

标签:定时器,USART,TIMER,开发板,NVIC,TIM,InitStructure,GPIO,STMF4
From: https://blog.csdn.net/weixin_62292999/article/details/139496849

相关文章

  • IT66352: 2 IN to 1 OUT HDMI2.0 18Gb/s Re Timer Switch
    TheIT66352isaHDMI2.02INto1OUTre-timerswitchwhichsupportsmaximumsignalingrateupto6Gbps/channel. IT66352是一款HDMI2.02INto1OUT重定时器开关,支持最高6Gbps/通道的信令速率。ItiscomplianttothelatestHDMI2.0bspecification4Kx2K@50/6......
  • 使用芯片为ZYNQ—7020,基于野火FPGA ZYNQ开发板
    使用芯片为ZYNQ—7020,基于野火FPGAZYNQ开发板肤色模型简介YCrCb也称为YUV,主要用于优化彩色视频信号的传输。与RGB视频信号传输相比,它最大的优点在于只需占用极少的频宽(RGB要求三个独立的视频信号同时传输)。其中“Y”表示明亮度(Luminance或Luma),也就是灰阶值;而“U”和“V”......
  • 51单片机有开发板A和开发板B,通过串口,实现开发板A的按键,控制开发板B的LED亮灭。
    1、功能描述有开发板A和开发板B,通过串口,实现开发板A的按键,控制开发板B的LED亮灭。2、实验原理1.串口通信(UART)串口通信是一种异步通信方式,它允许单片机通过两条线(发送线TX和接收线RX)进行数据传输。在51单片机中,串口通信是通过两个主要寄存器(SCON、SMO/SM1)和中断(RI、TI)......
  • QT210开发板学习(2): 通过DNW点亮LED灯
    查找开发板原理图,可知可用的LED有4个,引脚为EINT0/1/2/3,对应的IO口则是GPH0_0/1/2/3,寄存器有GPH0CON,GPH0DAT,GPH0PUD,GPH0DRVGPH0CON用来设置IO模式(地址为0xE0200C00),GPH0DAT是电平状态(地址为0xE0200C04)我们需要设置为Output模式,并且将状态设置为高电平新......
  • QT210开发板学习(1):SEC S5PC110 Test B/D驱动安装
    把开发板的开关拨到USBBOOT,通过USB线连接到开发板的OTG口,打开板上总电源,会提示驱动安装失败我们需要下载驱动(win7-64-DNW-USB)https://github.com/joyjohn131/QT210/tree/main/1打开dseo13b.exe,依次点击Next,Yes选择"EnableTestMode","Next",提示完成开启选择"SignaS......
  • 编写一个.sh的脚本,然后通过 shell 脚本执行 Makefile 文件并把生成的可执行文件下载到
    要编写一个shell脚本来执行Makefile并下载生成的可执行文件到开发板,你需要确保开发板可以通过某种方式(如SSH、FTP、SCP等)访问。以下是一个简单的shell脚本示例,它使用scp命令将可执行文件从本地机器复制到开发板。假设你的开发板可以通过SSH访问,并且你已经配置了SSH密钥认证,这样你......
  • TimerTask 定时任务
    定时任务就是在指定时间执行程序,或周期性执行计划任务。Java中实现定时任务的方法有很多,本文从从JDK自带的一些方法来实现定时任务的需求。一、Timer和TimerTaskTimer和TimerTask可以作为线程实现的常见方式,JDK1.5之后定时任务推荐使用ScheduledThreadPoolExecutor。1、快......
  • TimerWheel(计时轮)在Rust中的实现及源码解析
    计时器轮(TimerWheel),模拟时钟格式组成的高效计时器TimerWheel算法原理环形数据结构:TimerWheel,即时间轮,是一个环形的数据结构,类似于时钟的面,被等分为多个格子或槽位(slot)。槽位时间间隔:每个槽位代表一个固定的时间间隔,例如1毫秒、1秒等。这个时间间隔决定了定时器的精度。......
  • MFC案例:利用SetTimer函数编写一个“计时器”程序
    一、希望达成效果    利用基于对话框的MFC项目,做一个一方面能够显示当前时间;另一方面在点击开始按钮时进行读秒计时,计时结果动态显示,当点击结束时读秒结束并保持最后结果。二、编程步骤及相关代码、注释   1、启动VS->创建新项目->MFC应用-项目名称:MFCtimer->......
  • FRDM-MCXN947开发板之i2c应用
    介绍MCXN947NXPFRDM-MCXN947开发板是一款基于MCXN947MCU的低成本评估板,MCU集成了双核ArmCortex-M33微控制器和一个神经处理单元(NPU)。开发板由一个MCXN947控制器和一个64Mbit外部串行闪存组成。该板还具有P3T1755DPI3C温度传感器,TJA1057GTK/3ZCANPHY,以太网PHY,SDHC电路......