tiny6410裸机实验第10章--------------PWM定时器(原理及代码)

时间:2022-09-05 03:54:40

【说明】

             S3C6410带有5个32位定时器,其中定时器4是内部定时器,没有引出外部引脚的,这一节我们就来试试操作定时器中断。学了这个定时器操作之后,我们再利用它来写一个进程调度程序,实现最最简单的进程并发。

 

【原理】

             S3C6410的5个定时器中,定时器0和1有PWM功能,其他没有

             PWM具有两种操作,即自动装载模式和一次触发模式,       

             所提供的定时器有双缓冲功能,对定时器的操作不会影响定时器当前的运作

             看看电路图

             tiny6410裸机实验第10章--------------PWM定时器(原理及代码)

              1)源时钟为PCLK,我们在时钟初始化的时候将其设置为了66MHZ

              2)源时钟要进过两次分频才到达逻辑控制单元,所以显然我们得设置这2个分频咯

 

 

【寄存器操作】

                定时器的寄存器比较少所以操作起来非常简单

             1】定时器配置寄存器

                     tiny6410裸机实验第10章--------------PWM定时器(原理及代码)

                      tiny6410裸机实验第10章--------------PWM定时器(原理及代码)

                      1)这个寄存器就是第一个分频器的设置,我们要用定时器0,所以就设置前面8位

                    

                      tiny6410裸机实验第10章--------------PWM定时器(原理及代码)

                      tiny6410裸机实验第10章--------------PWM定时器(原理及代码)

                      2)设置第二次分频。。我们设置为0100

                        

                    2】设置定时时间

                        tiny6410裸机实验第10章--------------PWM定时器(原理及代码)     

                         1)往这个寄存器写入的就是定时的时间,当然,具体数值需要和最终的时钟频率有关。

                         2)其实定时器本身并不是利用这个寄存器计时的,而是用TCNTN0,但是那是一个内部寄存器,无法直接操作。

                         3)当TCNTN0到时的时候,若设置为自动装载模式,则TCNTB0的值会被复制到TCNTN0

 

                     3】设置比较时间

                           tiny6410裸机实验第10章--------------PWM定时器(原理及代码)

                            1)这个一般设置为0,就是说TCNTB0里面的数值减少到什么值的时候产生中断的。

 

                      4】控制寄存器

                             tiny6410裸机实验第10章--------------PWM定时器(原理及代码)

                             tiny6410裸机实验第10章--------------PWM定时器(原理及代码)

                              1)我们需要设置一下手动更新位,然后再清手动更新位。。。为什么呢?我也知道。。。

 

                             tiny6410裸机实验第10章--------------PWM定时器(原理及代码)

                               2)启动计时器

                               tiny6410裸机实验第10章--------------PWM定时器(原理及代码)

                                3)自动装载模式 

 

                        5】使能中断

                             

                             tiny6410裸机实验第10章--------------PWM定时器(原理及代码)

                             tiny6410裸机实验第10章--------------PWM定时器(原理及代码)

                              1)这个使能定时器,使其能发送中断

                          

                           tiny6410裸机实验第10章--------------PWM定时器(原理及代码)

                             tiny6410裸机实验第10章--------------PWM定时器(原理及代码)

                             2)在中断控制器中使能

【中断处理】

                     我们只是简单得在串口打印一句话。然后清中断。

 

【源代码】

                  

#include "stdio.h"

#define EINT0CON0                       (*((volatile unsigned long *)0x7F008900))
#define EINT0MASK                       (*((volatile unsigned long *)0x7F008920))
#define EINT0PEND                       (*((volatile unsigned long *)0x7F008924))
#define PRIORITY                (*((volatile unsigned long *)0x7F008280))
#define SERVICE                 (*((volatile unsigned long *)0x7F008284))
#define SERVICEPEND             (*((volatile unsigned long *)0x7F008288))
#define VIC0IRQSTATUS           (*((volatile unsigned long *)0x71200000))
#define VIC0FIQSTATUS           (*((volatile unsigned long *)0x71200004))
#define VIC0RAWINTR             (*((volatile unsigned long *)0x71200008))
#define VIC0INTSELECT           (*((volatile unsigned long *)0x7120000c))
#define VIC0INTENABLE           (*((volatile unsigned long *)0x71200010))
#define VIC0INTENCLEAR          (*((volatile unsigned long *)0x71200014))
#define VIC0PROTECTION          (*((volatile unsigned long *)0x71200020))
#define VIC0SWPRIORITYMASK      (*((volatile unsigned long *)0x71200024))
#define VIC0PRIORITYDAISY       (*((volatile unsigned long *)0x71200028))
#define VIC0ADDRESS             (*((volatile unsigned long *)0x71200f00))

#define         PWMTIMER_BASE                   (0x7F006000)
#define         TCFG0           ( *((volatile unsigned long *)(PWMTIMER_BASE+0x00)) )
#define         TCFG1           ( *((volatile unsigned long *)(PWMTIMER_BASE+0x04)) )
#define         TCON            ( *((volatile unsigned long *)(PWMTIMER_BASE+0x08)) )
#define         TCNTB0          ( *((volatile unsigned long *)(PWMTIMER_BASE+0x0C)) )
#define         TCMPB0          ( *((volatile unsigned long *)(PWMTIMER_BASE+0x10)) )
#define         TCNTO0          ( *((volatile unsigned long *)(PWMTIMER_BASE+0x14)) )
#define         TCNTB1          ( *((volatile unsigned long *)(PWMTIMER_BASE+0x18)) )
#define         TCMPB1          ( *((volatile unsigned long *)(PWMTIMER_BASE+0x1C)) )
#define         TCNTO1          ( *((volatile unsigned long *)(PWMTIMER_BASE+0x20)) )
#define         TCNTB2          ( *((volatile unsigned long *)(PWMTIMER_BASE+0x24)) )
#define         TCMPB2          ( *((volatile unsigned long *)(PWMTIMER_BASE+0x28)) )
#define         TCNTO2          ( *((volatile unsigned long *)(PWMTIMER_BASE+0x2C)) )
#define         TCNTB3          ( *((volatile unsigned long *)(PWMTIMER_BASE+0x30)) )
#define         TCMPB3          ( *((volatile unsigned long *)(PWMTIMER_BASE+0x34)) )
#define         TCNTO3          ( *((volatile unsigned long *)(PWMTIMER_BASE+0x38)) )
#define         TCNTB4          ( *((volatile unsigned long *)(PWMTIMER_BASE+0x3C)) )
#define         TCNTO4          ( *((volatile unsigned long *)(PWMTIMER_BASE+0x40)) )
#define         TINT_CSTAT      ( *((volatile unsigned long *)(PWMTIMER_BASE+0x44)) )

void irq_init(void)
{
        /* 在中断控制器里使能timer0中断 */
        VIC0INTENABLE |= (1<<23);


}

// timer0中断的中断处理函数
void do_irq()
{
        static int i=1;
        printf("%d Timer0 interrupt occur\r\n",i++);
        unsigned long uTmp;
        //清timer0的中断状态寄存器
        uTmp = TINT_CSTAT;
        TINT_CSTAT = uTmp;      


}

// 初始化timer
void timer_init(unsigned long utimer,unsigned long uprescaler,unsigned long udivider,unsigned long utcntb,unsigned long utcmpb)
{
        unsigned long temp0;

        // 定时器的输入时钟 = PCLK / ( {prescaler value + 1} ) / {divider value} = PCLK/(65+1)/16=62500hz

        //设置预分频系数为66
        temp0 = TCFG0;
        temp0 = (temp0 & (~(0xff00ff))) | ((uprescaler-1)<<0);
        TCFG0 = temp0;

        // 16分频
        temp0 = TCFG1;
        temp0 = (temp0 & (~(0xf<<4*utimer))& (~(1<<20))) |(udivider<<4*utimer);
        TCFG1 = temp0;

        // 1s = 62500hz
        TCNTB0 = utcntb;
        TCMPB0 = utcmpb;

        // 手动更新
        TCON |= 1<<1;

        // 清手动更新位
        TCON &= ~(1<<1);

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

        // 使能timer0中断
        temp0 = TINT_CSTAT;
        temp0 = (temp0 & (~(1<<utimer)))|(1<<(utimer));
        TINT_CSTAT = temp0;
}