学习江协科技stm32基于库函数开发记录一下
代码压缩包地址:code
文章来源地址https://www.toymoban.com/news/detail-826107.html
8.对射式红外传感器(中断)
中断流程
中断初始化
1.开启时钟
2.GPIO初始化
3.AFIO选择引脚
4.EXTI初始化
5.NVIC分组
6.NVIC配置
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
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;
}
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);
}
}
9.旋转编码器(中断)
Encoder.h
#ifndef __ENCODER_H
#define __ENCODER_H
void Encoder_Init(void);
int16_t Encoder_Get(void);
#endif
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;
}//返回后数据清零
10.定时器内部时钟
定时器初始化流程
1.开启时钟
2.配置时钟源
3.时基单元初始化
4.中断输出配置
5.nvic中断分组
6.nvic配置
7.tim使能
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
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);//清除标志位
// }
//}
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);//清除标志位
}
}
11.定时器外部时钟
定时器流程
1.开启时钟
2.配置时钟源
3.时基单元初始化
4.中断输出配置
5.nvic中断分组
6.nvic配置
7.tim使能
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
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);//清除标志位
// }
//}
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);//清除标志位
}
}
12.PWM控制LED
输出比较流程
1.rcc开启时钟(tim/gpio)
2.配置时基单元
3.配置输出比较单元(ccr/输出比较模式/极性选择/输出使能)
4.配置GPIO口为复用推挽
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
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的值
}
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);
}
}
}
13.PWM控制舵机
Servo.h
#ifndef __SERVO_H
#define __SERVO_H
void Servo_Init(void);
void Servo_SetAngle(float Angle);
#endif
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);//设置占空比
}
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);
}
}
14.pwm驱动直流电机
Motor.h
#ifndef __MOTOR_H
#define __MOTOR_H
void Motor_Init(void);//舵机初始化
void Motor_SetSpeed(int8_t Speed);//速度设置
#endif
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);//反向旋转
}
}
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);
}
}
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开启定时器
ic.h
#ifndef __IC_H
#define __IC_H
void Ic_Init(void);//输入捕获初始化
uint32_t Ic_GetFreq(void);//获取频率
#endif
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);
}
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);//频率展示
}
}
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
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);//计算占空比
}
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);//占空比显示
}
}
17.编码器测速
TIM_EncoderInterfaceConfig();//配置编码器以及两个通道是否反相
EncoderTwo.h
#ifndef __ENCODERTWO_H
#define __ENCODERTWO_H
void EncoderTwo_Init(void);//编码器测速初始化
int16_t Encoder_Get(void);//获取编码器测速值
#endif
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;
}
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);//清除标志位
}
}
文章来源:https://www.toymoban.com/news/detail-826107.html
到了这里,关于stm32下常用函数~中断定时器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!