当前位置:   article > 正文

stm32下常用函数~中断定时器_stm32单片机定时器中断函数

stm32单片机定时器中断函数

学习江协科技stm32基于库函数开发记录一下
代码压缩包地址:code

函数

8.对射式红外传感器(中断)

中断流程

中断初始化
1.开启时钟
2.GPIO初始化
3.AFIO选择引脚
4.EXTI初始化
5.NVIC分组
6.NVIC配置   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启afio时钟

GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);//将外部中断的14号线映射到GPIOB

EXTI_Init(&EXTI_InitStruct);//中断初始化

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置nvic分组

NVIC_Init(&NVIC_InitStruct);//nvic初始化

EXTI_GetITStatus(EXTI_Line14)//获取标志位

EXTI_ClearITPendingBit(EXTI_Line14)//清除标志位

EXTI15_10_IRQHandler(void)//中断服务函数(启动文件)

CountSensor.h

#ifndef __COUNTSENSOR_H
#define __COUNTSENSOR_H

void CountSeneor_Init(void);//中断初始化
uint16_t CountSensor_Get(void);//次数获取
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

CountSensor.c

#include "stm32f10x.h"                  // Device header
uint16_t CountSensor_Count;
/*
	中断初始化
	1.开启时钟
	2.GPIO初始化
	3.AFIO选择引脚
	4.EXTI初始化
	5.NVIC分组
	6.NVIC配置
*/
void CountSeneor_Init(void)
{
	//开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启gpiob时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启afio时钟,外部中断必须开启afio时钟
	//GPIO初始化
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_14;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStruct);//将PB14脚初始化为上拉输入  
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);//选择用作EXTI线的GPIO引脚
	//中断线选择,将外部中断的14号线映射到GPIOB,即选择PB14为外部中断引脚
	
	EXTI_InitTypeDef EXTI_InitStruct;
	EXTI_InitStruct.EXTI_Line = EXTI_Line14;//配置外部中断线
	EXTI_InitStruct.EXTI_LineCmd = ENABLE;//外部中断线使能
	EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;//指定外部中断线为中断模式
	EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;//外部中断线上升沿触发
	EXTI_Init(&EXTI_InitStruct);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置nvic分组,目前为分组2,抢占优先级与响应优先级均为0~3
	
	//nvic配置	
	NVIC_InitTypeDef NVIC_InitStruct;//结构体定义
	NVIC_InitStruct.NVIC_IRQChannel = EXTI15_10_IRQn;//选择配置nvic的EXTI15_10
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//使能
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;//响应优先级
	NVIC_Init(&NVIC_InitStruct);
}
void EXTI15_10_IRQHandler(void)//服务中断函数
{
	if(EXTI_GetITStatus(EXTI_Line14)== SET)
	{
		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0)
		{
			CountSensor_Count ++;
		}
		EXTI_ClearITPendingBit(EXTI_Line14);//结束清除标志位
	}
}

uint16_t CountSensor_Get(void)
{
	return CountSensor_Count;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "oled.h"
#include "countsensor.h"

int main()
{
	OLED_Init();//oled初始化
	CountSeneor_Init();
	OLED_ShowString(1,1,"count:");//第一行第一列展示字符串count:
	while(1)
	{
		OLED_ShowNum(1,7,CountSensor_Get(),5);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

9.旋转编码器(中断)

Encoder.h

#ifndef __ENCODER_H
#define __ENCODER_H

void Encoder_Init(void);
int16_t Encoder_Get(void);
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Encoder.c

#include "stm32f10x.h"                  // Device header
uint16_t Encoder_Count;
/*
	中断初始化
	1.开启时钟
	2.GPIO初始化
	3.AFIO选择引脚
	4.EXTI初始化
	5.NVIC分组
	6.NVIC配置
*/
void Encoder_Init(void)
{
	//开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启gpiob时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启afio时钟,外部中断必须开启afio时钟
	//GPIO初始化
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_0;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStruct);//将PB14脚初始化为上拉输入  
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);//选择用作EXTI线的GPIO引脚
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);
	
	EXTI_InitTypeDef EXTI_InitStruct;
	EXTI_InitStruct.EXTI_Line = EXTI_Line0 | EXTI_Line1;//配置外部中断线
	EXTI_InitStruct.EXTI_LineCmd = ENABLE;//外部中断线使能
	EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;//指定外部中断线为中断模式
	EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;//外部中断线下降沿触发
	EXTI_Init(&EXTI_InitStruct);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//配置nvic分组,目前为分组2,抢占优先级与响应优先级均为0~3
	
	//nvic配置	
	NVIC_InitTypeDef NVIC_InitStruct;//结构体定义
	NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;//选择配置nvic的EXTI0
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//使能
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;//响应优先级
	NVIC_Init(&NVIC_InitStruct);
	
	NVIC_InitStruct.NVIC_IRQChannel = EXTI1_IRQn;//选择配置nvic的EXTI0
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//使能
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;//抢占优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;//响应优先级
	NVIC_Init(&NVIC_InitStruct);
}
void EXTI0_IRQHandler(void)//服务中断函数
{
	if(EXTI_GetITStatus(EXTI_Line0)== SET)
	{
		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
		{
			if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
			{
				Encoder_Count ++;
			} 
		}
		EXTI_ClearITPendingBit(EXTI_Line0);//结束清除标志位
	}
}
void EXTI1_IRQHandler(void)//服务中断函数
{
	if(EXTI_GetITStatus(EXTI_Line1)== SET)
	{
		if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
		{
			if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
			{
				Encoder_Count --;
			}
		}
		EXTI_ClearITPendingBit(EXTI_Line1);//结束清除标志位
	}
}

int16_t Encoder_Get(void)
{
	int16_t Temp;
	Temp = Encoder_Count;
	Encoder_Count = 0;
	return Temp;
}//返回后数据清零

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86

10.定时器内部时钟

定时器初始化流程

1.开启时钟
2.配置时钟源
3.时基单元初始化
4.中断输出配置
5.nvic中断分组
6.nvic配置
7.tim使能
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//开启tim2时钟位于apb1总线

TIM_InternalClockConfig(TIM2);//选择时钟(内部时钟tim2)

TIM_TimeBaseInit();//配置时基单元

TIM_ITConfig();//中断输出配置

TIM_Cmd()//定时器使能

Timer.h

#ifndef __TIMER_H
#define __TIMER_H

void Timer_Init(void);

#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Timer.c

#include "stm32f10x.h"                  // Device header
/*
	1.开启时钟
	2.配置时钟源
	3.时基单元初始化
	4.中断输出配置
	5.nvic中断分组
	6.nvic配置
	7.tim使能
*/

/*
51
32   usart/iic/spi/freertos ~ 通信+系统
树莓派 ~linux编程
*/
void Timer_Init(void)
{
	//开启时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	//选择时钟源~~选择tim2为内部时钟
	TIM_InternalClockConfig(TIM2);
	//配置时基单元
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//计数模式~向上计数
	TIM_TimeBaseInitStruct.TIM_Period = 10000 - 1;//计数周期
	TIM_TimeBaseInitStruct.TIM_Prescaler = 7200 - 1;//预分频器72M = 7200 0000 /10000 /7200 = 1
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
	
	//中断输出配置
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//开启nvic中断
	
	//nvic中断分组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//ncic中断分组2
	//nvic初始化
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStruct);
	//定时器使能
	TIM_Cmd(TIM2, ENABLE);
}
//void TIM2_IRQHandler(void)
//{
//	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
//	{
//		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除标志位
//	}
//}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "oled.h"
#include "Timer.h"//.h文件多打了一个空格

int16_t Num;

int main()
{
	OLED_Init();//oled初始化
	Timer_Init();
	OLED_ShowString(1,1,"Num:");
	while(1)
	{
		OLED_ShowNum(1,5,Num,5);
	}
}

void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
		Num ++ ;
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除标志位
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

11.定时器外部时钟

定时器流程

1.开启时钟
2.配置时钟源
3.时基单元初始化
4.中断输出配置
5.nvic中断分组
6.nvic配置
7.tim使能 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

TIM_ETRClockMode2Config();//配置外部时钟模式2

TIM_GetCounter(TIM2);//返回tim2的cnt值

Timer.h

#ifndef __TIMER_H
#define __TIMER_H

void Timer_Init(void);
uint16_t Timer_GetCount(void);
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Timer.c

#include "stm32f10x.h"                  // Device header

void Timer_Init(void)
{
	//开启时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
//
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启gpioa时钟
//
	
//
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStruct);//gpioa初始化~上拉输入
//

//
	TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x0f);
	//配置外部时钟模式2,外设tim2,外部触发关闭,外部触发极性上升沿,滤波最大~0x0f
//
//	//选择时钟源~~选择tim2为内部时钟
//	TIM_InternalClockConfig(TIM2);
	//配置时基单元
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//计数模式~向上计数
	TIM_TimeBaseInitStruct.TIM_Period = 10 - 1;//计数周期 arr
	TIM_TimeBaseInitStruct.TIM_Prescaler = 1 - 1;//预分频器psc
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;//重复计数器
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
	
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除中断触发标志位
	//中断输出配置
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//开启nvic中断
	//启用或禁用指定中断,tim2,tim更新中断源,使能
	//nvic中断分组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//ncic中断分组2
	//nvic初始化
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStruct);
	//定时器使能
	TIM_Cmd(TIM2, ENABLE);
}
uint16_t Timer_GetCount(void)
{
	return TIM_GetCounter(TIM2);//返回tim2的cnt值
}
//void TIM2_IRQHandler(void)
//{
//	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
//	{
//		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除标志位
//	}
//}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "oled.h"
#include "Timer.h"//.h文件多打了一个空格

int16_t Num;

int main()
{
	OLED_Init();//oled初始化
	Timer_Init();
	OLED_ShowString(1,1,"Num:");
	OLED_ShowString(2,1,"CNT:");
	while(1)
	{
		OLED_ShowNum(1,5,Num,5);
		OLED_ShowNum(2,5,Timer_GetCount(),5);
	}
}

void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
		Num ++ ;
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除标志位
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

12.PWM控制LED

输出比较流程

1.rcc开启时钟(tim/gpio)
2.配置时基单元
3.配置输出比较单元(ccr/输出比较模式/极性选择/输出使能)
4.配置GPIO口为复用推挽
5.启动计数器
  • 1
  • 2
  • 3
  • 4
  • 5

TIM_InternalClockConfig(TIM2); //内部时钟源选择

TIM_TimeBaseInit();//时基单元初始化

TIM_OC1Init();//输出比较初始化

TIM_OCStructInit();//结构体赋值

TIM_Cmd();//定时器使能

TIM_SetCompare1();//设置ccr1的值

pwm.h

#ifndef __PWM_H
#define __PWM_H
void PWM_Init(void);//pwm初始化
void PWM_SetComparel(uint16_t Compare);//设置ccr1的值用于调节占空比
#endif
  • 1
  • 2
  • 3
  • 4
  • 5

pwm.c

#include "stm32f10x.h"                  // Device header
/*
1.rcc开启时钟(tim/gpio)
2.配置时基单元
3.配置输出比较单元(ccr/输出比较模式/极性选择/输出使能)
4.配置GPIO口为复用推挽
5.启动计数器
*/
void PWM_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);							//tim2时钟开启
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);             //gpioa初始化
	
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);																//gpio_a0脚初始化
	
	TIM_InternalClockConfig(TIM2);																	//内部时钟源选择
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Period = 100 - 1;//计数周期
	TIM_TimeBaseInitStruct.TIM_Prescaler = 720 - 1;//预分频器
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;//重复计数器
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);                //时基单元初始化
	
	TIM_OCInitTypeDef TIM_OCInitStruct;
	TIM_OCStructInit(&TIM_OCInitStruct);//结构体初始化,结构体未完全赋值先进行初始化赋值
	
	TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//输出比较模式
	TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//输出比较极性~high原样输出/low反向输出
	TIM_OCInitStruct.TIM_OutputState = ENABLE;//使能
	TIM_OCInitStruct.TIM_Pulse = 0;//CCR初始值
	TIM_OC1Init(TIM2,&TIM_OCInitStruct);                            //输出比较初始化
	
	TIM_Cmd(TIM2, ENABLE);//使能,定时器开始运行
}
void PWM_SetComparel(uint16_t Compare)
{
	TIM_SetCompare1(TIM2, Compare);//设置ccr1的值
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "oled.h"
#include "pwm.h"

uint8_t i;

int main()
{
	OLED_Init();//oled初始化
	PWM_Init();//pwm初始化
	while(1)
	{
		for(i = 0;i<=100;i++)
		{
			PWM_SetComparel(i);
			Delay_ms(10);
		}
		for(i = 0;i<=100;i++)
		{
			PWM_SetComparel(100 - i);
			Delay_ms(10);
		}
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

13.PWM控制舵机

Servo.h

#ifndef __SERVO_H
#define __SERVO_H
void Servo_Init(void);
void Servo_SetAngle(float Angle);
#endif 
  • 1
  • 2
  • 3
  • 4
  • 5

Servo.c

#include "stm32f10x.h"                  // Device header
#include "stm32f10x.h"                  // Device header
#include "pwm.h"
void Servo_Init(void)
{
	PWM_Init();//初始化舵机底层pwm
}
void Servo_SetAngle(float Angle)
{
	PWM_SetCompare2(Angle / 180 * 2000 + 500);//设置占空比
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "oled.h"
#include "Servo.h"
#include "Key.h"

uint8_t KeyNum;
float Angle;

int main()
{
	OLED_Init();//oled初始化
	Servo_Init();//舵机初始化
	Key_Init();//按键初始化
	
	OLED_ShowString(1,1,"Angle:");//显示静态字符"Angle:"
	
	while(1)
	{
		KeyNum = Key_GetNum();//得到键码返回值
		if(KeyNum == 1)
		{
			Angle += 30;//角度增加30
			if(Angle > 180)
			{
				Angle = 0;
			}
		}
		Servo_SetAngle(Angle);
		OLED_ShowNum(1,7,Angle,3);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

14.pwm驱动直流电机

Motor.h

#ifndef __MOTOR_H
#define __MOTOR_H
void Motor_Init(void);//舵机初始化
void Motor_SetSpeed(int8_t Speed);//速度设置
#endif
  • 1
  • 2
  • 3
  • 4
  • 5

Motor.c

#include "stm32f10x.h"                  // Device header
#include "pwm.h"
void Motor_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA ,&GPIO_InitStruct);//PA4与PA5脚进行初始化,用作控制脚
	
	PWM_Init();//PA2脚用作输出pwm
}
void Motor_SetSpeed(int8_t Speed)
{
	if(Speed >= 0)
	{
		GPIO_SetBits(GPIOA, GPIO_Pin_4);
		GPIO_ResetBits(GPIOA, GPIO_Pin_5);
		PWM_SetCompare3(Speed);
	}
	else
	{
		GPIO_ResetBits(GPIOA,GPIO_Pin_4);
		GPIO_SetBits(GPIOA,GPIO_Pin_5);
		PWM_SetCompare3(-Speed);//反向旋转
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "oled.h"
#include "Motor.h"
#include "Key.h"

uint8_t KeyNum;
int8_t Speed;

int main()
{
	OLED_Init();//oled初始化
	Motor_Init();//舵机初始化
	Key_Init();//按键初始化
	
	OLED_ShowString(1,1,"speed:");
	
	while(1)
	{
		KeyNum = Key_GetNum();
		if(KeyNum == 1)
		{
			Speed += 20;
			if(Speed > 100)
			{
				Speed = -100;
			}
		}
		Motor_SetSpeed(Speed);//占空比传递
		OLED_ShowSignedNum(1,7,Speed,3);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

15.定时器输入捕获

TIM_ICInit(TIM3,&TIM_ICInitStruct);//输入捕获初始化

TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);//触发源选择~TI1FP1

TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);//从模式选择

输入捕获流程

1.rcc开启时钟(gpio/tim)
2.gpio初始化(gpio~输入模式)~上拉 or 浮空  
3.配置时基单元,让cnt计数器在内部时钟的驱动下自增
4.配置输入捕获单元(滤波器、极性、直连通道 or 交叉通道、分频器) 
5.选择从模式的触发源ti1fp1
6.选择触发后进行的操作reset
7.tim开启定时器
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

ic.h

#ifndef __IC_H
#define __IC_H
void Ic_Init(void);//输入捕获初始化
uint32_t Ic_GetFreq(void);//获取频率
#endif
  • 1
  • 2
  • 3
  • 4
  • 5

ic.c

#include "stm32f10x.h"                  // Device header
/*
1.rcc开启时钟(gpio/tim)
2.gpio初始化(gpio~输入模式)~上拉 or 浮空  
3.配置时基单元,让cnt计数器在内部时钟的驱动下自增
4.配置输入捕获单元(滤波器、极性、直连通道 or 交叉通道、分频器)  
5.选择从模式的触发源ti1fp1
6.选择触发后进行的操作reset
7.tim开启定时器
*/
void Ic_Init(void)
{
	//rcc开启时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);							//tim2时钟开启
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);             //gpioa初始化
	//gpio初始化
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;//复用推挽输出
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);																//gpio_a0脚初始化
	//时钟源选择
	TIM_InternalClockConfig(TIM3);																	//内部时钟源选择
	//时基单元初始化
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Period = 65536 - 1;//计数周期
	TIM_TimeBaseInitStruct.TIM_Prescaler = 72 - 1;//预分频器
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;//重复计数器
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);  
	//输入捕获初始化
	TIM_ICInitTypeDef TIM_ICInitStruct;
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;//模式3通道1
	TIM_ICInitStruct.TIM_ICFilter = 0xF;//滤波
	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;//极性,不反转
	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;//预分频,不分频
	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;//直接选择
	TIM_ICInit(TIM3,&TIM_ICInitStruct);                                  //<=====================
	//选择触发源及从模式
	TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);//触发源选择~TI1FP1       //<=====================
	TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);//选择从模式					 //<=====================
	
	TIM_Cmd(TIM3,ENABLE);//使能tim3,定时器开始运行
}
uint32_t Ic_GetFreq(void)
{
	return 1000000 / (TIM_GetCapture1(TIM3) + 1);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "oled.h"
#include "pwm.h"
#include "ic.h"
int main()
{
	OLED_Init();//oled初始化
	PWM_Init();//pwm初始化
	Ic_Init();//输入捕获初始化
	OLED_ShowString(1,1,"Freq:00000Hz");
	PWM_SetPrescaler(720 - 1);//设置频率 freq = 72M / (psc + 1)/100
	PWM_SetCompare3(50);//设置占空比 duty = ccr / 100
	while(1)
	{
		OLED_ShowNum(1,6,Ic_GetFreq(),5);//频率展示
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

16.输入捕获~频率与占空比

TIM_PWMIConfig();//传入通道及结构体变量将自动配置另一个通道

ic.h

#ifndef __IC_H
#define __IC_H
void Ic_Init(void);//输入捕获初始化
uint32_t Ic_GetFreq(void);//获取频率
uint32_t Ic_GetDuty(void);//获取占空比
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

ic.c

#include "stm32f10x.h"                  // Device header
/*
1.rcc开启时钟(gpio/tim)
2.gpio初始化(gpio~输入模式)~上拉 or 浮空  
3.配置时基单元,让cnt计数器在内部时钟的驱动下自增
4.配置输入捕获单元(滤波器、极性、直连通道 or 交叉通道、分频器)  
5.选择从模式的触发源ti1fp1
6.选择触发后进行的操作reset
7.tim开启定时器
*/
void Ic_Init(void)
{
	//rcc开启时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);							//tim2时钟开启
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);             //gpioa初始化
	//gpio初始化
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;//复用推挽输出
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);																//gpio_a0脚初始化
	//时钟源选择
	TIM_InternalClockConfig(TIM3);																	//内部时钟源选择
	//时基单元初始化
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Period = 65536 - 1;//计数周期
	TIM_TimeBaseInitStruct.TIM_Prescaler = 72 - 1;//预分频器
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;//重复计数器
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);  
	//输入捕获初始化(pwmi)
	TIM_ICInitTypeDef TIM_ICInitStruct;
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;//模式3通道1
	TIM_ICInitStruct.TIM_ICFilter = 0xF;//滤波
	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;//极性,不反转
	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;//预分频,不分频
	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;//直接选择
	//TIM_ICInit(TIM3,&TIM_ICInitStruct);                                  
	TIM_PWMIConfig(TIM3,&TIM_ICInitStruct);//将结构体变量交给TIM_PWMIConfig,配置tim3的输入捕获通道
																				 //同时此函数会把另一个通道配置为相反模式//<=====================
	//选择触发源及从模式
	TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);//触发源选择~TI1FP1       
	TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);//选择从模式					 
	
	TIM_Cmd(TIM3,ENABLE);//使能tim3,定时器开始运行
}
uint32_t Ic_GetFreq(void)
{
	return 1000000 / (TIM_GetCapture1(TIM3) + 1);
}
uint32_t Ic_GetDuty(void)
{
	return (TIM_GetCapture2(TIM3) + 1) * 100 / (TIM_GetCapture1(TIM3) + 1);//计算占空比
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "oled.h"
#include "pwm.h"
#include "ic.h"
int main()
{
	OLED_Init();//oled初始化
	PWM_Init();//pwm初始化
	Ic_Init();//输入捕获初始化
	OLED_ShowString(1,1,"Freq:00000Hz");
	OLED_ShowString(2,1,"Duty:00%");
	PWM_SetPrescaler(720 - 1);//设置频率 freq = 72M / (psc + 1)/100
	PWM_SetCompare3(50);//设置占空比 duty = ccr / 100
	while(1)
	{
		OLED_ShowNum(1,6,Ic_GetFreq(),5);//频率展示
		OLED_ShowNum(2,6,Ic_GetDuty(),2);//占空比显示
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

17.编码器测速

TIM_EncoderInterfaceConfig();//配置编码器以及两个通道是否反相

EncoderTwo.h

#ifndef __ENCODERTWO_H
#define __ENCODERTWO_H
void EncoderTwo_Init(void);//编码器测速初始化
int16_t Encoder_Get(void);//获取编码器测速值
#endif
  • 1
  • 2
  • 3
  • 4
  • 5

EncoderTwo.c

#include "stm32f10x.h"                  // Device header

void EncoderTwo_Init(void)
{
	/*开启时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);			//开启TIM3的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);			//开启GPIOA的时钟
	
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);							//将PA6和PA7引脚初始化为上拉输入
	
	/*时基单元初始化*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;				//定义结构体变量
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;     //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,选择向上计数
	TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;               //计数周期,即ARR的值
	TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;                //预分频器,即PSC的值
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;            //重复计数器,高级定时器才会用到
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);             //将结构体变量交给TIM_TimeBaseInit,配置TIM3的时基单元
	
	//输入捕获初始化
	TIM_ICInitTypeDef TIM_ICInitStruct;
	TIM_ICStructInit(&TIM_ICInitStruct);//不完全赋值先进行初始化//<======================
	
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;//选择定时器通道
	TIM_ICInitStruct.TIM_ICFilter = 0xf;//滤波器
	TIM_ICInit(TIM3,&TIM_ICInitStruct);
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;//选择定时器通道
	TIM_ICInitStruct.TIM_ICFilter = 0xf;//滤波器
	TIM_ICInit(TIM3,&TIM_ICInitStruct);

	TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);
	//配置编码器模式以及两个输入通道是否反相
	TIM_Cmd(TIM3, ENABLE);
}
int16_t Encoder_Get(void)
{
	int16_t Temp;
	Temp = TIM_GetCounter(TIM3);//获取计数器计数值
	TIM_SetCounter(TIM3 , 0);//设置计数器值
	return Temp;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "oled.h"
#include "timer.h"
#include "encodertwo.h"

int16_t Speed;

int main()
{
	OLED_Init();//oled初始化
	Timer_Init();//定时器初始化
	EncoderTwo_Init();//编码器接口初始化
	OLED_ShowString(1,1,"Speed:");
	while(1)
	{
		OLED_ShowSignedNum(1,7,Speed,5);
	}
}
void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
		Speed = Encoder_Get();//将寄存器中数值保存到中间变量Speed中
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除标志位
	}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/212588
推荐阅读
相关标签
  

闽ICP备14008679号