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

来源:互联网 发布:淘宝the mountain 编辑:程序博客网 时间:2024/05/20 06:04

【说明】

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

 

【原理】

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

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

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

             看看电路图

            

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

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

 

 

【寄存器操作】

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

             1】定时器配置寄存器

                    

                     

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

                    

                     

                     

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

                        

                    2】设置定时时间

                             

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

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

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

 

                     3】设置比较时间

                          

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

 

                      4】控制寄存器

                            

                             

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

 

                            

                               2)启动计时器

                              

                                3)自动装载模式 

 

                        5】使能中断

                             

                            

                            

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

                          

                          

                            

                             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;      }// 初始化timervoid 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;}


 

0 0
原创粉丝点击