MSP432学习笔记13:TIMER_32定时器的学习与使用

文章提供源码与工程,芯片型号MSP432P401R

在前些日子的学习里,我们深刻认识了具有强大功能的定时器A,这是一种广泛存在于各类现有 MSP430 器件的 16 位定时器。同 时,它也是灵活性最高的定时器,由于其可用于众多不同案例,因而堪称“瑞士军刀”级的定时器。

今日学习使用MSP432的另一个定时器:   Timer_32 定时器~

目录

Timer_32 定时器的基础概念:

Timer_32 定时器相关初始化函数介绍:

 1.Timer_32 定时器初始化函数:

2.设定自动重载值:

3.设定计数模式:

4.开启定时器中断:

5.清除中断标志位:

Timer_32 定时器实战使用编写:

程序下载测试截图:

完整代码贴出:


Timer_32 定时器的基础概念:

首先我们将数据手册(1053页的那本)翻阅到765页,看到Timer_32的介绍:

MSP432学习笔记13:TIMER_32定时器的学习与使用_第1张图片

当然~这开头的手册贴图它只是个玩笑,这充满了英文,我怎么可能看得懂~~

所以我将其翻译了:

通过下段介绍,我们知道Timer32有俩个定时器,俩个定时器可以被编程为32或者16位,使用时需要将它选择的时钟进行预分频处理

18.1介绍
Timer32是一款符合AMBA标准的外设,由Arm有限公司开发、测试和授权。的
Timer32由两个可编程的32位或16位下行计数器组成,可以在计数达到零时产生中断。


Timer32的主要特性包括:
•两个独立的计数器,每个可配置为32位或16位计数器大小
•每个计数器支持三种不同的计时器模式
•将输入时钟分频除以1、16或256的预刻度单元
•来自每个计数器的独立中断,以及来自两个计数器的组合中断计数器

 通过下段介绍,我们知道了Timer32俩个定时器之间是相互独立的,他们有三种计时模式需要注意说明的是:前面俩种自由运行与周期计数模式是二选一的,第三个一次性定时模式是选择性开关的。

18.2功能介绍
Timer32中有两个独立的计时器。对于每个定时器,有以下操作模式是可用的:


•自由运行模式:

计数器在达到零值后轮回,并继续从最大值。这是默认设置的模式。


•周期定时器模式:

计数器以恒定的间隔产生中断,重新加载原始数据值。


•一次性定时器模式:

计数器产生一次中断。当计数器达到零时,它暂停,直到用户重新编程。这可以通过清除One Shot Count位来实现。在控制寄存器中,在这种情况下,计数根据自由运行或选择进行
周期模式,或通过向加载值寄存器写入一个新值。

 通过下段介绍,我们知道了Timer32俩个定时器在对于寄存器的操作上是相同的,也知道了俩种计数模式在计数中断,写入寄存器等操作后的不同状态,以及知道了它的时钟是MCLK的不同分频

 18.3操作
每个计时器都有一组相同的寄存器,每个计时器的操作也是相同的。计时器是通过写入加载寄存器进行加载,如果启用使能,则计数降至零。当一个计数器已经运行时,写入加载寄存器将导致计数器立即在新值处重新启动。写命令给后台负载值对当前计数没有影响。如果在周期模式,而不是选中一次性定时器模式:计数器继续递减到零,然后从新的重载值重新开始。


当达到零时,就会产生中断。可以通过写入clear寄存器来清除中断登记。如果选择“一次性定时器模式”,则计数器在达到零时停止,直到“一次性定时器模式”被取消选择,或者写入新的Load值。否则,在达到零计数后,如果计时器正在自由运行模式下,它从最大值继续递减。如果选择周期定时器模式,计时器从加载寄存器重新加载计数值并继续递减。在这种模式下
计数器有效地产生周期性中断。模式由定时器控制中的一个位来选择登记。在任何时候,都可以从当前值寄存器中读取当前计数器的值。通过T32CONTROLx寄存器中的ENABLE位使能。


在重置时,计数器被禁用,中断被清除,负载寄存器被设置为零。模式和预调值设置为自由运行,时钟分频分别为1。


定时器时钟使能是由一个预置单元产生的。然后计数器使用启用来创建一个时钟:具有下列时间之一的时钟:
•MCLK
•MCLK除以16,由4位预刻度生成
•MCLK除以256,由总共8位的预分频产生


图18-1显示了在预刻度单元中定时器时钟频率的选择。这使定时器能够他的时钟频率不同。

 MSP432学习笔记13:TIMER_32定时器的学习与使用_第2张图片

  通过下段介绍,我们知道了Timer32有三种中断

18.4中断生成。
当完整的32位计数器达到零时会生成中断,并且仅当。T32INTCLRx寄存器被写入值了。寄存器保存该值,直到中断被清除。最多的。计数器的有效进位位检测到计数器达到零。


通过将0写入T32CONTROLx寄存器中的中断使能位,可以屏蔽中断。无论是在原始中断状态,在掩蔽之前,和最终中断状态

可以读取屏蔽前的原始中断状态和屏蔽后的最终中断状态。状态寄存器。来自各个计数器的中断在屏蔽之后被逻辑地或进一个。组合中断TIMINTC提供来自定时器32外设的附加中断条件。因此,该模块总共支持三个中断-TIMINT1、TIMINT2和TIMINTC。

Timer_32 定时器相关初始化函数介绍:

 1.Timer_32 定时器初始化函数:

 此函数初始化设置 定时器预分频、32或16位计数、计数模式这四个参数

    MAP_Timer32_initModule(uint32_t timer,uint32_t preScaler,uint32_t resolution, uint32_t mode);

 #define ROM_Timer32_initModule                                                \
        ((void (*)(uint32_t timer,                                            \
                   uint32_t preScaler,                                        \
                   uint32_t resolution,                                       \
                   uint32_t mode))ROM_TIMER32TABLE[0])

 uint32_t timer ,可以选择以下定时器之一:

#define TIMER32_0_BASE   (uint32_t)TIMER32_1
#define TIMER32_1_BASE   (uint32_t)TIMER32_2

uint32_t preScaler:可以选择以下预分频之一( 1、16、256):

#define TIMER32_PRESCALER_1      0x00
#define TIMER32_PRESCALER_16     0x04
#define TIMER32_PRESCALER_256    0x08

uint32_t resolution:可以选择以下计数位数之一(16位或32位):

 这个设置影响的是最大重载值不同

#define TIMER32_16BIT            0x00
#define TIMER32_32BIT            0x01

uint32_t mode:可以选择以下计数模式之一:

自由运行模式、周期模式 ,一般使用周期模式

#define TIMER32_FREE_RUN_MODE   0x00
#define TIMER32_PERIODIC_MODE   0x01

2.设定自动重载值:

    MAP_Timer32_setCount(uint32_t timer, uint32_t count);

#define ROM_Timer32_setCount                                                  \
        ((void (*)(uint32_t timer,                                            \
                   uint32_t count))ROM_TIMER32TABLE[1])

uint32_t count 就是需要填入的自动重载值

3.设定计数模式:

    MAP_Timer32_startTimer(TIMER32_0_BASE, false); //连续计数模式 false

#define ROM_Timer32_startTimer                                                \
        ((void (*)(uint32_t timer,                                            \
                   bool oneShot))ROM_TIMER32TABLE[4])

此处的计数模式选择参数用的是bool类型变量

4.开启定时器中断:

    MAP_Interrupt_enableInterrupt(INT_T32_INT1);

 这里的参数可以选择俩个中断,对应32定时器1和2的中断:

#define INT_T32_INT1                                    (41) /* T32_INT1 IRQ */
#define INT_T32_INT2                                    (42) /* T32_INT2 IRQ */

5.清除中断标志位:

    MAP_Timer32_clearInterruptFlag(TIMER32_0_BASE);

这个函数就是在中断服务函数中清除中断标志位的,必不可少~

MSP432学习笔记13:TIMER_32定时器的学习与使用_第3张图片

Timer_32 定时器实战使用编写:

现在进入我们的实战使用环节:

 目标:

驱动Timer32定时器0,以1s为周期发送串口测试

首先编写初始化函数,这相较于定时器A,Timer32的初始化十分简单:

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的时钟是MCLK,便可以提供以下公式进行计算:

/*
 * 定时器中断周期:
 *
 * T_timer_32 = CLKDIV * (ARR + 1) / MCLK
 *            = 1 * 48000000 / 48000000
 *            = 1s = 1Hz
 */

在这里我希望其周期是1S,因此我作以下初始化:

#define CLKDIV TIMER32_PRESCALER_1 // 时钟源分频
#define ARR 47999999               // 自动重装载值

MSP432学习笔记13:TIMER_32定时器的学习与使用_第4张图片

最后编写中断服务函数:

/* Timer32 ISR */
void T32_INT1_IRQHandler(void)
{
    MAP_Timer32_clearInterruptFlag(TIMER32_0_BASE);
    static uint8_t timer_second = 0;
    //一般在频率较高的中断不常用 这个printf比较费时间 这里只是演示
    printf("timer_second=%d\r\n", ++timer_second);
}

程序下载测试截图:

 MSP432学习笔记13:TIMER_32定时器的学习与使用_第5张图片

完整代码、工程贴出:

完整工程下载地址:

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

移植此代码须知:

将原先RNA的库大部分移除了在复制,只留下截图中有的:

MSP432学习笔记13:TIMER_32定时器的学习与使用_第6张图片

/*TIMER32定时器初始化与使用*/

#include "main.h"

/*
 * 定时器中断周期:
 *
 * T_timer_32 = CLKDIV * (ARR + 1) / MCLK 
 *            = 1 * 48000000 / 48000000 
 *            = 1s = 1Hz
 */

#define CLKDIV TIMER32_PRESCALER_1 // 时钟源分频
#define ARR 47999999               // 自动重装载值

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

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

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 */
void T32_INT1_IRQHandler(void)
{
    MAP_Timer32_clearInterruptFlag(TIMER32_0_BASE);
    static uint8_t timer_second = 0;
    //一般在频率较高的中断不常用 这个printf比较费时间 这里只是演示
    printf("timer_second=%d\r\n", ++timer_second);
}


//串口A0初始化
void uart_init(uint32_t baudRate)
{
  //固件库v3_40_01_02
  //默认SMCLK 48MHz 比特率 115200
  const eUSCI_UART_ConfigV1 uartConfig =
      {
          EUSCI_A_UART_CLOCKSOURCE_SMCLK,                // SMCLK Clock Source
          26,                                            // BRDIV = 26
          0,                                             // UCxBRF = 0
          111,                                           // UCxBRS = 111
          EUSCI_A_UART_NO_PARITY,                        // No Parity
          EUSCI_A_UART_LSB_FIRST,                        // MSB First
          EUSCI_A_UART_ONE_STOP_BIT,                     // One stop bit
          EUSCI_A_UART_MODE,                             // UART mode
          EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION, // Oversampling
          EUSCI_A_UART_8_BIT_LEN                         // 8 bit data length
      };
 eusci_calcBaudDividers((eUSCI_UART_ConfigV1 *)&uartConfig, baudRate); //配置波特率
  MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);//初始化串口引脚
  MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig);    //用配置好的结构体初始化串口
  MAP_UART_enableModule(EUSCI_A0_BASE);								//开启串口模块
  MAP_UART_enableInterrupt(EUSCI_A0_BASE,EUSCI_A_UART_RECEIVE_INTERRUPT);//开启串口中断
  MAP_Interrupt_enableInterrupt(INT_EUSCIA0);
}

//串口相关:
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
  int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
  x = x;
}
#else
int fgetc(FILE *f)
{
  while (EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG !=
         UART_getInterruptStatus(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG))
    ;
  return UART_receiveData(EUSCI_A0_BASE);
}
#endif

//重定向Printf,可以切换printf函数对应的串口
int fputc(int ch, FILE *f)
{
  UART_transmitData(EUSCI_A0_BASE, ch & 0xFF);
  return ch;
}

#ifndef _main_h_
#define _main_h_

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



void inint_all(void);               //初始化所有模块
void Tim32_0_Int_Init(uint32_t aar, uint8_t psc);
void uart_init(uint32_t baudRate);


#endif

你可能感兴趣的:(MSP432学习笔记,嵌入式硬件,经验分享)