MSP432自主开发笔记6:定时器多通道捕获多条编码器线脉冲数

所用开发板:MSP432P401R

今日在此更新一下编码器测速的定时器捕获写法,之前学习时竟然忘记更新了~~

本文讲如何用定时器的通道来 捕获编码器的脉冲信号数量,不提供速度路程的计算方式,

文章提供源码,测试工程下载;

实践内容:

1.使用定时器TA2捕获四个轮子编码器的信号

2.上升下降沿都捕获

3.串口定时反馈捕获值

程序编写:

程序设计方面十分简单,分为以下步骤,每个步骤有一些注意点:

一、初始化定时器:

            1.关闭定时溢出中断,开启捕获事件的中断

            2.选择合适的定时器频率,略高于编码器最大频率即可

            3.四个通道除了引脚不同,初始化基本一样,结构体名称改改就行

            4.设置为上升沿、下降沿、上升下降沿,三种捕获模式之一,(本文设置为上升下降都捕获    )

二、捕获事件中断服务函数:

            1.因为之前关闭了 定时溢出中断,所以void TA2_N_IRQHandler(void)的进入条件只有捕获事件到来时:(本文捕获事件为:上升下降都是捕获事件    ),就会进一次中断

             2.定时器配置捕获后,可以通过读取TAxIV寄存器来判断是哪个通道传来的捕获事件,借此对其计数。(本文是定时器2,因此读取TA2IV)

             3.     

 有关TAxIV寄存器介绍在801页MSP432自主开发笔记6:定时器多通道捕获多条编码器线脉冲数_第1张图片

 1.初始化定时器TA2四条通道的捕获:

注意点在之前说过了:

开启定时器计时,但关闭计时溢出中断

选择合适的计时溢出频率,这决定了捕获的采样率,比编码器脉冲频率快就行,当然,直接定时器48M也是没有问题的

四条通道初始化相同的

开启TA2端口中断     MAP_Interrupt_enableInterrupt(INT_TA2_N);

//定时器TA2捕获初始化:
void TA2_CAP_init(void)
{
	//四个通道初始化输入
		MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,GPIO_PIN6,GPIO_PRIMARY_MODULE_FUNCTION);	
		MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,GPIO_PIN7,GPIO_PRIMARY_MODULE_FUNCTION);	
		MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P6,GPIO_PIN6,GPIO_PRIMARY_MODULE_FUNCTION);	
		MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P6,GPIO_PIN7,GPIO_PRIMARY_MODULE_FUNCTION);	
	
	//定时器连续计数模式初始化,关闭定时溢出中断
			const Timer_A_ContinuousModeConfig continuousModeConfig =
		{
						TIMER_A_CLOCKSOURCE_SMCLK,
						TIMER_A_CLOCKSOURCE_DIVIDER_1,  //1分频,分辨率最高48M
						TIMER_A_TAIE_INTERRUPT_DISABLE, 
						TIMER_A_SKIP_CLEAR
		};
//初始化通道1:
				const Timer_A_CaptureModeConfig captureModeConfig_1 =
		{
						TIMER_A_CAPTURECOMPARE_REGISTER_1, 
						TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE,
						TIMER_A_CAPTURE_INPUTSELECT_CCIxA,
						TIMER_A_CAPTURE_SYNCHRONOUS,
						TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE,
						TIMER_A_OUTPUTMODE_OUTBITVALUE
		};
//初始化通道2:
				const Timer_A_CaptureModeConfig captureModeConfig_2 =
		{
						TIMER_A_CAPTURECOMPARE_REGISTER_2, 
						TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE,
						TIMER_A_CAPTURE_INPUTSELECT_CCIxA,
						TIMER_A_CAPTURE_SYNCHRONOUS,
						TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE,
						TIMER_A_OUTPUTMODE_OUTBITVALUE
		};
//初始化通道3:
				const Timer_A_CaptureModeConfig captureModeConfig_3 =
		{
						TIMER_A_CAPTURECOMPARE_REGISTER_3, 
						TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE,
						TIMER_A_CAPTURE_INPUTSELECT_CCIxA,
						TIMER_A_CAPTURE_SYNCHRONOUS,
						TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE,
						TIMER_A_OUTPUTMODE_OUTBITVALUE
		};
//初始化通道4:
				const Timer_A_CaptureModeConfig captureModeConfig_4 =
		{
						TIMER_A_CAPTURECOMPARE_REGISTER_4, 
						TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE,
						TIMER_A_CAPTURE_INPUTSELECT_CCIxA,
						TIMER_A_CAPTURE_SYNCHRONOUS,
						TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE,
						TIMER_A_OUTPUTMODE_OUTBITVALUE
		};		
		
		
	  MAP_Timer_A_initCapture(TIMER_A2_BASE, &captureModeConfig_1);
	  MAP_Timer_A_initCapture(TIMER_A2_BASE, &captureModeConfig_2);
	  MAP_Timer_A_initCapture(TIMER_A2_BASE, &captureModeConfig_3);
	  MAP_Timer_A_initCapture(TIMER_A2_BASE, &captureModeConfig_4);

    MAP_Timer_A_configureContinuousMode(TIMER_A2_BASE, &continuousModeConfig);
    MAP_Interrupt_enableInterrupt(INT_TA2_N);
    MAP_Timer_A_startCounter(TIMER_A2_BASE, TIMER_A_CONTINUOUS_MODE);
}

 2.编写定时器 中断服务函数:

代码中的 Wheel[x].CAPTURE 无须在意,是我给每个轮子定义的结构体,换成普通变量一样用的,这种高速计数脉冲,需要大家时刻注意溢出问题,以下代码段的意思就是防止数据溢出不被记录:

if(Wheel[1].CAPTURE==62700)
					{Wheel[1].CAPTURE=0;Wheel[1].CAT_OUT_TIME++;}

 


//这是捕获事件中断服务函数(因为定时器溢出中断已关闭)
//注意对照引脚看通道,这里通道情况与PWM控制不一样
void TA2_N_IRQHandler(void)
{
    uint16_t captureSource = TA2IV;
// 根据捕获通道来源进行适当的处理
//脉冲计数到62700时刚好车轮转95圈
//大电机减速比30编码器11线
    switch (captureSource) 
			{
        case 0x02:
            // 处理TA2 CCR1通道的捕获中断
						Wheel[1].CAPTURE++;
					if(Wheel[1].CAPTURE==62700)
					{Wheel[1].CAPTURE=0;Wheel[1].CAT_OUT_TIME++;}
            break;
        case 0x04:
            // 处理TA2 CCR2通道的捕获中断
						Wheel[2].CAPTURE++;
					if(Wheel[2].CAPTURE==62700)
					{Wheel[2].CAPTURE=0;Wheel[2].CAT_OUT_TIME++;}		
            break;
        case 0x06:
            // 处理TA2 CCR3通道的捕获中断
						Wheel[3].CAPTURE++;
					if(Wheel[3].CAPTURE==62700)
					{Wheel[3].CAPTURE=0;Wheel[3].CAT_OUT_TIME++;}					
            break;
        case 0x08:
            // 处理TA2 CCR4通道的捕获中断
						Wheel[4].CAPTURE++;
					if(Wheel[4].CAPTURE==62700)
					{Wheel[4].CAPTURE=0;Wheel[4].CAT_OUT_TIME++;}					
            break;
        default: break;	
}
}			

3.32定时器初始化为1s周期,通过串口反馈捕获情况:

//此句放在初始化,主函数开头,初始化32定时器为1s周期
 Tim32_0_Int_Init(47999999,1);


//32定时器初始化函数,传入的aar psc决定了其周期
void Tim32_0_Int_Init(uint32_t aar, uint8_t psc)
{
    MAP_Timer32_initModule(TIMER32_0_BASE, psc, TIMER32_32BIT, TIMER32_PERIODIC_MODE);
    MAP_Timer32_setCount(TIMER32_0_BASE, aar);
    MAP_Timer32_enableInterrupt(TIMER32_0_BASE);
    MAP_Timer32_startTimer(TIMER32_0_BASE, false); //连续计数模式 false
    MAP_Interrupt_enableInterrupt(INT_T32_INT1);
}




/* Timer32 ISR 中断服务函数,1s进一次*/
void T32_INT1_IRQHandler(void)
{
    MAP_Timer32_clearInterruptFlag(TIMER32_0_BASE);
		  printf("W1_CAP=%d\r\n",Wheel[1].CAPTURE);
			printf("W2_CAP=%d\r\n",Wheel[2].CAPTURE);
			printf("W3_CAP=%d\r\n",Wheel[3].CAPTURE);
			printf("W4_CAP=%d\r\n",Wheel[4].CAPTURE);
}

整体代码:

#include "main.h"

//单个车轮状态与参数结构体:
Wheel_dat Wheel[5];


int main(void)
{
	  inint_all();   //初始化所有模块
    while (1)
    {  }
}

/* Timer32 ISR */
void T32_INT1_IRQHandler(void)
{
    MAP_Timer32_clearInterruptFlag(TIMER32_0_BASE);
		  printf("W1_CAP=%d\r\n",Wheel[1].CAPTURE);
			printf("W2_CAP=%d\r\n",Wheel[2].CAPTURE);
			printf("W3_CAP=%d\r\n",Wheel[3].CAPTURE);
			printf("W4_CAP=%d\r\n",Wheel[4].CAPTURE);
}


//初始化所有模块
void inint_all(void)
{
    SysInit();                                  //时钟配置    
    delay_init();								 								//delay_ms函数配置
		uart_init(115200);	
	  TA2_CAP_init();
	  Tim32_0_Int_Init(47999999,1);
	  printf("Hello,MSP432!\r\n");								//串口打印测试字符
		MAP_Interrupt_enableMaster();               // 开启总中断
}


//串口0服务函数
//串口0接收命令,存在数组中
void EUSCIA0_IRQHandler(void)
{
	uint32_t status = UART_getEnabledInterruptStatus(EUSCI_A0_BASE);
	if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG)      //接收中断
	{
		USART0_save[USART0_xb++]=MAP_UART_receiveData(EUSCI_A0_BASE);
		if(USART0_xb== 20){USART0_xb=0;	}							      //下标最大不超过20
		if(USART0_save[USART0_xb-1]=='\0'){USART0_flag=1;}  //命令以\0结尾
	}
}


//这是捕获事件中断服务函数(因为定时器溢出中断已关闭)
//注意对照引脚看通道,这里通道情况与PWM控制不一样
void TA2_N_IRQHandler(void)
{
    uint16_t captureSource = TA2IV;
// 根据捕获通道来源进行适当的处理
//脉冲计数到62700时刚好车轮转95圈
//大电机减速比30编码器11线
    switch (captureSource) 
			{
        case 0x02:
            // 处理TA2 CCR1通道的捕获中断
						Wheel[1].CAPTURE++;
					if(Wheel[1].CAPTURE==62700)
					{Wheel[1].CAPTURE=0;Wheel[1].CAT_OUT_TIME++;}
            break;
        case 0x04:
            // 处理TA2 CCR2通道的捕获中断
						Wheel[2].CAPTURE++;
					if(Wheel[2].CAPTURE==62700)
					{Wheel[2].CAPTURE=0;Wheel[2].CAT_OUT_TIME++;}		
            break;
        case 0x06:
            // 处理TA2 CCR3通道的捕获中断
						Wheel[3].CAPTURE++;
					if(Wheel[3].CAPTURE==62700)
					{Wheel[3].CAPTURE=0;Wheel[3].CAT_OUT_TIME++;}					
            break;
        case 0x08:
            // 处理TA2 CCR4通道的捕获中断
						Wheel[4].CAPTURE++;
					if(Wheel[4].CAPTURE==62700)
					{Wheel[4].CAPTURE=0;Wheel[4].CAT_OUT_TIME++;}					
            break;
        default: break;	
}
}			


//定时器TA2捕获初始化:
void TA2_CAP_init(void)
{
	//四个通道初始化输入
		MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,GPIO_PIN6,GPIO_PRIMARY_MODULE_FUNCTION);	
		MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,GPIO_PIN7,GPIO_PRIMARY_MODULE_FUNCTION);	
		MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P6,GPIO_PIN6,GPIO_PRIMARY_MODULE_FUNCTION);	
		MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P6,GPIO_PIN7,GPIO_PRIMARY_MODULE_FUNCTION);	
	
	//定时器连续计数模式初始化,关闭定时溢出中断
			const Timer_A_ContinuousModeConfig continuousModeConfig =
		{
						TIMER_A_CLOCKSOURCE_SMCLK,
						TIMER_A_CLOCKSOURCE_DIVIDER_1,  //1分频,分辨率最高48M
						TIMER_A_TAIE_INTERRUPT_DISABLE, 
						TIMER_A_SKIP_CLEAR
		};
//初始化通道1:
				const Timer_A_CaptureModeConfig captureModeConfig_1 =
		{
						TIMER_A_CAPTURECOMPARE_REGISTER_1, 
						TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE,
						TIMER_A_CAPTURE_INPUTSELECT_CCIxA,
						TIMER_A_CAPTURE_SYNCHRONOUS,
						TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE,
						TIMER_A_OUTPUTMODE_OUTBITVALUE
		};
//初始化通道2:
				const Timer_A_CaptureModeConfig captureModeConfig_2 =
		{
						TIMER_A_CAPTURECOMPARE_REGISTER_2, 
						TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE,
						TIMER_A_CAPTURE_INPUTSELECT_CCIxA,
						TIMER_A_CAPTURE_SYNCHRONOUS,
						TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE,
						TIMER_A_OUTPUTMODE_OUTBITVALUE
		};
//初始化通道3:
				const Timer_A_CaptureModeConfig captureModeConfig_3 =
		{
						TIMER_A_CAPTURECOMPARE_REGISTER_3, 
						TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE,
						TIMER_A_CAPTURE_INPUTSELECT_CCIxA,
						TIMER_A_CAPTURE_SYNCHRONOUS,
						TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE,
						TIMER_A_OUTPUTMODE_OUTBITVALUE
		};
//初始化通道4:
				const Timer_A_CaptureModeConfig captureModeConfig_4 =
		{
						TIMER_A_CAPTURECOMPARE_REGISTER_4, 
						TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE,
						TIMER_A_CAPTURE_INPUTSELECT_CCIxA,
						TIMER_A_CAPTURE_SYNCHRONOUS,
						TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE,
						TIMER_A_OUTPUTMODE_OUTBITVALUE
		};		
		
		
	  MAP_Timer_A_initCapture(TIMER_A2_BASE, &captureModeConfig_1);
	  MAP_Timer_A_initCapture(TIMER_A2_BASE, &captureModeConfig_2);
	  MAP_Timer_A_initCapture(TIMER_A2_BASE, &captureModeConfig_3);
	  MAP_Timer_A_initCapture(TIMER_A2_BASE, &captureModeConfig_4);

    MAP_Timer_A_configureContinuousMode(TIMER_A2_BASE, &continuousModeConfig);
    MAP_Interrupt_enableInterrupt(INT_TA2_N);
    MAP_Timer_A_startCounter(TIMER_A2_BASE, TIMER_A_CONTINUOUS_MODE);
}

#ifndef _main_h_
#define _main_h_

#include 
#include "string.h"				   	//C标准库、字符串处理库
#include "sysinit.h"			   	//时钟配置
#include "delay.h"				   	//滴答定时器初始化(提供delay_ms延时)
#include "Public.h"
#include "DATA.h"

//单个车轮状态与参数结构体:
typedef struct wheel_data
{
	uint16_t Sta;            //正反转状态,0不转,2正,1反
	uint16_t PWM_DIV;        //车轮电机占空比6 - 99
  uint32_t CAT_OUT_TIME;   //编码器 脉冲溢出次数,溢出一次就加一,记录有几个65530
  uint32_t CAPTURE;        //编码器 外部中断次数记录最大65530次脉冲,溢出后CAT_OUT_TIME会加一,CAPTURE归零
	uint32_t CAPTURE_LAST;   //上一次外部中断次数记录
  uint32_t CAPTURE_NEW;    //最新外部中断次数记录
	uint32_t DISTANCE;       //单轮行驶总路程长度单位cm,最大65535cm
  uint32_t SPEED;          //瞬时速度值存储,单位cm/s
}Wheel_dat;


void inint_all(void);               //初始化所有模块
//定时器TA2捕获初始化:
void TA2_CAP_init(void);

#endif

 测试工程下载:

https://download.csdn.net/download/qq_64257614/88214201?spm=1001.2014.3001.5503

你可能感兴趣的:(MSP432学习笔记,笔记,嵌入式硬件,单片机)