您现在的位置是:首页 > 正文

基于cubemx的stm32开发之路(使用正点原子战舰V3开发板)——基本定时器的应用

2024-01-30 20:40:15阅读 0

实验目的

学习利用CubeMX创建HAL库的工程
掌握定时器的基本原理

实验现象

使用stm32F1的TIM6定时器实现LED灯1hz的闪烁

实验设备

正点原子新战舰V3 STM32F103ZET6开发板学习板
st-link烧录器

定时器原理

F103定时器组成

STM32F103ZET6总共有8个定时器:

计数器类型 预分配系数 产生DMA 捕获/比较通道 互补输出 计数器分辨率
高级定时器 TIM1 向上/向下 1-65535 可以 4 16位(2^16)
TIM8 向上/向下 1-65535 可以 4 16位
通用定时器 TIM2 向上/向下 1-65535 可以 4 16位
TIM3 向上/向下 1-65535 可以 4 16位
TIM4 向上/向下 1-65535 可以 4 16位
TIM5 向上/向下 1-65535 可以 4 16位
基本定时器 TIM6 向上 1-65535 可以 0 16位
TIM7 向上 1-65535 可以 0 16位

总结:
TIM1和TIM8定时器特殊在有互补输出。高级定时器可以定时、输出比较、输入捕捉、还可以输出三相电机互补信号,每个高等定时器有8个外部IO口。
TIM6和TIM7基本定时器特殊在:基本定时器没有外部IO口,只能向上计数定时产生中断/DMA请求,没有捕获/比较通道
通用定时器(TIM2-TIM5)可以定时、输出比较、输入捕捉,每个通用定时器具有4个外部IO口。

定时器时间计算

基本定时器的计数次数由自动重装载寄存器决定的,基本定时器的计数器从0开始向上计数(计数模式为向上计数时),当计数器的值与自动重装载寄存器相等时,产生溢出。所以基本定时器的溢出时间计算公式如下:
T i m e = ( P S C + 1 ) ∗ ( A R R ) / T I M x C L K ( u s ) Time = (PSC+1)*(ARR)/ TIMxCLK(us) Time=PSC+1ARR/TIMxCLKus
PSC是定时器的分频系数,TIMxCLK是内部时钟。
  ARR是自动重装载寄存器的值(既计数多少产生一次溢出)。
  假设基本定时器TIMxCLK = 72MHZ,PSC = 72-1,ARR = 1000,那么定时器的溢出时间为:
T i m e = 72 ∗ 1000 / 72 = 1000 ( u s ) = 1 ( m s ) Time = 72*1000/72 = 1000(us) = 1(ms) Time=721000/72=1000us=1ms

具体步骤

1.RCC时钟源配置

RCC_allocation

2.时钟树配置

Clock_Configuration

3.GPIO配置,LED0对应PB5引脚

GPIO_Configuration

4.TIM6配置与中断使能

对应的时间为
T i m e = 7200 ∗ 5000 / 72 = 500 ( m s ) = 0.5 ( s ) ; 周 期 T = 1 s ; 频 率 f = 1 h z . Time = 7200*5000/72 = 500(ms)=0.5(s); 周期T=1s ; 频率f=1hz. Time=72005000/72=500ms=0.5(s)T=1sf=1hz.

NVIC_settings

5.项目配置

Project_Setings
code_setings

代码编写

1.CubeMX 生成的main.c
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();			//GPIO初始化,,函数definition在gpio.c
  MX_TIM6_Init();			//Tim6定时器初始化,函数definition在tim.c
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
2.CubeMX 生成的tim.c
#include "tim.h"

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

TIM_HandleTypeDef htim6;

/* TIM6 init function */
void MX_TIM6_Init(void)			//定时器初始化函数
{
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  htim6.Instance = TIM6;
  htim6.Init.Prescaler = 7200-1;				//定时器预分频系数
  htim6.Init.CounterMode = TIM_COUNTERMODE_UP;	//向上计数模式
  htim6.Init.Period = 5000-1;					//自动重装载值
  htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;		//自动重装功能使能
  if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }

}

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)  //中断设置
{

  if(tim_baseHandle->Instance==TIM6)
  {
  /* USER CODE BEGIN TIM6_MspInit 0 */

  /* USER CODE END TIM6_MspInit 0 */
    /* TIM6 clock enable */
    __HAL_RCC_TIM6_CLK_ENABLE();

    /* TIM6 interrupt Init */
    HAL_NVIC_SetPriority(TIM6_IRQn, 0, 0);		//中断NVIC优先级设置为0,0
    HAL_NVIC_EnableIRQ(TIM6_IRQn);				//使能定时器6的中断服务
  /* USER CODE BEGIN TIM6_MspInit 1 */

  /* USER CODE END TIM6_MspInit 1 */
  }
}

void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)	//中断挂起函数
{

  if(tim_baseHandle->Instance==TIM6)
  {
  /* USER CODE BEGIN TIM6_MspDeInit 0 */

  /* USER CODE END TIM6_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_TIM6_CLK_DISABLE();

    /* TIM6 interrupt Deinit */
    HAL_NVIC_DisableIRQ(TIM6_IRQn);
  /* USER CODE BEGIN TIM6_MspDeInit 1 */

  /* USER CODE END TIM6_MspDeInit 1 */
  }
}
3.查看stm32f1xx_it.c文件,找到中断服务函数
void TIM6_IRQHandler(void)
{
  /* USER CODE BEGIN TIM6_IRQn 0 */

  /* USER CODE END TIM6_IRQn 0 */
  HAL_TIM_IRQHandler(&htim6);
  /* USER CODE BEGIN TIM6_IRQn 1 */

  /* USER CODE END TIM6_IRQn 1 */
}

这个函数调用了下面这个函数

HAL_TIM_IRQHandler(&htim6) ;

4.找到中断回调服务函数

进入HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)函数,这里面的代码很长,其实就是不同的中断类型,进入不同的中断回调函数,都属于虚函数,所以我们只要在 main.c 或者 tim.c 文件中使能中断并重写中断服务函数即可

void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)
{
  /* Capture compare 1 event */
  if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1) != RESET)
  {
    if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC1) != RESET)
    {
      {
        __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1);
        htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;

        /* Input capture event */
        if ((htim->Instance->CCMR1 & TIM_CCMR1_CC1S) != 0x00U)
        {
       ..............................................
5.使能定时器中断并编写中断回调服务函数
使能定时器中断
  MX_GPIO_Init();
MX_TIM6_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_Base_Start_IT(&htim6);  //放在初始化之后
编写中断回调服务函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM6)
	{
		HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
	}
}

对应的源程序压缩包可以前往https://download.csdn.net/download/weixin_46074226/20533195 下载

网站文章

  • exit()与_exit()函数的区别

    进程就好比人一样有其生命,我们通过fork()函数来创建一个进程,那么我们又是如何来中止进程呢。1.Linux中的进程退出进程退出表示进程即将结束。在Linux中进程退出分为了正常退出和异常退出两种。(1)正常退出a. 在main()函数中执行return;b.调用exit()函数;c.调用_exit()函数。(2)异常退出a.调用about函数;b.进程收到某...

    2024-01-30 20:39:47
  • html icheck插件的使用

    html icheck插件的使用

    在前端用到的比较实用的插件 引入css文件 ,js文件 icheck $('input').iCheck({ checkboxClass: 'icheckbox_minimal...

    2024-01-30 20:39:42
  • python爬虫翻页_Scrapy爬虫案例01——翻页爬取

    python爬虫翻页_Scrapy爬虫案例01——翻页爬取

    之前用python写爬虫,都是自己用requests库请求,beautifulsoup(pyquery、lxml等)解析。没有用过高大上的框架。早就听说过Scrapy,一直想研究一下。下面记录一下我学...

    2024-01-30 20:39:36
  • 面试官:你知道Dubbo怎么做优雅上下线的吗?你:优雅上下线是啥?

    面试官:你知道Dubbo怎么做优雅上下线的吗?你:优雅上下线是啥?

    △Hollis, 一个对Coding有着独特追求的人△这是Hollis的第350篇原创分享作者 l Hollis来源 l Hollis(ID:hollischuang)最近无论是校招还...

    2024-01-30 20:39:28
  • jvm - 内存泄露和内存溢出的区别是什么

    这就是内存泄露,因为这些无用的对象无法被垃圾回收器回收,从而导致内存资源的浪费。需要注意的是,内存泄露和内存溢出是需要在特定场景下才会发生的问题,开发人员在编写代码时应该注意资源的释放和内存的合理使用...

    2024-01-30 20:38:58
  • 【JDK8 新特性 8】JDK 8新增的Optional类&新的日期和时间 API & 重复注解与类型注解

    【JDK8 新特性 8】JDK 8新增的Optional类&新的日期和时间 API & 重复注解与类型注解

    Optional是一个没有子类的工具类,Optional是一个可以为null的容器对象。它的作用主要就是为了解决避免Null检查,防止NullPointerException( 空指针异常)。

    2024-01-30 20:38:51
  • netbeans部署工程至外部tomcat

    netbeans部署工程至外部tomcat

    1.在启动端口中不使用8080修改为其他端口,因为这个端口已被其他服务器占用(如:glassfish等),否则部署不成功,并不显示具体错误. 这个问题困扰我很久,终于被发现 2.使用tomcat的zip版,也就是绿色版. 3.路径中不出现中文. 4.有可能要配置(catalina_home,catalina_base)...

    2024-01-30 20:38:34
  • vue项目使用crypto-js在IE中报错SCRIPT1006: 缺少 ‘)‘

    1.版本问题,crypto-js 4.0.0版本以上会出现问题 2.如果4.0.0的版本还是报错,那就把node_models中把crypto-js中的crypto-js.js文件复制出来直接引用,不...

    2024-01-30 20:38:06
  • L1正则能够得到稀疏解

    L1正则能够得到稀疏解

    在复习到过拟合的解决方法的时候L1正则化和L2正则化都可以用于降低过拟合的风险,但是L1正则化还会带来一个额外的好处:它比L2正则化更容易获得稀疏解,也就是说它求得的w权重向量具有更少的非零分量。主要...

    2024-01-30 20:38:00
  • appium 多开

    最近跑一个app 使用的是appium,单开太慢了~,就想多开,结果遇到一个问题,最后解决了,这里记录一下! self.desired_caps = { "platformName": PLATFROM, "deviceName": DEVIE_NAME, "udid":UDID, ...

    2024-01-30 20:37:53