【嵌入式设计与开发项目-TIM程序设计应用】


知识扫盲:TIM除了可以实现基本的定时功能外,还可以实现输入捕获和输出比较等功能。 输入捕获可以测量PWM信号的周期和脉宽,输出比较可以输出单脉冲,也可以输出PWM信号。

一、实现的功能

  • ①TIM1的通道2(PA9)输出1kHz、占空比为25%的矩形波;
  • ②用TIM2通道2(PA1)测量矩形波周期和脉冲宽度的初始化;

二、根据功能实现代码

1、主文件main.c

#include"key.h"
#include"led.h"
#include"lcd.h"
#include "usart.h"
#include "i2c.h"
#include "adc.h"
#include "tim.h"

unsigned int uiTim_Val[2];
unsigned char ucSec,ucSec1;
unsigned char pucStr[21];
unsigned long ulTick_ms;

void TIM_Proc(void);

int main(void)
{
	SysTick_Config(72000);	//定时1ms(HCLK = 72MHz)
	KEY_Init();
	LED_Init();
	
	STM3210B_LCD_Init();
	LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(White);
	USART2_Init(9600);
	i2c_init();
	ADC1_Init();
	TIM1_OCInit();
	TIM2_ICInit();
	
	sprintf((char *)pucStr,"		TIM DEMO");
	LCD_DisplayStringLine(Line3,pucStr);
	printf("%s\r\n",pucStr);
		
	while(1)
	 {
		LED_Disp(ucSec);
		TIM_Proc();
	 }
	}
	
	void TIM_Proc(void)
	{
		if(ucSec != ucSec1)
		{
			ucSec1 = ucSec;
			
			TIM2_Cap(uiTim_Val);
			
			sprintf((char *)pucStr,"		%4u %1ums",
				 uiTim_Val[0],uiTim_Val[0]/1000);
			LCD_DisplayStringLine(Line5,pucStr);
			printf("%3u %s",ucSec,pucStr);
			
			sprintf((char *)pucStr,"		%4u %2u%%",uiTim_Val[1],uiTim_Val[1]*100/uiTim_Val[0]);
			LCD_DisplayStringLine(Line6,pucStr);
			printf("%s\r\n",pucStr);
		}	
	}
	
//SysTick 中断处理程序
	void SysTick_Handler(void)
	{
		ulTick_ms++;
		if(ulTick_ms % 1000 ==0)
		ucSec++;
		
	}

主函数分析:❤️ ❤️ ❤️

  1. 每隔1s捕获一次矩形波周期和脉冲宽度;
  2. 通过TIM2_Cap()获取周期和高电平所占的时间,从而计算出脉宽为25%;

2、TIM头文件“tim.h”

#include "stm32f10x.h"

void TIM1_OCInit(void);
void TIM2_ICInit(void);
unsigned char TIM2_Cap(unsigned int* puiTim_Val);

简要分析:❤️ ❤️

  1. 初始化PA9为复用推挽输出,同时初始化TIM1定时器1和OC比较输出250us高电平的矩形方波;
  2. 初始化PA1为浮空输入,同时初始化TIM2定时器2和IC上升沿触发并直接映射到TI1上;
  3. 获取捕获到的PWM的周期和高电平的所占周期;

3、TIM源文件“tim.c”

#include "tim.h"

//TIM1通道2(PA9)输出矩形波初始化子程序
void TIM1_OCInit(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_OCInitTypeDef TIM_OCInitStruct;

	//允许GPIOA和TIM1时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
	
	//PA9-IN8复用推挽输出
	GPIO_InitStruct.GPIO_Pin =GPIO_Pin_9;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStruct.GPIO_Mode =GPIO_Mode_AF_PP;	//复用推挽输出模式
	GPIO_Init(GPIOA,&GPIO_InitStruct);

	TIM_TimeBaseInitStruct.TIM_Prescaler = 71;		//psc预装分频器的值
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;		//向上计数模式
	TIM_TimeBaseInitStruct.TIM_Period = 999;	//定时器周期,设定自动重载的值
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;	//时钟不分频
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;	//溢出重复计数器
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);	//根据指定参数初始化TIM1

	TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;		//脉宽调制模式1
	TIM_OCInitStruct.TIM_OutputState =TIM_OutputState_Enable;		//使能比较输出
	TIM_OCInitStruct.TIM_OutputNState =TIM_OutputNState_Disable;		//禁止比较互补输出		
	TIM_OCInitStruct.TIM_Pulse = 250;	//比较输出的脉冲宽度,设置占空比
	TIM_OCInitStruct.TIM_OCPolarity =TIM_OCPolarity_High;	//比较输出的极性为高电平
	TIM_OC2Init(TIM1, &TIM_OCInitStruct);	 //根据TIM_OCInitStruct中指定的参数初始化外设TIMx


	TIM_CtrlPWMOutputs(TIM1, ENABLE);	//主动输出使能
	TIM_Cmd(TIM1, ENABLE);	//使能定时器,计数器开始计数
}


//TIM2通道2(PA1)测量矩形波周期和脉冲宽度初始化子程序
void TIM2_ICInit(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_ICInitTypeDef TIM_ICInitStruct;

	//允许GPIOA和TIM2时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	
	//PA9-IN8复用推挽输出
	GPIO_InitStruct.GPIO_Pin =GPIO_Pin_1;
	GPIO_InitStruct.GPIO_Mode =GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA,&GPIO_InitStruct);

	TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;	//向上计数模式
	TIM_TimeBaseInitStruct.TIM_Period = 65535;	//定时器周期,设定自动重载的值
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);

	TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;	//选择通道2
	TIM_ICInitStruct.TIM_ICPolarity =TIM_ICPolarity_Rising;	//设置为上升沿捕获
	TIM_ICInitStruct.TIM_ICSelection =TIM_ICSelection_DirectTI;	//直接映射到TI1
	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;	//不分频
	TIM_ICInitStruct.TIM_ICFilter =0;	//滤波器长度
	TIM_PWMIConfig(TIM2,&TIM_ICInitStruct);

	TIM_SelectInputTrigger(TIM2,TIM_TS_TI2FP2);	//参考TIM结构图选择滤波后的TI2输入作为触发源,触发下面程序的复位
	TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);//复位模式-选中的触发输入(TRGI)的上升沿初始化计数器,并且产生一个更新线号
	TIM_Cmd(TIM2,ENABLE);
}

//TIM2测量方波周期和脉冲宽度处理程序
unsigned char TIM2_Cap(unsigned int* puiTim_Val)
{
	//状态标志位获取
	if(TIM_GetFlagStatus(TIM2,TIM_FLAG_CC2))
	{
		puiTim_Val[0] = TIM_GetCapture2(TIM2)+1;	//获得CCR2的值
		puiTim_Val[1] = TIM_GetCapture1(TIM2)+1;	//获得CCR1的值
		return 1;
	}
	return 0;
}

简要分析:❤️ ❤️

  1. 初始化TIM1通道2(PA9)输出矩形波的顺序:①初始化PA9的GPIO结构体(复用推挽输出)②初始化TIM和OC结构体→ ③配置TIM1的预分频值、计数模式、分频值、分频系数、重复计数值以及初始化TIM1结构体④配置oc的工作模式、使能比较输出模式、禁止补偿输出、设置pwm占空比为250、设置占空比的电平以及初始化OC结构体⑤主动输出使能以及启动定时器1
  2. 初始化TIM2通道2(PA1)测量矩形波周期和脉冲宽度的顺序:①初始化PA1的GPIO结构体(浮空输入模式)②初始化TIM和IC结构体→ ③配置TIM1的预分频值、计数模式、分频值、分频系数、重复计数值以及初始化TIM1结构体④配置IC的通道、触发条件、直接映射、分频系数、滤波器长度以及初始化IC结构体⑤选择滤波后的TI2输入作为触发源、选中的触发输入(TRGI)的上升沿初始化计数器、启动TIM2
  3. 获取TIM2的CC2标志位,然后获取方波周期脉冲宽度

三、实现功能过程的注意与学习点

1、注意点

  1. 配置的参数太多,容易配错或者缺少一些配置;
  2. 当使用IO的复用功能时,需要使能AFIO时钟,开启IO的复用功能;

2、学习的知识点

  1. PWM矩形方波的输出的IO配置为复用推挽输出,输入捕获配置为浮空输入模式;
  2. 了解输出PWM输出方波和输入捕获的配置流程;
  3. 学会通过预分频值和分频值计算计数的周期,从而可以进行精确的延时以及方波的占空比设置;

❤️ ❤️ ❤️ ❤️ ❤️ ❤️

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序小鹿

博主不差钱,点个赞就行哈哈

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值