MSP432学习笔记9:定时器A-----捕获

今日得以继续我的MSP432电赛速通之旅~~~

目录

基础知识:

相关库函数:

一般配置步骤:

首先定义一个初始化函数:

1.复用引脚:

2.配置连续计数结构体:

3.初始化定时器连续计数:

4.配置捕获结构体:

5.初始化定时器为捕获:

6.选择模式开始计数:

7.清除中断标志位:

8.开启定时器端口中断:

9.开启总中断:

10.编写 TIMA ISR:

11.主函数捕获的编写:

硬件电路的连接:

实验结果:


基础知识:

MSP432捕获模式是一种可编程的寄存器配置,

在此模式下,MSP432可以在外部事件确切发生的瞬时刻捕获一个定时器的值。

捕获模式可以用于许多应用,例如测量某个事件的时间间隔或周期,

以及检测输入脉冲的上升边、下降边或两种边缘的时间。

在MSP432上,捕获模式与定时器结合使用。

MSP432中的每个定时器都有多个捕获/比较通道可以使用,

每个通道可以独立配置为捕获模式。

在捕获模式下,每个通道可以在定时器上的不同时间点捕获一个定时器的值。

并将其存储在一个捕获寄存器中。

在定时器捕获中,我们只需关心连续计数模式就好了:

MSP432学习笔记9:定时器A-----捕获_第1张图片

连续计数模式就是从零开始计数

直到65535,然后又从0开始计数,如此往复循环。

此处先列出定时器与通道对应引脚

MSP432学习笔记9:定时器A-----捕获_第2张图片

相关库函数:

以下1~7,都定义在库 timer_a.h中:

1.初始化定时器为连续计数模式:

Timer_A_configureContinuousMode(TIMER_Ax,&continuousModeConfig);

2.配置定时器的捕获模式:

Timer_A_initCapture(TIMER_Ax_BASE,&captureModeConfig);

3.选择模式开始计数:

Timer_A_startCounter(TIMER_Ax_BASE,TIMER_A_CONTINUOUS_MODE);

第一个参数选择定时器 ,第二个参数可选择填写以下模式之一:

1. TIMER_A_STOP_MODE

(TIMER_A_CTL_MC_0)`: 停止模式,计时器A停止计数并保持其当前值。

2. TIMER_A_UP_MODE

(TIMER_A_CTL_MC_1)`: 单向上计数模式,计时器A从0开始递增计数,当计数值达到最大值(根据配置而定)时,计时器将重新从0开始。

3. TIMER_A_CONTINUOUS_MODE

(TIMER_A_CTL_MC_2)`: 连续模式,计时器A从0开始递增计数,当计数值达到最大值(根据配置而定)时,计时器将自动重新从0开始。

4. TIMER_A_UPDOWN_MODE

(TIMER_A_CTL_MC_3)`: 上下计数模式,计时器A从0开始递增计数,当计数值达到最大值(根据配置而定)时,计时器将自动切换为递减模式,直到计数值回到0。这个模式可以用来产生周期性的波形。

通过选择适当的工作模式,可以根据应用的需求来配置计时器A的行为。

4.清除定时器溢出中断标志位:

Timer_A_clearInterruptFlag(TIMER_Ax_BASE);

5.清除定时器捕获中断标志位:

Timer_A_clearCaptureCompareInterrupt(TIMER_Ax,REGISTER_N);

6.获取定时器溢出中断状态:

Timer_A_getEnabledInterruptStatus(TIMER_Ax_BASE);

7.获取定时器捕获中断状态:

Timer_A_getCaptureCompareEnabledInterruptStatus(TIMER_Ax,REGISTER_N);

8.获取定时器捕获电平状态:

Timer_A_getSynchronizedCaptureCompareInput(TIMER_Ax,REGISTER_N,Setting);

返回值:

TIMER_A_OUTPUTMODE_OUTBITVALUE_LOW

TIMER_A_OUTPUTMODE_OUTBITVALUE_HIGH

以下9~10,定义在了interrupt.h中:

9.开启定时器A端口中断:

Interrupt_enableInterrupt(INT_TAx_N);

10.开启总中断:

Interrupt_enableMaster(void);

一般配置步骤:

0.配置时钟

1.复用引脚

2.配置连续计数结构体

3.初始化定时器连续计数

4.配置捕获结构体

5.初始化定时器为捕获

6.选择模式开始计数

7.清除中断标志位

8.开启定时器端口中断

9.开启总中断

10.编写 TIMA ISR

本次配置TA2 通道1捕获并测量高电平持续时间为实验目标:

对应引脚为P5.6

首先定义一个初始化函数:

用来封装初始化的语句:

void Timer2_Cap_Inint()
{

}

1.复用引脚:

 Tip:   定时器捕获是复用输入,定时器PWM是复用输出:

//1.复用引脚GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5,GPIO_PIN6,GPIO_PRIMARY_MODULE_FUNCTION);

2.配置连续计数结构体:

首先在timer_a.h中找到结构体:

MSP432学习笔记9:定时器A-----捕获_第3张图片

 复制内容粘贴在初始化函数中:

MSP432学习笔记9:定时器A-----捕获_第4张图片

 做以下修改:

	//2.配置连续计数结构体
	Timer_A_ContinuousModeConfig continuousModeConfig=
	{
		TIMER_A_CLOCKSOURCE_SMCLK,      //时钟源
        TIMER_A_CLOCKSOURCE_DIVIDER_48, //时钟分频48  分辨力为1us
        TIMER_A_TAIE_INTERRUPT_ENABLE,  //开启定时器溢出中断
		TIMER_A_SKIP_CLEAR              //Skip Clear Counter 
	};

定时器溢出中断要使能开启,因为如果高电平持续时间过长

恰好到定时器溢出中断了才结束,此时的捕获寄存器刚好清零

读取到的捕获值就是0了,算出来的高电平持续时间就是0了

所以要开启溢出中断,每溢出一次就中断记录一次,

最后计算的时候,在把溢出的时间加回去

3.初始化定时器连续计数:

填上定时器A2和结构体地址就行了

//3.初始化定时器连续计数:
Timer_A_configureContinuousMode(TIMER_A2_BASE,&continuousModeConfig);

4.配置捕获结构体:

	//4.配置捕获结构体:
	const Timer_A_CaptureModeConfig continuousModeConfig_TA2=
	{
		TIMER_A_CAPTURECOMPARE_REGISTER_1,             //此处改通道引脚	
		TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE,   //上升下降沿捕获
		TIMER_A_CAPTURE_INPUTSELECT_CCIxA,	//CCIxA:外部引脚输入(CCIxB:与内部ACLK连接)
		TIMER_A_CAPTURE_SYNCHRONOUS                    //同步捕获
	};

5.初始化定时器为捕获:

	//5.初始化定时器为捕获:
	Timer_A_initCapture(TIMER_A2_BASE,&continuousModeConfig_TA2);

6.选择模式开始计数:

	//6.选择模式开始计数:
	Timer_A_startCounter(TIMER_A2_BASE,TIMER_A_CONTINUOUS_MODE);
	

7.清除中断标志位:

	//7.清除中断标志位:
	Timer_A_clearInterruptFlag(TIMER_A2_BASE);
	Timer_A_clearCaptureCompareInterrupt(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_1);

8.开启定时器端口中断:

	//8.开启定时器端口中断:
	Interrupt_enableInterrupt(INT_TA2_N);

该函数参数的有效值可以去interrupt.h找到声明:

MSP432学习笔记9:定时器A-----捕获_第5张图片

 我们用的是定时器A2 通道1中断,

通道1、2、3、4都是选择INT_TA2_N这个端口

              只有通道0是选择INT_TA2_0这个端口

9.开启总中断:

主函数初始化区域调用函数开启即可

MSP432学习笔记9:定时器A-----捕获_第6张图片

10.编写 TIMA ISR:

中断服务函数,去启动文件寻找函数名并复制:

MSP432学习笔记9:定时器A-----捕获_第7张图片

 粘贴,声明作为新的函数:

MSP432学习笔记9:定时器A-----捕获_第8张图片

开始编写捕获处理:

#define CAP_TIMA_SELECTION TIMER_A2_BASE                         //在这里改定时器
#define CAP_REGISTER_SELECTION TIMER_A_CAPTURECOMPARE_REGISTER_1 //在这里改定时器通道
#define CAP_CCR_NUM 1                                            //在这里改定时器通道
#define CAP_PORT_PIN GPIO_PORT_P5, GPIO_PIN6                     //在这里改复用引脚


uint16_t TIMA2_CAP_STA = 0;
uint16_t TIMA2_CAP_VAL = 0;




//定时器A2 通道1 中断服务函数
void TA2_N_IRQHandler(void)
{
	 //还未成功捕获
    if ((TIMA2_CAP_STA & 0X80) == 0)
    {
			//溢出中断
        if (MAP_Timer_A_getEnabledInterruptStatus(CAP_TIMA_SELECTION))
        {
					 //清除定时器溢出中断标志位
            MAP_Timer_A_clearInterruptFlag(CAP_TIMA_SELECTION);

            
            /*如果在未清除中断位值时,来了一次中断,COV会置位,需要软件复位,
							这里没有官方库函数。具体可以参考技术手册(slau356h.pdf) P790 */
            BITBAND_PERI(TIMER_A_CMSIS(CAP_TIMA_SELECTION)->CCTL[CAP_CCR_NUM], TIMER_A_CCTLN_COV_OFS) = 0;

				    //已经捕获到高电平了 40H = 0x 0100 0000
            if (TIMA2_CAP_STA & 0X40)
            {
							//高电平太长了
                if ((TIMA2_CAP_STA & 0X3F) == 0X3F)
                {
									 //强制标记成功捕获完高电平 80H = 0x1000 0000
                    TIMA2_CAP_STA |= 0X80;
                    TIMA2_CAP_VAL = 0XFFFF;
                }
                else
										//溢出次数加1
                    {TIMA2_CAP_STA++; }
            }
        }
						 //捕获中断
        if (MAP_Timer_A_getCaptureCompareEnabledInterruptStatus(CAP_TIMA_SELECTION, CAP_REGISTER_SELECTION))
        {
					//清除 CCR1 更新中断标志位
            MAP_Timer_A_clearCaptureCompareInterrupt(CAP_TIMA_SELECTION, CAP_REGISTER_SELECTION);

            //判断是否捕获到下降沿
            if (TIMA2_CAP_STA & 0X40 && 
							(MAP_Timer_A_getSynchronizedCaptureCompareInput(
								CAP_TIMA_SELECTION,
                CAP_REGISTER_SELECTION,
								TIMER_A_READ_CAPTURE_COMPARE_INPUT) == TIMER_A_CAPTURECOMPARE_INPUT_LOW))
            {
							 //标记成功捕获完高电平
                TIMA2_CAP_STA |= 0X80;
                TIMA2_CAP_VAL = Timer_A_getCaptureCompareCount(CAP_TIMA_SELECTION, CAP_REGISTER_SELECTION);
            }
						 //还未开始,第一次捕获上升沿
            else 
            {
                TIMA2_CAP_STA = 0;
                TIMA2_CAP_VAL = 0;
                MAP_Timer_A_clearTimer(CAP_TIMA_SELECTION); //清空定时器 重新从0计数
                TIMA2_CAP_STA |= 0X40;                      //标记捕获到了上升沿
            }
        }
    }
}

11.主函数捕获的编写:

 此处按键K1   K2分别是为了将LED点亮和熄灭

点亮时是高电平,以此模拟捕获高电平时长

并将计算好的时长通过串口发送给上位机

#include "sysinit.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "tim32.h"
#include "key.h"

#define CAP_TIMA_SELECTION TIMER_A2_BASE                         //在这里改定时器
#define CAP_REGISTER_SELECTION TIMER_A_CAPTURECOMPARE_REGISTER_1 //在这里改定时器通道
#define CAP_CCR_NUM 1                                            //在这里改定时器通道
#define CAP_PORT_PIN GPIO_PORT_P5, GPIO_PIN6                     //在这里改复用引脚


uint16_t TIMA2_CAP_STA = 0;
uint16_t TIMA2_CAP_VAL = 0;


void TimA2_Cap_Init(void);

int main(void)
{
	   uint8_t key;
    uint32_t temp;
	
	
    SysInit();         // 第3讲 时钟配置
    uart_init(115200); // 第7讲 串口配置
    delay_init();      // 第4讲 滴答延时
		    LED_Init();        //第2讲 GPIO输出
    KEY_Init(0);       //第2讲 GPIO输入
    TimA2_Cap_Init();  //第8讲 定时器A 捕获
		
    printf("Hello,MSP432!\r\n");
    MAP_Interrupt_enableMaster(); // 开启总中断
    while (1)
    {
			        key = KEY_Scan(0);
        if (key == KEY1_PRES)
            LED_RED_On();
        else if (key == KEY2_PRES)
            LED_RED_Off();

        if (TIMA2_CAP_STA & 0X80) //成功捕获到了一次上升沿
        {
            temp = TIMA2_CAP_STA & 0X3F;
            temp *= 65536;                 //溢出时间总和
            temp += TIMA2_CAP_VAL;         //得到总的高电平时间
            printf("HIGH:%dus\r\n", temp); //打印总的高点平时间
            TIMA2_CAP_STA = 0;             //开启下一次捕获
        }
			
    }
}

硬件电路的连接:

别忘了将P1^0与P5^6用杜邦线相连,这样LED亮,

就送来高电平给引脚P5^6测量捕获

实验结果:

MSP432学习笔记9:定时器A-----捕获_第9张图片

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