stm32库函数学习篇

发布者:psi33最新更新时间:2022-05-31 来源: eefocus关键字:stm32  库函数  交替闪烁 手机看文章 扫描二维码
随时随地手机看文章

两天学习了一下stm32通用定时器的输入捕获功能。在网上看到很多网友说触发中断程序进不了,于是自己也测试了个小程序,还好能够进入中断。呵呵~

 

实现功能:PA8随意延时驱动led灯闪烁,并且将PA8用杜邦线连接到PA7口,PA7是通用定时器TIM3的2通道,在TIM3_CH2触发中断程序中取反连接到PD2口的led灯,指示中断程序运行,并且每次进入中断后改变触发捕获的极性。实现两个led灯会交替闪烁。

 

先有必要了解stm32定时器的输入触发模块,如下图:




需要注意的是,一眼望去一个定时器似乎有8个通道,左边四个,右边四个,但其实左边和右边是共用相同的IO引脚,所以名称标注是一模一样。也就是说,每个通用定时器都只有四个独立通道,当某一通道作为了输入触发功能那就不能再作为输出匹配功能。这一点我们也可以从其他地方找到印证。比如TIM_ITConfig()函数中如下:

void TIM_ITConfig

(

TIM_TypeDef * 

TIMx,



uint16_t 

TIM_IT,



FunctionalState 

NewState 


)



Enables or disables the specified TIM interrupts.

Parameters:

TIMx,:

where x can be 1 to 17 to select the TIMx peripheral.

TIM_IT,:

specifies the TIM interrupts sources to be enabled or disabled. This parameter can be any combination of the following values:

TIM_IT_Update: TIM update Interrupt source TIM_IT_CC1: TIM Capture Compare 1 Interrupt source TIM_IT_CC2: TIM Capture Compare 2 Interrupt source TIM_IT_CC3: TIM Capture Compare 3 Interrupt source TIM_IT_CC4: TIM Capture Compare 4 Interrupt source TIM_IT_COM: TIM Commutation Interrupt source TIM_IT_Trigger: TIM Trigger Interrupt source TIM_IT_Break: TIM Break Interrupt source

我们可以看到此函数TIM_IT参数的取值范围如下:

TIM_IT_Update: TIM update Interrupt source

TIM_IT_CC1: TIM Capture Compare 1 Interrupt source

TIM_IT_CC2: TIM Capture Compare 2 Interrupt source

TIM_IT_CC3: TIM Capture Compare 3 Interrupt source

TIM_IT_CC4: TIM Capture Compare 4 Interrupt source

TIM_IT_COM: TIM Commutation Interrupt source

TIM_IT_Trigger: TIM Trigger Interrupt source

TIM_IT_Break: TIM Break Interrupt source

也就是说每个通道的捕获和比较功能是共用一个中断标志。

 

 

stm32定时器输入触发功能其实挺简单的,与AVR单片机几乎一样。就是单片机引脚上一旦出现一个有效边沿(可以配置为上升、下降或者上升下降均触发),那么定时器计数器CNT里面的值就会被相应的Capture/Compare X Register保存下来。这里X可以是1,2,3,4任何一个。并且中断标志位被置位。但是此时TIM的计数寄存器CNT却不管这一事件的发生,继续自己的计数。此功能可以用来测量外部信号的脉宽或者是周期。

 

对于定时器的时基单元TIM_TimeBaseStructure就不作说明了,在我前面的文章有专门介绍。下面就重点讲解输入触发单元TIM_ICInitStructure。

首先看次结构体原型的定义如下:




typedef struct
{

   uint16_t TIM_Channel;      /*!< Specifies the TIM channel.
                                  This parameter can be a value of @ref TIM_Channel */
   uint16_t TIM_ICPolarity;   /*!< Specifies the active edge of the input signal.
                                   This parameter can be a value of @ref TIM_Input_Capture_Polarity */
   uint16_t TIM_ICSelection;  /*!< Specifies the input.
                                  This parameter can be a value of @ref TIM_Input_Capture_Selection */

   uint16_t TIM_ICPrescaler;  /*!< Specifies the Input Capture Prescaler.
                                   This parameter can be a value of @ref TIM_Input_Capture_Prescaler */

  uint16_t TIM_ICFilter;     /*!< Specifies the input capture filter.
                                   This parameter can be a number between 0x0 and 0xF */
} TIM_ICInitTypeDef;

 

 

它一共有5个成员,5个成员具体作用,我们只要看看3.5版本固件库的说明就清楚了。

 

uint16_t TIM_ICInitTypeDef::TIM_Channel

Specifies the TIM channel. This parameter can be a value of TIM_Channel

其中TIM_Channel的取值范围如下:

TIM_Channel_1.

TIM_Channel_2

TIM_Channel_3

TIM_Channel_4

uint16_t TIM_ICInitTypeDef::TIM_ICFilter

Specifies the input capture filter. This parameter can be a number between 0x0 and 0xF

说实话这个成员具体作用我没有深入了解,仅仅知道是作为对输入信号的滤波作用,估计是让用户设定用多少个采样时钟来确定最终输入信号,起到滤波作用,避免高频信号干扰,反正不管它了。

uint16_t TIM_ICInitTypeDef::TIM_ICPolarity

Specifies the active edge of the input signal. This parameter can be a value of TIM_Input_Capture_Polarity

这个就是触发边沿的极性选择了,取值范围如下:

TIM_ICPolarity_BothEdge

TIM_ICPolarity_Rising

TIM_ICPolarity_Falling

uint16_t TIM_ICInitTypeDef::TIM_ICPrescaler

Specifies the Input Capture Prescaler. This parameter can be a value of TIM_Input_Capture_Prescaler

这个成员是对外部信号进行分频,也即是设置上图中的Prescaler,可以设置为1/2/4/8分频。

uint16_t TIM_ICInitTypeDef::TIM_ICSelection

Specifies the input. This parameter can be a value of TIM_Input_Capture_Selection

这个成员的作用就必须要对照上面的示意图才能明白。仔细看上面的图,可以发现定时器的4个通道并不是完全独立的,而是1、2一组,3、4一组,同组之间的通道是有联系的。也就是可以出现交叉触发。而TIM_ICSelection就是选择要不要使用交叉来触发,如果不明白可以看固件库的说明文档,如下是此结构体成员的取值范围:

#define TIM_ICSelection_DirectTI   ((uint16_t)0x0001)

TIM Input 1, 2, 3 or 4 is selected to be connected to IC1, IC2, IC3 or IC4, respectively

#define TIM_ICSelection_IndirectTI   ((uint16_t)0x0002)

TIM Input 1, 2, 3 or 4 is selected to be connected to IC2, IC1, IC4 or IC3, respectively.

#define TIM_ICSelection_TRC   ((uint16_t)0x0003)

TIM Input 1, 2, 3 or 4 is selected to be connected to TRC.

也就是说,根据不同的取值,可以讲外部引脚的触发信号连到内部不同的单元,这样就使得单片机更加灵活了。

 

  

下面是main.c文件

#include "stm32f10x.h"

 GPIO_InitTypeDef GPIO_InitStructure;

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

TIM_ICInitTypeDef  TIM_ICInitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

 void delay()

{undefined

u32 i,j;

for(i=0;i<1000;i++)

for(j=0;j<5000;j++)

;

}

 void rcc_cfg()

{undefined

 ;

}

 void gpio_cfg()

{undefined

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOA, ENABLE);

 

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       //随意延时led取反,且将PA8作为触发定时器电平

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

 

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;                       //触发中断时,取反PD2

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

  GPIO_Init(GPIOD, &GPIO_InitStructure);

 

  /* TIM3 channel 2 pin (PA.07) configuration */

   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;

   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

   GPIO_Init(GPIOA, &GPIO_InitStructure);

}

 

void nvic_cfg()

{undefined

        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

              /* Enable the TIM3 global Interrupt */

       NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断

       NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级

       NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级

       NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能

       NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

}

 

void tim3_cfg()

{undefined

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);

   TIM_DeInit(TIM3);

  TIM_InternalClockConfig(TIM3);

  //预分频系数为36000-1,这样计数器时钟为72MHz/36000 = 2kHz

  TIM_TimeBaseStructure.TIM_Prescaler = 36000 - 1;

  //设置时钟分割

  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

  //设置计数器模式为向上计数模式

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  //设置计数溢出大小,每计2000个数就产生一个更新事件

  TIM_TimeBaseStructure.TIM_Period = 2000 - 1;

  //将配置应用到TIM2中

  TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);

   //禁止ARR预装载缓冲器

  TIM_ARRPreloadConfig(TIM3, DISABLE);

 

 //下面是对 TIM_ICInitStructure的配置

   TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;

   TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;

   TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;

   TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;    

   TIM_ICInitStructure.TIM_ICFilter = 0x0;       /*选择输入比较滤波器,滤波设置,经历几个周期跳变认定波形稳定0x0~0xF*/

    TIM_ICInit(TIM3, &TIM_ICInitStructure);

 

  //开启TIM2的中断

  TIM_ClearFlag(TIM3, TIM_IT_CC2);

  TIM_ITConfig(TIM3,TIM_IT_CC2,ENABLE);

 

  TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设

}

 

/**

  * @brief  Main program.

  * @param  None

  * @retval None

  */

int main(void)

{undefined

      rcc_cfg();

      gpio_cfg();

      nvic_cfg();

      tim3_cfg();

  while (1)

  {undefined

    /* Set PA8 */

    GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_SET);

       delay();

    /* Reset PA8 */

    GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_RESET);

       delay();

  }

}

 

注意定时器3通道2引脚设置为浮空输入。

 

 

 

下面是stm32f10x_it.c文件

 

#include "stm32f10x_it.h"

 u8 flag=0;

extern TIM_ICInitTypeDef  TIM_ICInitStructure;

[1] [2] [3]
关键字:stm32  库函数  交替闪烁 引用地址:stm32库函数学习篇

上一篇:STM32的定时器有两种捕获模式
下一篇:STM32定时器输出比较模式

推荐阅读最新更新时间:2024-11-16 20:03

stm32库函数学习篇----通用定时器(PWM功能)
上午花了半天时间熟悉了stm32的PWM模块。中午利用午饭时间把PWM功能调试成功。当然,很简单的东西,也许很多前辈估计都不屑一顾的东西。 今天最大的感叹就是网络资源实在是个巨大的宝库,真的很庆幸,在这个复杂的社会环境里,在一个到处充斥着私心、私利的时代,各个网站,各个论坛上的众多网友都时刻保持着开源的氛围。学习一定要和他人交流,而网络提供了这么一个极好的平台。 废话少说,言归正传。 实现功能:采用定时器2的通道2,使PA1输出频率1K,占空比40的PWM波形,用PA8随意延时取反led灯,指示程序运行。 首先熟悉一下定时器的PWM相关部分。看图最明白 其实PWM就是定时器的一个比较功能而已。 CNT里的值不断++
[单片机]
<font color='red'>stm32</font><font color='red'>库函数</font>学习篇----通用定时器(PWM功能)
STM32_总中断关闭
STM32在使用时有时需要禁用全局中断,比如MCU在升级过程中需禁用外部中断,防止升级过程中外部中断触发导致升级失败。 ARM MDK中提供了如下两个接口来禁用和开启总中断: __disable_irq(); // 关闭总中断 __enable_irq(); // 开启总中断 但 测试 发现这样一个问题,在关闭总中断后,如果有中断触发,虽然此时不会引发中断,但在调用__enable_irq()开启总中断后,MCU会立即处理之前触发的中断。这说明__disable_irq()只是禁止CPU去响应中断,没有真正的去屏蔽中断的触发,中断发生后,相应的寄存器会将中断标志置位,在__enable_irq()开启中断后,由于相应的中断
[单片机]
基于STM32的三种库函数代码效率对比解析
前言 ST已经推出了三种库函数,以方便客户快速开发STM32系列MCU。从最早的标准外设驱动库,到后来的Cube HAL,再到Cube LL以及直接操作寄存器。这几种库的代码效率到底如何呢?本文将针对这个问题进行粗略分析,并提供对比数据供大家参考。 问题分析 我们以GPIO翻转、TIM PWM 输出、ADCDMA 数据采集和DMA M2M这四个常用功能,通过不同的库函数来实现相同功能,最终来对比各个库函数的性能。四个工程代码的内容简述如下: GPIO翻转:切换GPIO的输出电平,其中包含了系统时钟初始化和GPIO翻转的代码。TIM PWM输出:通过TIM1 的通道1输出频率是36KHz的PWM,循环修改其占空比从25%到50%
[单片机]
基于<font color='red'>STM32</font>的三种<font color='red'>库函数</font>代码效率对比解析
stm32单步调试,出现*** error 65: access violation at 0x40023
问题解决如题: 在单步调试的时候,总是在systeminit()中运行,全速执行不起作用,出现调试错误信息如下 *** error 65: access violation at 0x40023800 : no 'read' permission 该问题的引起的原因是在MDK的设置问题上,Debug选项卡处:use simulator 和 use ,这两种是二选一,我们在use 这项前面打钩,问题就解决了
[单片机]
STM32嵌入式入门必看之文章
为什么要写这篇文章呢?这是一篇关于嵌入式入门的文章,因为我在进入嵌入式这个领域之前,也是遇到过非常多非常多的困难,所以呢,希望写下这篇文章,让大家看看少走弯路。 首先,我打算先列举一下大家问得最多的几个问题,然后我们一起由问题切入进行一些讨论。 问题1:我是学单片机好还是直接学STM32好??? 问题2:STM32如何才能快速入门? 问题3:为什么是STM32呢?为什么不是ARM9,ARM11呢? 下面我将逐个答复 首先问题1:我是单片机好还是直接学STM32好呢? 答:首先我们谈下目的,你学习的最终目的是能够开发产品或者成为项目经理;而目前市场上的单片机都基本用C语言了,用汇编进行开发的项目已经非常少了 在硬件接
[单片机]
proteus8.6仿真STM32按键控制LED灯程序
proteus8.6 按键控制LED灯闪烁情况 单片机源程序如下: #include led.h #include exti.h #include delay.h int main(void) { LED_Init(); //初始化与LED连接的硬件接口 EXTIX_Init();//外部中断初始化 while(1); }
[单片机]
proteus8.6仿真<font color='red'>STM32</font>按键控制LED灯程序
STM32学习之路:I2C的基本读写
宏定义: /*I2C传输速度,最高为400kHz*/ #define I2C_SPEED 400000 /* STM32 自身的 I2C 地址, 这个地址只要与 STM32 外挂的 I2C 器件地址不一样即可 */ #define I2C_OWN_ADDR 0x77 /*EEPROM地址*/ #define EEPROM_ADDR (0x50 1) //0xA0 #define EEPROM_SCL_GPIO_CLK RCC_AHB1Periph_GPIOB #define EEPROM_SCL_PIN GPIO_Pin_6 #define EEPROM_SCL_GPIO_PORT GPIOB #de
[单片机]
STM32单片机使用ST-LINK调试程序时不能设断点
我使用的是STM32单片机,昨天使用ST-LINK调试程序时,发现有些语句不能设断点。程序编译时OK的,没有错误,将程序烧录入单片机后程序看着也能正常运行,但是点击keil中debug按钮后程序进入调试状态,程序并没有停留在main函数的第一条语句,而是停留在别处。main函数第一条语句不能设置断点。 经过在网上查阅资料,发现可能是由于keil软件代码优化的问题。经过测试,发现果然是代码优化的问题。关于以上问题的解决方法:点击keil中“options for target”- 点击 C/C++ ,修改其中的 Optimization 一栏,选择“Level 0”即可。重新按keil中debug按钮进入调试状态,语
[单片机]

推荐帖子

DS1302做的LCD1602时钟晶振不起振
我用万用板做了个DS1302和1602显示的时钟,1602能显示时间但是时间不走。。。。DS1302的32.768KHZ的晶振两脚有电压但很少。。。请问是什么原因啊????谢谢DS1302做的LCD1602时钟晶振不起振你的补偿电容是多呢。??、一般用的是15P的。。你可以在示波器上观察一下。。。或者并一个电阻来加速起振。,30P的有两个问题,1、是否仅仅是1302的问题呢?如果是,你用示波器看看晶振,是否起振2、如果不是,你看看是否是其他问题,我觉得你的
leijiayou 51单片机
不知道有没有用过ADS1247芯片的?
最近调试ADS1247,用dSPIC33Fj做主控芯片,I/O模拟SPI时序。在试着读ADS1247内部寄存器的值时,但是每次读出来的值都不一样,不知道SPI通信是否正确?不知道有没有用过ADS1247芯片的?我最近在调试ADS1246,调试了挺久的没调通,楼主能不能给发一下你的源程序?谢谢啦!541195483@qq.com我调试过ADS1146,是16位的,ADS1247是24位的;输入管脚要加一个共模电压,否则读写寄存器不正确,不知道你是不是这个问题。墨眉发表于201
fx-sg TI技术论坛
[Micropython]TPYBoard v10x VS183B红外遥控器控制开发板
本文只是简单的红外遥控器控制TPYBoardv102开发板资料。可以做的拓展非常多,VS1838固件见附件。1.实验目的:•学习使用红外接收头VS1838的使用2.所需原器件:•TPYBoardv10X开发板1块•红外接收头VS1838一个•microUSB数据线1条•杜邦线若干•红外遥控器一个3.实验原
loktar MicroPython开源版块
触摸感应式应用设计指南
刚刚看了个不错的资料,分享给大家,正在边喝茶边看呢。触摸感应式应用设计指南
gaoyang9992006 stm32/stm8
DC/DC 24V转5V
有个项目24V转5V打算用Ti的TPS54331但是客户要求这个模块要耐3kvAC,请教这一点如何才能做的到。DC/DC24V转5V更正一下是这个电源模块的隔离电压3KV回复楼主rhoda_yao的帖子改了用Top414的方案了回复沙发rhoda_yao的帖子
rhoda_yao 电源技术
【2024 DigiKey 创意大赛】物料开箱--跑通所有官方例程
ESP32S3_EV_BOARD开箱最后时刻搭上来年度创意大赛的末班车,拿下来心心念念的ESP32S3_EV_BOARD。鉴于上一年的翻车事件,今年低调很多,再也不敢开那些天马行空的题目了,低调的做一些物联网项目,目标是力保不翻车。虽然迟到了一个月,基础学习不能少。EV_BOARD开发板上乐鑫官方推出为S3性能背书的产品,展示了S3在物联网、人机交互、视频语音方面的潜力。这些相关的Demo在官方网站上可以轻松获取,但全部正常跑通的人不多,原因是Espress
genvex DigiKey得捷技术专区
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved