IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32 定时器的简单应用 1ms中断代码 -> 正文阅读

[嵌入式]STM32 定时器的简单应用 1ms中断代码

引言:利用定时器TIM8产生1ms中断,每中断一次,全局变量+1,计数到10即10ms,使得输出引脚翻转一次。芯片采用STM32F103VCT6,系统输入时钟12MHz,完成代码并用示波器输出。

根据要求,本项目涉及系统时钟配置、中断源配置、GPIO输出配置、定时器配置四个部分。

1、准备工作

(1)系统时钟配置

? ? TIM8时钟为PLCK2,由APB2进行提供,时钟配置流程如下图(具体配置方法见STM32 RCC配置时钟 MCO输出实验_Artemis_yuer的博客-CSDN博客),本项目TIM8选择内部时钟CK_INT作为时钟源。

? ? ? ?配置步骤:

? ? ? ①12MHz外部时钟HSE输入;

? ? ? ②HSE分频器作为PLL输入,此处选择不分频;

? ? ? ③HSE时钟作为PLL输入时钟;

? ? ? ④PLL倍频系数,设置为6倍,产生72MHzPLLCLK时钟;

? ? ? ⑤选择PLLCLK作为系统时钟;

? ? ? ⑥设置AHB时钟,得到HCLK时钟;

? ? ? ⑦设置高速AHB时钟,通过APB2得到PLCK2时钟;

? ? ? ⑧PLCK2分频得到TIMx CLK;

? ? ? ⑨TIMx CLK作为TIM8内部时钟。

(2)中断源配置

? ? ? ? ?配置TIM8中断向量,这里直接用库函数进行配置。配置相应的主优先级和从优先级。

(3)GPIO输出配置

? ? ? ? ?TIM8位单片机的PC7引脚,因此需要使能GPIOC,即APB2 外设时钟使能寄存器(RCC_APB2ENR)第四位置1。

? ? ? ? PC7使用端口配置低寄存器(GPIOx_CRL)进行配置,设置为推挽输出模式,如图所示,寄存器复位值并不为0,首先要将寄存器第七位(即31:28)清零,然后赋值0011。

? ? ? ? ?本项目需要定时器每中断一次,全局变量+1,计数到10即10ms,使得输出引脚翻转一次,设置局部变量和中断输出函数,当进入十次中断后,局部变量+1,输出高电平,再进入十次中断后,局部变量再+1,输出低电平,以此来实现10ms的电平翻转。

? ? ? ?配置步骤:

? ? ? ?①IOPC使能;②PC7引脚清零;③PC7设置为推挽输出模式;④判断是否溢出中断;⑤清除中断标志位;⑥电平翻转输出。

(4)定时器配置

? ? ? ? 实验需设定定时器中断为1ms,输出方波为1kHz,定时中断周期计算公式:

? ? ? ? Tout =?((ARR+1)*(PSC+1))/Tclk ;

? ? ? ? 其中:Tclk:定时器的输入时钟频率(单位MHZ)

? ? ? ? Tout:定时器溢出时间(单位为us)

? ? ? ? PSC:定时器预分频值,将Tclk分频了PSC+1,定时器的最终频率就是Tclk/(PSC+1) MHz

? ? ? ? ARR:自动重装载寄存器,定时器计数的值被重装载一次被就是一个更新,若为向上计数,则从0开始重新计数。

? ? ? ? 这里为满足要求,设置PSC=72-1;即Tclk分频72次,得到1MHz定时器频率,为1us,项目需要中断为1ms,是1us的1000倍,则ARR值为1000-1,得到1ms中断值;f=1/T=1/1ms=1000Hz,也就是1kHZ的方波。而本项目需要产生20ms周期的方波,f=1/T=1/20ms=50Hz,则输出频率为50Hz的方波(若不需要20ms周期输出,则输出频率为1000Hz)。

? ? ? ?配置步骤:

? ? ?①TIM8时钟使能;

? ? ?②设置TIM8的PSC(预分频值)和ARR(自动重装溢出值);

? ? ?③输出使能(配置高级定时器的刹车和死区寄存器打开);

? ? ?④允许接收中断;

? ? ?⑤使能TIM8。

2、程序代码


(1)基于寄存器代码

#include "sys.h"
#include "main.h"
#include "stm32f10x.h"
#include "misc.h"

//时钟配置
void Stm32_Clock_Init()
{
        uint8_t temp=0;
	    RCC_DeInit();                   /* 时钟复位 */
	    RCC->CR|=1<<16;                 /* 使能HSE时钟 */
	    while(!(RCC->CR|=1>>17))        /* 判断HSE就绪 */
	    {
		}
		RCC->CFGR=0x00000400;           /* APB1=DIV2;APB2=DIV1;AHB=DIV1 */
		RCC->CFGR|=1<<16;               /* 配置HSE时钟作为PLL时钟输入 */
		FLASH->ACR|=0x32;               /* FLASH延时两个周期 */
		RCC->CFGR|=0x00100000;          /* PLL 6倍频输出 */
	    RCC->CR|=1<<24;                 /* PLL使能 */
		while(!(RCC->CR|=1>>25))        /* 判断PLL时钟就绪 */
		{
		}
		RCC->CFGR|=0x02;                /* 选择PLL为SYSCLK */
	
		
		while(temp!=0x02)               /* 判断SYSCLK是否设置成功 */
		{   
		temp=RCC->CFGR>>2;
		temp&=0x03;
		}    
		
}		 

//GPIO配置  PC7
void TIM8GPIOConfig()

{
      RCC->APB2ENR|=1<<4;             /* IOPC使能 */
	  GPIOC->CRL&=0X0FFFFFFF;         /* PC7引脚清零 */
	  GPIOC->CRL|=0X30000000;         /* PC7设置为推挽输出模式 */
    
}



//Timer配置  1kHz
void TIM8_Init()

{
   
      RCC->APB2ENR|=1<<13;           /* TIM8时钟使能 */
	  TIM8->ARR=999;                 /* 计数器自动重装值为1000,刚好1ms,1KHz */
	  TIM8->PSC=71;                  /* 预分频器72,得到1MHz的计数频率 */

	  TIM8->BDTR = 0x8000;           /* 输出使能 */
	  TIM8->CR1|=0x0080;             /* 寄存器装入缓冲器 */ 
	
	  TIM8->DIER|=1<<0;              /* 允许更新中断 */
	  TIM8->DIER|=1<<6;              /* 允许触发中断 */
      TIM8->CR1 |=0X01;              /* 使能定时器8 */
}



//TIM8中断优先级配置
void TIM8_IT_Init()	    
{    
      NVIC_InitTypeDef  NVIC_InitStructure;    
	  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);              
	  NVIC_InitStructure.NVIC_IRQChannel = TIM8_UP_IRQn;  
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
      NVIC_Init(&NVIC_InitStructure);  
    
}	




//中断输出配置
uint16_t cnt=0;

void TIM8_UP_IRQHandler(void)
{
   static uint16_t flag=0;
   if(TIM8->SR&0x0001)                     /* 判断是否溢出中断 */
		{
		   TIM8->SR&=~(1<<0);              /* 清除中断标志位 */
		   cnt++;                          /* 每进一次中断,CNT+1 */
	       if(cnt>=10)                     /* 如果CNT=10,输出*/
		    {	
					cnt=0;
					flag++;                    /* 每十个中断flag+1*/
					if(flag%2==0)              /* 若为奇数*/
					{
						GPIOC->ODR|=1<<7;      /* 输出高电平*/
					}
					else
					{  
                        GPIOC->ODR&=0<<7;      /* 否则输出低电平*/
                    }
		
		    }
	
	     }

}



	
	
int main()
{
  	  Stm32_Clock_Init();
	  TIM8GPIOConfig();
	  TIM8_Init();
	  TIM8_IT_Init();	 
	
	 
	  while(1)
		{
			
			
		}
}

(2)基于库函数代码

#include "sys.h"
#include "main.h"
#include "stm32f10x.h"
#include "misc.h"


uint16_t cnt=0;
void RCC_Init()                                      /* 系统时钟配置 */
{    
	    ErrorStatus HSEStartUpStatus;                    /* 枚举型变量 */
		RCC_DeInit();                                    /* 重置RCC  */
		RCC_HSEConfig(RCC_HSE_ON);                       /* HSE使能 */
		HSEStartUpStatus=RCC_WaitForHSEStartUp();        /* 等待HSE起振 */
		if(HSEStartUpStatus==SUCCESS)                    /* 判断HSE起振成功 */
		{
				
		    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);        
            FLASH_SetLatency(FLASH_Latency_2);           /* 2个延时周期*/
		    RCC_HCLKConfig(RCC_SYSCLK_Div1);               
		    RCC_PCLK1Config(RCC_HCLK_Div2);              /* 设置低速APB1时钟PLCK1*/
			RCC_PCLK2Config(RCC_HCLK_Div1);              /* 设置高速APB2时钟PLCK2*/
			RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_6);       /* 6倍频 */
		}	
		else
	   {
			    /*do nothing*/
       }
			
			
		RCC_PLLCmd(ENABLE);                                   /* PLL使能 */
		while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY)==RESET)     /* 检查使能标志位 */
		{
		}
		RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);            /* PLLCLK作为SYSCLK */
		while (RCC_GetSYSCLKSource()!=0x08)     
        /* 判断SYSCLK是否设置成功  0x08PLL作为系统时钟 */
		{
		}
}


void TIM8_GPIO_Config(void)                                            /* GPIO配置 */
{		
    GPIO_InitTypeDef GPIO_InitStruct;                                  /* 结构体定义 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);              /* GPIOC使能 */
    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_7;                               /* PC7引脚 */
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;                        /* 推挽输出 */
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;                       /* 50MHz*/
    GPIO_Init(GPIOC,&GPIO_InitStruct);                                 /*初始化GPIOC */
	}


	
	

void TIM8_Init()
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure; 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);           /* TIM8时钟使能 */
	TIM_DeInit(TIM8);
	TIM_InternalClockConfig(TIM8);
    TIM_TimeBaseStructure.TIM_Period = 71;            /* 预分频器72,得到1MHz的计数频率 */
    TIM_TimeBaseStructure.TIM_Prescaler =999;         /* 计数器自动重装值为1000 */
    TIM_TimeBaseStructure.TIM_ClockDivision = 0; 
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;     /* 向上计数 */ 
    TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure); 
    TIM_ITConfig(TIM8,TIM_IT_Update,ENABLE);
	TIM_Cmd(TIM8, ENABLE); 
	 
}
  


void TIM8_IT_Init()
{
	NVIC_InitTypeDef  NVIC_InitStructure;    
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
	
	NVIC_InitStructure.NVIC_IRQChannel = TIM8_UP_IRQn;  
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
    NVIC_Init(&NVIC_InitStructure);  
          
	  
}

void TIM8_UP_IRQHandler(void)
{
	  static uint16_t flag=0;
	  if (TIM_GetITStatus(TIM8, TIM_IT_Update)!= RESET) 
      {
        TIM_ClearITPendingBit(TIM8, TIM_IT_Update);  
        cnt++;
		  
		 
		 if(cnt>=100)
		 {
              cnt=0;
			  flag++;
			  if(flag%2==0)
				{
			      GPIO_SetBits(GPIOC,GPIO_Pin_7);
				}
				else					  
                {			
	              GPIO_ResetBits(GPIOC,GPIO_Pin_7);
                }
          }
       }
}



int main()
{
      RCC_Init();
	  TIM8_GPIO_Config();
	  TIM8_Init();
	  TIM8_IT_Init();
	  
	  while(1)
		{
			
		}
}

3、信号输出

生成代码编译后烧写至芯片内,通过示波器显示如下图:

???? ? ? ? ? ?

? ? ? ?由示波器可以观察到输出周期为20ms,也就是说配置定时器中断为1ms,,示波器频率显示为50HZ,实验成功。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-12-14 16:07:28  更:2021-12-14 16:09:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 14:27:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码