s5pv210 的定时器

以下是关于s5pv210的定时器相关的图示,可以看出定时器的时钟来自PCLK的时钟,有2个8bit的预分频,然后还可以再次分频为1,2,4,8,16或者直接选用SCLK_PWM,后面有一个逻辑控制单元,一个是计数器,一个是控制输出管脚的的高低电平。计数器是TCNTBn是一个向下递减的计数器,减到0时产生中断(如果使能中断的话),TCMPBn是比较寄存器,当TCNTBn 的值倒计时到和TCMPBn相等时会使对应的输出管脚输出对应的电平


如图是整个定时器运行的全部过程。


以下是关于如何设置timer的步骤


以下是webee的裸机代码:

#include "timer.h"
#include "int.h"
#include "stdio.h"
#include "key.h"

unsigned int  time_val;  // 全局定时计数变量

/*  功能:
 *  启动某个定时器,如启动定时器0,则调用start_time(0);
 */
void start_timer(unsigned long num)
{
	if(num < 2)
	{
		TCON |= 1<< (num * 8);
	}
	else
	{
		TCON |= 1<< ((num + 1 )* 4);
	}
}

/*  功能:
 *  关闭某个定时器,如关闭定时器3,则调用start_time(3);
 */
void stop_timer(unsigned long num)
{
	if(num < 2)
	{
		TCON &= ~(1<< (num * 8));
	}
	else
	{
		TCON &= ~(1<< ((num + 1 )* 4));
	}
	
}

/*  功能:
 *  复位并关闭定时器0
 */
void reset_time_val(void)
{
	time_val  = 0;
	stop_timer(0);
}


/* 功能:
 * 关闭所有PWM定时器 
 */
void stop_all_timer(void)
{
	TCON = 0;
}


/* 功能:
 * timer0中断的真正的中断处理函数 
 */
void isr_timer()
{
	TINT_CSTAT = TINT_CSTAT;   //清timer0的中断状态寄存器
	VIC0ADDR = 0;			   //清中断控制向量
	
	printf("\nCurrent count time = %d.%d\r",time_val/10,time_val%10);  // 打印中断发生次数
	time_val++;	
}


/* 
 *	定时器0初始化调用timer_init(0,65,4,6250,0);	
 *  timer_num = 0,uprescaler = 65, udivider = 4 = 0x0100,utcntb=6250,utcmpb = 0.
 *	定时器的输入时钟 = PCLK / ( {prescaler value + 1} ) / {divider value} 
 *					   = PCLK/(65+1)/16=62500hz 
 *  本实验定时器0.1秒
 */
void timer_init(unsigned int timer_num,unsigned long uprescaler,unsigned long udivider,unsigned long utcntb,unsigned long utcmpb)
{
	unsigned long temp0;
	temp0 = TCFG0;  //设置预分频系数为66
	
	time_val = 0;
	
	if((timer_num < 2) && (timer_num >= 0))     // 一级预分频参数的设置(timer0,1)
	{
		temp0 = (temp0 & (~(0xff))) | ((uprescaler-1)<<0);
		TCFG0 = temp0;
	}
	else if((timer_num < 5) && (timer_num >= 2))  // 一级预分频参数的设置(timer2,3,4)
	{
		temp0 = (temp0 & (~(0xff << 8))) | ((uprescaler-1)<<8);
		TCFG0 = temp0;
	}

	TCFG1 = (TCFG1 & (~(0xf<<4*timer_num))& (~(1<<20))) |(udivider<<4*timer_num); // 二级预分频,这里是16分频

	switch(timer_num)  		// 1s = 62500hz,即每秒计数器计数62500次
	{
		case 0:
				TCNTB0 = utcntb;
				TCMPB0 = utcmpb;
				break;

		case 1:
				TCNTB1 = utcntb;
				TCMPB1 = utcmpb;
				break;

		case 2:
				TCNTB2 = utcntb;
				TCMPB2 = utcmpb;
				break;

		case 3:
				TCNTB3 = utcntb;
				TCMPB3 = utcmpb;
				break;

		case 4:
				TCNTB4 = utcntb;
				break;
		default:
				break;
	}
	
	TCON |= 1<<(1+(timer_num*8));       //第一次必须手动更新

	TCON &= ~(1<<(1+(timer_num*8)));    //紧接着要清除手动更新位

	TCON |= (1<<(0+(timer_num*8)))|(1<<(3+(timer_num*8)));  // 自动加载和启动timer0

	TINT_CSTAT = (TINT_CSTAT & (~(1<<timer_num)))|(1<<(timer_num));  // 使能timer0中断
}
main.c

#include "lib.h"
#include "clock.h"
#include "led.h"
#include "uart.h"
#include "timer.h"
#include "int.h"
#include "key.h"

int main(void)
{
	led_init(); 		//初始化LED
	sys_clock_init(); 	//初始化时钟
	uart_init(); 		//初始化串口
	int_init();			//初始化中断
	key_init();
	
	printf("\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
	printf("\n     		 This is a stopwatch test.\n");
	printf("\n    		 Write by WebeeA8 member: %d \n",2013);
	printf("\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n");
	
	stop_all_timer();				// 先关闭所有PWM定时器
	timer_init(0,65,4,6250,0);		// 设置timer0,在里面会启动定时器
	while (1);
	
	return 0;
}
中断初始化

#include "int.h"
#include "timer.h"
#include "key.h"


/* 通用中断处理函数 */
void irq_handler(void)
{
	void (*isr_p)(void);   //定义一个函数指针,这个指针指向一个返回值类型为void,参数为void的函数
	
	if(VIC0IRQSTATUS)		//VICxIRQSTATUS = 1 表示有中断发生
	isr_p  = (void (*)(void))VIC0ADDR;	//取出中断服务程序地址
	else if(VIC1IRQSTATUS)
	isr_p  = (void (*)(void))VIC1ADDR;	//取出中断服务程序地址
	else if(VIC2IRQSTATUS)
	isr_p  = (void (*)(void))VIC2ADDR;	//取出中断服务程序地址
	else if(VIC3IRQSTATUS)
	isr_p  = (void (*)(void))VIC3ADDR;	//取出中断服务程序地址

	(*isr_p)();						    //跳转到真正的中断处理函数
}

void int_init(void)
{
		pExceptionIRQ  = (unsigned long)IRQ_handle;		//设置中断跳转地址

		VIC0VECTADDR21 = (unsigned long)isr_timer;	    //设置中断服务程序地址
		VIC0VECTADDR16 = (unsigned long)isr_key;

		VIC0INTSELECT &= (~(1<<21))&(~(1<<16));			//将外部中断21、16设为IRQ模式
		
		VIC0INTENABLE  |= (1<<21)|(1<<16); 				//使能中断控制器
}


具体的代码可以参考以下地址:

https://code.csdn.net/snippets/1545702

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值