欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【ARM裸板】定时器中断示例与分析

程序员文章站 2022-06-09 08:54:20
...

1.定时器结构分析

  • 1.每来一个CLK,TCNTn减1
  • 2.当TCNTn == TCMPn时,(可以把对应的PWM引脚翻转)
    • TCNTnTCMPn的值来自寄存器TCNPBnTCMTBn
  • 3.TCNTn继续减1,当TCNTn == 0时,可以产生中断(PWM引脚再次翻转)
  • 4.TCNTn == 0时,可自动加载初值
    【ARM裸板】定时器中断示例与分析

2.初始化

  • 1.设置时钟源
  • 2.设置初值
  • 3.加载初值,启动Timer
  • 4.设置为自动加载
  • 5.中断相关

【ARM裸板】定时器中断示例与分析

  • 需要设置:1.Prescaler,2.MUX(Divider),3.TCMPB0(不是PWM测试,因此该不需要设置),4.TCNTB0,5.TCON0

【ARM裸板】定时器中断示例与分析

2.1 设置时钟源

【ARM裸板】定时器中断示例与分析

  • 由上公式:
  • 设置Prescaler
  • 设置MUX
	/* 1.设置timer0的时钟
	 * Timer CLK = PCLK / {prescaler value+1} / {divider value}
	 *               50000000/(99+1)/(16) = 31250
	 */
	TCFG0 = 99;    //Prescaler = 99,用于timer0,timer1
	TCFG1 &= ~0xFF;
	TCFG1 |= 3;    //MUX0=1/16(即是 divider value)

2.2 设置初值

	//2.设置timer0的初值
	TCNTB0 = 15625;  //0.5s中断一次(15625/31250=0.5s)

【ARM裸板】定时器中断示例与分析

2.3 手动加载初值

  • 手动加载初值至TCNT0与TCMT0,启动timer0
  • 置1
	TCON |= (1<<1);//Update from (TCNTB0 & TCMPB0) to (TCNT0 & TCMT0)

【ARM裸板】定时器中断示例与分析

2.4 清除手动加载

  • 清零
	TCON &= ~(1<<1);

2.5 设置自动重装载并启动

	TCON |= (1<<0) | (1<<3);//bit0:start,  bit3:auto reload

【ARM裸板】定时器中断示例与分析

3. 构造函数指针

  • 把每一个中断的处理函数放置在指针数组中,当发生中断时,通过判断中断号,调用对应的函数即可

3.1 定义

  • 定义函数指针,指针的变量名为irq_func
    typedef void (*irq_func)(int);

    irq_func irq_array[32];//定义存放函数指针数组(即:数组中存放的是函数指针)
  • typedef void(*Func)(void)的用途,先来看下其基本用法
	typedef void (*func)(void);  
	void myfunc(void);  
	func pfun = myfunc;/*赋值*/  
	pfun();/*调用*/  

3.2 由来

  • typedef void(*Func)(void);的由来
  • 其实这样的形式声明函数指针是有"问题"的。如果仿照变量类型声明,声明函数指针似乎应该这样:
typedef void(*)()  variable;

但是c标准的创建者没有这样做,不知道为什么,而选择了这样的声明:

typedef void(*variable)();

C编译器非常清楚,这就是在声明一个void(*)() 类型的函数指针variable。

3.4 注册函数

/* 注册中断
 * param:1.中断号,2.中断服务函数
*/
void register_irq(int irq,irq_func fp)
{
	irq_array[irq] = fp;//将fp指向的函数地址 存放在arr中

	INTMSK &= (1<<irq);
}
  • eg:
	register_irq(10, timer0_irq);

3.5 调用函数

/* 中断处理函数
 *
*/
void handle_irq_c(void)
{
	/* 1.分辨中断源 */
	int bit = INTOFFSET;//判断谁在请求中断

	/* 2.调用对应的处理函数 */
	irq_array[bit](bit); //irq_array存放的是函数指针,加一个()即表示调用该函数

	/* 3.清中断 :从源头开始清 */
	SRCPND = (1<<bit);
	INTPND = (1<<bit);
}
相关标签: 【ARM裸板】