stm32f407定时器2的编码器功能测轮子的圈数

1、用定时器的PA15和PB3;因此需要复用引脚;默认是PA0和PA1作为定时器2的引脚。
2、用到的资源是
定时器2的PA15和PB3,作为T2ch1和T2CH2引脚,作为AB相输入;
定时器8定时一段时间,读取编码器数值,得到圈数和方向。
中断NVIC配置:定时器2的中断,定时器8的中断。
3、代码(这里只是测试编码器1的定时器2,其他的还没配置好。)
3.1

ENCODER.h

#ifndef __ENCODER_H
#define __ENCODER_H


#include "stdio.h"	
#include "stm32f4xx_conf.h"
#include "sys.h" 

#define ENCODER_LINE    1024.0f  
//一圈30个码盘,编码器线260,转一圈260个脉冲,4倍频1040,分辨率是0.35度。
#define MAX_DELTA_50HZ  200    //50hz===1/50=0.02s=20ms,20ms读取一次

#define COUNTER_PERIOD  65535  //计数最大值
#define MAX_CIRCLES     1.0e5f  //1*10e5最大的圈数

//************************编码器1,定时器T2的PA15,PB3--------------------------------P2
#define ENCODER10_PIN            GPIO_Pin_15     		    // LED1 引脚      
#define ENCODER10_PORT           GPIOA                 // LED1 GPIO端口     
#define ENCODER10_CLK            RCC_AHB1Periph_GPIOA  // LED1 GPIO端口时钟_
#define ENCODER10_CLK_ENABLE()   {RCC_AHB1PeriphClockCmd(ENCODER10_CLK,ENABLE);} //使能GPIOA时钟
#define ENCODER10_PINSOURCE       GPIO_PinSource15

#define ENCODER11_PIN            GPIO_Pin_3     		    // LED1 引脚      
#define ENCODER11_PORT           GPIOB                 // LED1 GPIO端口     
#define ENCODER11_CLK            RCC_AHB1Periph_GPIOB  // LED1 GPIO端口时钟_
#define ENCODER11_CLK_ENABLE()   {RCC_AHB1PeriphClockCmd(ENCODER11_CLK,ENABLE);} //使能GPIOB时钟
#define ENCODER11_PINSOURCE       GPIO_PinSource3

//************************编码器2,定时器T3的B4---B5
#define ENCODER20_PIN            GPIO_Pin_4    		    // LED1 引脚      
#define ENCODER20_PORT           GPIOB                // LED1 GPIO端口     
#define ENCODER20_CLK            RCC_AHB1Periph_GPIOB  // LED1 GPIO端口时钟_
#define ENCODER20_CLK_ENABLE()   {RCC_AHB1PeriphClockCmd(ENCODER20_CLK,ENABLE);} //使能GPIOA时钟

#define ENCODER21_PIN            GPIO_Pin_5     		    // LED1 引脚      
#define ENCODER21_PORT           GPIOB                 // LED1 GPIO端口     
#define ENCODER21_CLK            RCC_AHB1Periph_GPIOB  // LED1 GPIO端口时钟_
#define ENCODER21_CLK_ENABLE()   {RCC_AHB1PeriphClockCmd(ENCODER21_CLK,ENABLE);} //使能GPIOB时钟
//************************编码器3,定时器T4的B6---B7
#define ENCODER30_PIN            GPIO_Pin_6    		    // LED1 引脚      
#define ENCODER30_PORT           GPIOB                // LED1 GPIO端口     
#define ENCODER30_CLK            RCC_AHB1Periph_GPIOB  // LED1 GPIO端口时钟_
#define ENCODER30_CLK_ENABLE()   {RCC_AHB1PeriphClockCmd(ENCODER30_CLK,ENABLE);} //使能GPIOA时钟

#define ENCODER31_PIN            GPIO_Pin_7     		    // LED1 引脚      
#define ENCODER31_PORT           GPIOB                 // LED1 GPIO端口     
#define ENCODER31_CLK            RCC_AHB1Periph_GPIOB  // LED1 GPIO端口时钟_
#define ENCODER31_CLK_ENABLE()   {RCC_AHB1PeriphClockCmd(ENCODER31_CLK,ENABLE);} //使能GPIOB时钟

//************************编码器4,定时器T5的A0---A1
#define ENCODER40_PIN            GPIO_Pin_0   		    // LED1 引脚      
#define ENCODER40_PORT           GPIOA                // LED1 GPIO端口     
#define ENCODER40_CLK            RCC_AHB1Periph_GPIOA  // LED1 GPIO端口时钟_
#define ENCODER40_CLK_ENABLE()   {RCC_AHB1PeriphClockCmd(ENCODER40_CLK,ENABLE);} //使能GPIOA时钟

#define ENCODER41_PIN            GPIO_Pin_1     		    // LED1 引脚      
#define ENCODER41_PORT           GPIOA                 // LED1 GPIO端口     
#define ENCODER41_CLK            RCC_AHB1Periph_GPIOA  // LED1 GPIO端口时钟_
#define ENCODER41_CLK_ENABLE()   {RCC_AHB1PeriphClockCmd(ENCODER41_CLK,ENABLE);} //使能GPIOB时钟

//----------------------------------------也可以用typedef创建新类型
typedef struct   //编码器的结构体,
{
    
    
  float   circles;//圈数
  int8_t   direct;  //方向
}encoder;

extern encoder encoder_obj00;


void Encoder1_Init_TIM2(void);//PA15+PB3
void Encoder2_Init_TIM3(void);//
void Encoder3_Init_TIM4(void);//
void Encoder4_Init_TIM5(void);//

void update_encoder(void);  //更新编码器
void get_direct(unsigned char who0,encoder *encoder_obj);//获取编码器的方向
void get_circles(unsigned char who0,encoder *encoder_obj);//获取编码器的圈数

#endif

//2、速度的常用单位
//(1) m/s 表示“米每秒”,是线速度单位;
//(2) rpm 表示“转每分”,是转数单位;
//(3) rad/s 表示“弧度每秒”,是转速单位。
//做速度换算一定要注意“单位”(也叫“量纲”),有单位的数据才是有意义的,不然都是瞎算。

//3、马达转数与轮子的转数
//相差一个减速箱的“减速比”。

//4、轮子的转速与轮子的线速度
//线速度 = 转速(角速度)* 轮子半径

3.2 ENCODER.c

#include <stdlib.h>
#include "encoder.h"
#include "usart.h"
#include "stm32f4xx.h"
#include "sys.h" //位操作

encoder  encoder_obj00;

static int32_t encoder_cnt[4];
static int32_t last_cnt[4];
static int32_t  delta_cnt[4];
static int8_t   direct[4];
static float   circles[4];

void update_delta(void);


/**************************************************************************
函数功能:把TIM2初始化为编码器接口模式
入口参数:无
返回  值:无
**************************************************************************/
//用定时8--------------------定时ms,读取数值

void Encoder1_Init_TIM2(void)//PA15+PB3
{
    
    
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
  TIM_OCInitTypeDef  TIM_OCInitStructure;//定时器OC结构体
	TIM_ICInitTypeDef TIM_ICInitStructure;//定时器编码滤波结构体

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);  ///使能TIM2时钟
	
	GPIO_PinAFConfig(ENCODER10_PORT,ENCODER10_PINSOURCE,GPIO_AF_TIM2); //复用为定时器2
  GPIO_PinAFConfig(ENCODER11_PORT,ENCODER11_PINSOURCE,GPIO_AF_TIM2); //复用为定时器2
	
	ENCODER10_CLK_ENABLE();//使能PORTA时钟
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;   //输入模式
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP ;	// //输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度选择
	 GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
	GPIO_InitStructure.GPIO_Pin   = ENCODER10_PIN;	 
	GPIO_Init(ENCODER10_PORT, &GPIO_InitStructure);	
	
	ENCODER11_CLK_ENABLE();//使能PORTB时钟------------------
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;   //输入模式
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP ;	// //浮空输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度选择
	 GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
	GPIO_InitStructure.GPIO_Pin   = ENCODER11_PIN;//---------------	 
	GPIO_Init(ENCODER11_PORT, &GPIO_InitStructure);	//----------------

	TIM_TimeBaseInitStructure.TIM_Period = COUNTER_PERIOD-1;  //????
	TIM_TimeBaseInitStructure.TIM_Prescaler=0x0;  //???
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //????
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //????
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//???TIM3
		
//	/* 把定时器初始化为编码器模式 和相应的捕获设置 TIM_ICPolarity_Rising */ 
	 TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
	 TIM_ICStructInit(&TIM_ICInitStructure); 
   TIM_ICInitStructure.TIM_ICFilter = 10;//滤波值
   TIM_ICInit(TIM2, &TIM_ICInitStructure);
	 
	 TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除TIM的更新标志位
   TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	 TIM_SetCounter(TIM2,0); //TIM2->CNT=0
	 TIM_Cmd(TIM2, ENABLE);
}


void Encoder2_Init_TIM3(void)//PA15+PB3
{
    
    
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	  GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);  ///使能TIM3时钟

	ENCODER20_CLK_ENABLE();//使能PORTA时钟
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;   //输入模式
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;	// //浮空输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度选择
	GPIO_InitStructure.GPIO_Pin   = ENCODER20_PIN;	 
	GPIO_Init(ENCODER20_PORT, &GPIO_InitStructure);	
	
	ENCODER21_CLK_ENABLE();//使能PORTB时钟
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;   //输入模式
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;	// //浮空输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度选择
	GPIO_InitStructure.GPIO_Pin   = ENCODER21_PIN;	 
	GPIO_Init(ENCODER21_PORT, &GPIO_InitStructure);	
  
	/* 把定时器初始化为编码器模式 */ 
	TIM3->PSC = 0x0;//预分频器
	TIM3->ARR = COUNTER_PERIOD-1;//设定计数器自动重装值 
  TIM3->CCMR1 |= 1<<0;          //输入模式,IC1FP1映射到TI1上
  TIM3->CCMR1 |= 1<<8;          //输入模式,IC2FP2映射到TI2上
  TIM3->CCER |= 0<<1;           //IC1不反向
  TIM3->CCER |= 0<<5;           //IC2不反向
	TIM3->SMCR |= 3<<0;	          //SMS='011' 所有的输入均在上升沿和下降沿有效
	TIM3->CR1 |= 0x01;          //CEN=1,使能定时器
	
}

void Encoder3_Init_TIM4(void)//PA15+PB3
{
    
    
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);  ///使能TIM4时钟

	ENCODER30_CLK_ENABLE();//使能PORTA时钟
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;   //输入模式
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;	// //浮空输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度选择
	GPIO_InitStructure.GPIO_Pin   = ENCODER30_PIN;	 
	GPIO_Init(ENCODER30_PORT, &GPIO_InitStructure);	
	
	ENCODER31_CLK_ENABLE();//使能PORTB时钟
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;   //输入模式
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;	// //浮空输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度选择
	GPIO_InitStructure.GPIO_Pin   = ENCODER31_PIN;	 
	GPIO_Init(ENCODER31_PORT, &GPIO_InitStructure);	
  
	/* 把定时器初始化为编码器模式 */ 
	TIM4->PSC = 0x0;//预分频器
	TIM4->ARR = COUNTER_PERIOD-1;//设定计数器自动重装值 
  TIM4->CCMR1 |= 1<<0;          //输入模式,IC1FP1映射到TI1上
  TIM4->CCMR1 |= 1<<8;          //输入模式,IC2FP2映射到TI2上
  TIM4->CCER |= 0<<1;           //IC1不反向
  TIM4->CCER |= 0<<5;           //IC2不反向
	TIM4->SMCR |= 3<<0;	          //SMS='011' 所有的输入均在上升沿和下降沿有效
	TIM4->CR1 |= 0x01;          //CEN=1,使能定时器
	
}


void Encoder4_Init_TIM5(void)//PA15+PB3
{
    
    
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);  ///使能TIM4时钟

	ENCODER40_CLK_ENABLE();//使能PORTA时钟
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;   //输入模式
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;	// //浮空输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度选择
	GPIO_InitStructure.GPIO_Pin   = ENCODER40_PIN;	 
	GPIO_Init(ENCODER40_PORT, &GPIO_InitStructure);	
	
	ENCODER41_CLK_ENABLE();//使能PORTB时钟
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;   //输入模式
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;	// //浮空输入
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度选择
	GPIO_InitStructure.GPIO_Pin   = ENCODER41_PIN;	 
	GPIO_Init(ENCODER41_PORT, &GPIO_InitStructure);	
  
	/* 把定时器初始化为编码器模式 */ 
	TIM5->PSC = 0x0;//预分频器
	TIM5->ARR = COUNTER_PERIOD-1;//设定计数器自动重装值 
  TIM5->CCMR1 |= 1<<0;          //输入模式,IC1FP1映射到TI1上
  TIM5->CCMR1 |= 1<<8;          //输入模式,IC2FP2映射到TI2上
  TIM5->CCER |= 0<<1;           //IC1不反向
  TIM5->CCER |= 0<<5;           //IC2不反向
	TIM5->SMCR |= 3<<0;	          //SMS='011' 所有的输入均在上升沿和下降沿有效
	TIM5->CR1 |= 0x01;          //CEN=1,使能定时器
}
// 50Hz update,20ms读取一次编码数值
void update_encoder(void)
{
    
    
  encoder_cnt[0] = (uint32_t)(TIM2 -> CNT);
//  encoder_cnt[1] = (uint32_t)(TIM3 -> CNT);
//  encoder_cnt[2] = (uint32_t)(TIM4 -> CNT);
//  encoder_cnt[3] = (uint32_t)(TIM5 -> CNT);

  update_delta();//得到方向和圈数
}



//----------------------------------------------------------------50Hz update
void update_delta(void)
{
    
    
  uint8_t i;

  for(i=0; i<1; i++) 
	{
    
    
    delta_cnt[i] = encoder_cnt[i] - last_cnt[i];

    if(abs(delta_cnt[i]) >= MAX_DELTA_50HZ) 
			{
    
    
				u32 temp;
				if(delta_cnt[i] > 0) 
					{
    
    
						temp = COUNTER_PERIOD - encoder_cnt[i];
						delta_cnt[i] = -(last_cnt[i] + temp);
					} 
					else 
					{
    
    
						temp = COUNTER_PERIOD - last_cnt[i];
						delta_cnt[i] = encoder_cnt[i] + temp;
					}
			}

    last_cnt[i]  = encoder_cnt[i];

    if(delta_cnt[i] == 0) {
    
    
      direct[i] = 0;
    } else if(delta_cnt[i] > 0) {
    
    
      direct[i] = 1;
    } else {
    
    
      direct[i] = -1;
    }
    
    circles[i] += delta_cnt[i]/ENCODER_LINE;//编码总数值/编码线数===圈数260
		
    if(circles[i] > MAX_CIRCLES){
    
    
      circles[i] = 0.0f;
    }
    if(circles[i] < 0.0f){
    
    
      circles[i] = MAX_CIRCLES;
    }
    
  }
}

//----------------------------------------------------------------------------------------
void get_circles(unsigned char who0,  encoder *encoder_obj)
{
    
    
    switch(who0) 
			{
    
    
					case 0: {
    
    
						encoder_obj->circles = circles[0];
						break;
					}
					case 1: {
    
    
						encoder_obj->circles = circles[1];
						break;
					}
					case 2: {
    
    
						encoder_obj->circles = circles[2];
						break;
					}
					case 3: {
    
    
						encoder_obj->circles = circles[3];
						break;
					}
					default: {
    
    
						encoder_obj->circles = 0;
						break;
					}
    }
  
}

void  get_direct(unsigned char who0,encoder *encoder_obj)
{
    
    
    switch(who0) 
			{
    
    
					case 0: {
    
    
						encoder_obj->direct = direct[0];
						break;
					}
					case 1: {
    
    
						encoder_obj->direct = direct[1];
						break;
					}
					case 2: {
    
    
						encoder_obj->direct = direct[2];
						break;
					}
					case 3: {
    
    
						encoder_obj->direct = direct[3];
						break;
					}
					default: {
    
    
						encoder_obj->direct = 0;
						break;
					}
    }
 
}


3.3定时器8的程序

timer.h

#ifndef _TIMER_H
#define _TIMER_H
#include "sys.h"
//	 
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32F407开发板
//定时器 驱动代码	   
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2014/6/16
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved									  
// 	
extern u8 Uart1CmdSendFlag;
extern u8 countTIM3flag;


void TIM3_Int_Init(u16 arr,u16 psc);
void TIM8_Int_Init(u16 arr,u16 psc);
#endif

timer.c主要看定时器8的初始化和中断

#include "timer.h"
#include "led.h"
#include "usart.h"
#include "encoder.h"

extern u16 ptt;
u8 Uart1CmdSendFlag=1;
u8 countTIM3flag=0;//监控的时间到了,就=1
//通用定时器3中断初始化
//arr:自动重装值。
//psc:时钟预分频数
//定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定时器工作频率,单位:Mhz
//这里使用的是定时器3!
//
void TIM3_Int_Init(u16 arr,u16 psc)
{
    
    
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);  ///使能TIM3时钟
	
  TIM_TimeBaseInitStructure.TIM_Period = arr; 	//自动重装载值
	TIM_TimeBaseInitStructure.TIM_Prescaler=psc;  //定时器分频
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
	
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//初始化TIM3
	
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允许定时器3更新中断
	TIM_Cmd(TIM3,DISABLE); //使能定时器3	
}

/*
	@定时器8:定时20ms,50HZ,读取编码器数据,并处理得到
	//注意,定时器1用APB2时钟线

*/
void TIM8_Int_Init(u16 arr,u16 psc)
{
    
    
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8,ENABLE);  	//=====TIM8时钟使能 	

  TIM_TimeBaseInitStructure.TIM_Period = arr; 	//自动重装载值
	TIM_TimeBaseInitStructure.TIM_Prescaler=psc;  //定时器分频
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;// 重复计数器的值,没用到不用管
	TIM_TimeBaseInit(TIM8,&TIM_TimeBaseInitStructure);//初始化TIM8
	
	TIM_ITConfig(TIM8,TIM_IT_Update,ENABLE); //允许定时器8更新中断  
  TIM_ClearFlag(TIM8,TIM_FLAG_Update);
	TIM_Cmd(TIM8,DISABLE); //定时器8
	
  //确定定时器8的中断优先级,在NVIC.c中定义
}

//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
    
    
	static u8 counttim3=0;
	
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
	{
    
    
		if(counttim3<50)//小于50ms
		{
    
     	
			counttim3++;
			countTIM3flag=0;//小于50ms这个标记=0;
			if(UART1_OK_Flag==1)//在串口1中断的功能判别里面进行=1,改变
			{
    
    
				Uart1CmdSendFlag=0;//接收到,不再发送
				TIM_Cmd(TIM3,DISABLE);//关闭	
			}
			else
			  Uart1CmdSendFlag=1;//
		}
		
		//30ms内判断,有没有接收到二维码的ok信息
		//超过了30ms,没有接受到ok信息,那么就继续发送命令,
		else 
		{
    
    
			countTIM3flag=1;//超出30ms,就标记=1
			counttim3=0;
//			LED1=!LED1;
			if(UART1_OK_Flag==1)//在串口1中断的功能判别里面进行=1,改变
			{
    
    
				Uart1CmdSendFlag=0;//接收到,不再发送
				TIM_Cmd(TIM3,DISABLE);//关闭	
			}
			else
			  Uart1CmdSendFlag=1;//
				
		}
	}
	TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清除中断标志位
}


//*************************************************
//定时器8中断服务函TIM8_UP_TIM13_IRQHandler

void TIM8_UP_TIM13_IRQHandler(void)
{
    
    
	
  if (TIM_GetITStatus(TIM8, TIM_IT_Update) != RESET)
    {
    
      
	
				
      TIM_ClearITPendingBit(TIM8, TIM_IT_Update);
       //  LED1=!LED1;
			update_encoder();
			get_circles(0,&encoder_obj00);//extern encoder encoder_obj00;
	  	get_direct(0,&encoder_obj00);	//TIM2 -> CNT
			printf("%.2f,%d\r\n",encoder_obj00.circles,encoder_obj00.direct);
		  //printf("%.2f,%d\r\n",5.25,TIM2 -> CNT);
//		 	
//			
    } 
		  

}

/**********************************************************************/
//定时器2 溢出中断服务函数
void TIM2_IRQHandler(void)
{
    
       
    if(TIM2->SR&0x0001)//????
    {
    
    
      
    }   
    TIM2->SR&=~(1<<0);//???????     
}

3.5NVIC的程序,主要看定时器2和定时器8的中断配置

NVIC.h

#ifndef __NVIC_H
#define __NVIC_H

#include "stm32f4xx.h"
#include "sys.h"

void NVIC_Config(void);

#endif //__LED_H


NVIC.c


#include "NVIC.h"  
#include "usart.h"
// 函数:LED IO口初始化
//
void NVIC_Config(void)
{
    
    		
	NVIC_InitTypeDef    NVIC_InitStructure; 
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组 2,,,2:2

	/**——————————————按键中断优先级设置----------------*/
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//外部中断 0 
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//抢占优先级 0 
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//响应优先级 2 
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道 
  NVIC_Init(&NVIC_InitStructure);//配置 NVIC 
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;//外部中断 0 
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//抢占优先级 0 
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//响应优先级 2 
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道 
  NVIC_Init(&NVIC_InitStructure);//配置 NVIC 
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;//外部中断 0 
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//抢占优先级 0 
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//响应优先级 2 
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道 
  NVIC_Init(&NVIC_InitStructure);//配置 NVIC 
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;//外部中断 0 
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//抢占优先级 0 
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//响应优先级 2 
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道 
  NVIC_Init(&NVIC_InitStructure);//配置 NVIC 
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;//外部中断 0 
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//抢占优先级 0 
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;//响应优先级 2 
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断通道 
  NVIC_Init(&NVIC_InitStructure);//配置 NVIC 
	/**——————————————按键中断优先级设置----------------*/
	
	
		
	#if EN_USART1_RX	//如果用中断接收的话,就进行中断管理
	
		USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断
		//Usart1 NVIC 配置
		NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道
		NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//抢占优先级3
		NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;		//子优先级3
		NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
		NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器、

	#endif
		//定时器2中断配置

		NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn; 
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; 
    NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x01; 
    NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
    NVIC_Init(&NVIC_InitStructure);
		
	//定时器3中断配置
	NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定时器3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; //抢占优先级1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);
//	
//		//定时器8中断配置
	NVIC_InitStructure.NVIC_IRQChannel=TIM8_UP_TIM13_IRQn; //定时器8更新中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x00; //抢占优先级0
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x01; //子优先级01
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);

}


主函数------------mainc.c

/*
实验室217-2学习代码,希望感兴趣的同学,循序渐进完成。
理解代码,测试代码,修改代码,然后自己完成新的代码;
*/
#include "stm32f4xx.h"
#include "sys.h" //位操作
#include "delay.h"//反客科技提供
#include "delayzd.h"//正点原子提供
#include "led.h"   
#include "beep.h"   
#include "key.h" //独立按键中断------- 
#include "NVIC.h"  
#include "usart.h"  
#include "Lcd_Driver.h"//LCD 显示屏
#include "motor.h"  //电机操作
#include "pwm.h"//PWM
#include "tracksensor.h" //循迹模块传感器
#include "timer.h" //定时器3监控串口
#include "encoder.h" //定时器3监控串口

//***************************************引用按键
//定义全局变量
u16 ptt=0;

u8 task_flag=0; //任务标签0-255
//
//*****************************函数声明,后面定义
//第一个测试:LED测试
void test1();
//第2个测试:蜂鸣器测试
void test2();
//第2个测试:蜂鸣器测试
void test3();
//*****************************************************************************************************
//
//
int main(void)
{
    
    	
	u16 t=0;
	u8 checktemp0=0;
	
  Delay_Init();		//延时函数初始化
  delay_init(168);
	
	LED_Init();			   //LED初始化
	BEEP_Init();
	KEY_INT_Init();
	Delay_ms(10);
	
	uart1_init(115200);
	Delay_ms(10);
	
	MotorInit(8000);//8000HZ
	Tracksensor_Init();//

	//定时器时钟 84M,分频系数 8400,所以 84M/8400=10Khz 
//频率是10Khz----那么计算的时钟基准是1/10k=10e-4s=10
//的计数频率,计数 5000 次为 500ms,我们需要是1ms,那么是50 
	//5000次,是500ms,每次是0.1ms=100us
	//TIM3_Int_Init(50-1,8400-1);//定时器3定时1ms,定时100ms,在100ms内检测功能标记是不是等于1
  
	//200+4200----5ms进入一次中断
	//如果200+8400,那么20ms周期,10ms进入一次中断
	TIM8_Int_Init(200-1,8400-1);	//2000+8400   f=5hz----T=0.2s===200ms.

	Lcd_Init();//初始化函数
  Lcd_Clear(WHITE);//清屏,颜色
	
  LED1=1;
	delay_ms(500);
	LED1=0;
	delay_ms(500);
		
	LED1=1;
	delay_ms(500);
	LED1=0;
	delay_ms(500);
		
  LED1=1;
	delay_ms(500);
	LED1=0;
	delay_ms(500);
  Encoder1_Init_TIM2();


	NVIC_Config();
	delay_ms(100);
	
	//初始化:二维码显示屏幕显示++++数据
	//LCD_ShowStringQRcode96(0,0,RED,WHITE,"++++++");		
	//LCD_ShowStringQRcode96(0,0,RED,WHITE,"312+231");	
//	LCD_ShowCharAsc96(0,0,RED,WHITE,'+');//1	
//	LCD_ShowCharAsc96(48,0,RED,WHITE,'+');//2
//	LCD_ShowCharAsc96(96,0,RED,WHITE,'+');//3
//	LCD_ShowCharAsc96(144,0,RED,WHITE,'+');//+	
//	LCD_ShowCharAsc96(0,100,RED,WHITE,'+');//3		
//	LCD_ShowCharAsc96(48,100,RED,WHITE,'+');//2		
//	LCD_ShowCharAsc96(96,100,RED,WHITE,'+');//1
//	Delay_ms(100);

		encoder_obj00.circles=0;
		encoder_obj00.direct=0;
	
	TIM_Cmd(TIM8,ENABLE); //使能定时器8
	while (1)
	{
    
    
			
		
	}

	
}



猜你喜欢

转载自blog.csdn.net/lmf666/article/details/112287495