分享

飞凌ok6410定时器精确控制led

 共同成长888 2015-07-18

 关于借鉴与版权的说明:飞凌提供的代码有一定问题,并且部分关键代码没有解释,我在搜集各方面资料后综合网友指正和自己的理解,注释了部分自己认为重要的部分。当然如果大神觉得可不注释,也可以。此篇文章援引多家大神的微博,如需看大神原作,请百度搜索标题,此处个人见解不恰当的请各位指正。
 

6410中的PWM 定时器

1.简单介绍 :

S3C6410X中有5个定时器,这些定时器产生内部中断。其中,Timer0和Timer1具有PWM功能,而Timer2,3,4没有此功能。

PWM具有两种操作模式:自动装载模式,一次触发模式。为实现PWM功能,芯片提供了16个功能寄存器。这些功能寄存器都连接APB总线。

定时器具有双缓冲特性,这样就能在不停止当前定时器操作的情况下,为下次定时器运行装入新的数值。尽管为定时器设置了新数值,但当前的定时操作能够成功完成。定时器从TCNTBn读取的值是为下次延时定时用的,并不影响当前定时器的运行。当TCNTn减小到0的时候,TCNTBn的值会自动复制到TCNTn中,这就是说的自动装载操作。定时器的当前计数值可以从定时计数观察寄存器中TCNTOn读取。如果TCNTn为0且从装载也为0的话则TCNTn不在进行下次操作。

2.定时器的电路结够图: 

 
 

3.定时器架构流程。

PCLK   ---à  经过8位的预分频器【8bit prescaler0】  --à   分频器divider   [1/1 1/2 1/4 1/81/16]   -à  多路选择器  MUX   -à   逻辑控制器【比较TCMPBn和TCNTBn的数值】--à(deadzone generator )  --à  时钟

  计算公式:

 
 

4.定时器的工作原理是什么。 

 
 

每个定时器有32位的递减计数器。递减计数器的初始值由TCNTBn来加载。  当计数器的值变为0时, 定时器产生中断信号通知cpu定时器操作完成。   当计数器的值变为0时,TCNTBn的值自动加载到递减计数器并开始下个周期的操作。    如果定时器停止工作(比如,在定时器工作模式期间清空寄存器TCONn的定时器使能位,这样对应的定时器就会停止工作),这时TCNTBn的值就不会加载到定时器。 

 

 

而对于PWM 功能,要用到寄存器TCMPBn,当递减计数器down-counter的值和比较寄存器TCMPBn的值相同时,定时控制逻辑模块就会改变输出电平。因此比较寄存器TCMPBn决定了PWM的输出。

而且TCNTBn 和 TCMPBn寄存器具有双缓冲特性,这样就能在不停止当前定时器操作的情况下,为下次定时器运行装入新的数值。尽管为定时器设置了新数值,但当前的定时操作能够成功完成。

5.  定时器的工作时序

 
 

我说怎么在上面的第一步中突然冒出个TCNTn和TCMPn,我以为是数据手册错了,因为在PWM提供的16个寄存器中没有这两个寄存器。  那么请看下面: 

 

从上面内容看出。TCNTn和TCMPn是内部的寄存器(internal registers ).而TCNTn寄存器的值可以通过读取寄存器TCNTOn来获得。

6.       16个特殊功能寄存器

7.接下来看一下飞凌提供的精确控制LED的程序。【利用定时器来精确控制LED跑马灯,每隔1s轮询点亮】

#define rGPMCON                     (*(volatile unsigned*)(0x7F008820))

#define rGPMDAT                     (*(volatileunsigned*)(0x7F008824))

#define rGPMPUD                     (*(volatile unsigned*)(0x7F008828))

 

#define PCLK 66000000 //forS3C6410 66MHZ 
// #define HCLK 133000000//forS3C6410 133MHZ 这一句没用到,写上可以。

 

#define rTCFG0               (*(volatile unsigned*)(0x7F006000))

#define rTCFG1               (*(volatileunsigned*)(0x7F006004))

 

#define rTCON                (*(volatileunsigned*)(0x7F006008))

#define rTCNTB0              (*(volatileunsigned*)(0x7F00600C))

#define rTCMPB0              (*(volatileunsigned*)(0x7F006010))

 

#define rTCNTO0              (*(volatileunsigned*)(0x7F006014))

#define rTCNTB1              (*(volatileunsigned*)(0x7F006018))

#define rTCMPB1              (*(volatileunsigned*)(0x7F00601c))

 

#define rTCNTO1              (*(volatileunsigned*)(0x7F006020))

#define rTCNTB2              (*(volatileunsigned*)(0x7F006024))

#define rTCNTO2              (*(volatileunsigned*)(0x7F00602c))

 

#define rTCNTB3              (*(volatileunsigned*)(0x7F006030))

#define rTCNTO3              (*(volatileunsigned*)(0x7F006038))

#define rTCNTB4              (*(volatileunsigned*)(0x7F00603c))

 

#define rTCNTO4              (*(volatileunsigned*)(0x7F006040))

#definerTINT_CSTAT    (*(volatileunsigned*)(0x7F006044))

 

void uDelay(intusec)

{

   unsignedint val=(PCLK)/1000000-1; //val = 65

  

//configure prescalerand divider

  rTCFG0&=~(0xff<<8); //0000_0000_1111_1111  TCFG0[15:8-7:0]

  rTCFG0|=0<<8;       //0000_0000_0000_0000 |0000_0000_1111_1111   prescalar0 = 255  timer0,timer1 的prescalar value= 255  timer2,3,4的prescalar1 value = 0

  

  rTCFG1&=~(0xf<<8); // 0000_1111_1111   TCFG1 [7:0] =1111_1111 TCFG1[11:8] = 0000(select mux for timer2.   divider value = 1 );  

  rTCFG1|=0<<8;

  

   //compute  :  

   //timerinput clock frequency = PCLK /({prescaler value + 1})/{divider value} 

   // timer2input clock frequency = 66M /(1)/(1)= 66M hz 

 

//configure timercounter buffer  and enable timer2   

  rTCNTB2=val;

  

  rTCON&=~(0xf<<12); //  0000_1111_1111_1111

  rTCON|=0xb<<12;    //  1011_0000_0000_0000|0000_1111_1111_1111 = 1011_1111_1111_1111

  rTCON&=~(2<<12);   //  1101_1111_1111_1111&1011_1111_1111_1111 = 1001_1111_1111_1111

【//  TCON(Timer control register)
 
 

//1001   : 表示 :   auto-reload  ,   starttimer2】

  //TCON[15]=1 auto-reload

  //TCON[14]  Reserved bits

  //TCON[13]=0  no operatin ,  =1,update TCNTB2 TCMPB2

  //TCON[12]=0  stop ,  =1 ,start timer2

  

  

  //rTCON&= 0x9fff;  

   while(usec--){

          while(rTCNTO2 >= val>>1);

          while(rTCNTO2 < val>>1);

     };

 

}

 

void msDelay(inttime)

 

{

          volatile unsigned int i,j;

          for(i=0;i<2000000;i++)

    for(j=0;j<time;j++);

}

 

void GPIO_Init(void)

 

{

        rGPMCON =0x11111;

        rGPMPUD =0x00;

 

        rGPMDAT =0X1F;

}

 

voidLedTest(void)

{

        volatile unsigned int i ,j;

 

        while(1)

        {

                for(i=0;i<4;i++)

 

                {

                         rGPMDAT=~(1<<i);

                        for(j=0;j<1000;j++)

 

                        uDelay(1000);

                }

        }

 

}

void Main(void)

{

        GPIO_Init();

        LedTest();

}


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多