zoukankan      html  css  js  c++  java
  • S3C2440的定时器详解

    S3C2440A516位定时器。其中定时器0123具有脉宽调制(PWM)功能。定时器4是一个无输出引脚的内部定时器。定时器0还包含用于大电流驱动的死区发生器

    定时器01共用一个8位预分频器,定时器234共用另外的8位预分频器。每个定时器都有一个可以生成5种不同分频信号(1/21/41/81/16TCLK)的时钟分频器。每个定时器模块从相应8位预分频器得到时钟的时钟分频器中得到其自己的时钟信号。8位预分频器是可编程的,并且按存储在TCFG0TCFG1寄存器中的加载值来分频PCLK

    每个定时器有它自己的由定时器时钟驱动的16位递减计数器。当递减计数器到达零时,产生定时器中断请求通知CPU定时器操作已经完成。当定时器计数器到达零时,相应的TCNTBn的值将自动被加载到递减计数器以继续下一次操作

    对于定时器的使用有两种模式,第一是普通定时第二是PWM输出

    先说普通定时,一般定时器的使用流程都会包含这几步

    1.       在低功耗寄存器里面启用相应的定时器外设

    2.       设置时钟分频比,获取定时器的计数时钟

    3.       设置定时器的定时值(重载值),配置中端,启动定时器

    4.       等待中断发生,中断处理函数中清除中断

    依靠这几步,有以下寄存器我们需要注意


    首先,设置PCLK到定时器的分频比例,有两种时钟,分别是01定时器和234定时器

    然后进行第二次分频


    可选择1/2 1/4 1/8 1/16几种时钟,时钟源是从上一个寄存器分频来的


    设置定时器的自动重载和启动定时器,注意在这个寄存器中,请用手动更新了之后必须再次清零,否则定时器无法运行


    我之前就遇到过这个问题


    设置定时器自动重载的值

    再然后按照之前的设置中断的方式设置中断,定时器没有次级源,以time0为例

    1.       源挂起srcpend


    2.       中断模式intmode


    3.       中断屏蔽intmask


    4.       中断挂起intpend


    使能中断之后定时器就可以正常使用了

     

    具体代码如下:

     

    Timer.c

     

    #include "timer.h"
    
    u8 timer0Up = 0;
    
    void __irq timer0()
    {
    	rSRCPND |= (1<<10);//清除源挂起
    	rINTPND |= (1<<10);//清除中断挂起
    
    	timer0Up = 1;
    }
    
    //定时器初始化
    //prescaler 8为分频器值,0-255
    //mux定时器的选通输入 0 1/2 1 1/4 2 1/8 3 1/16
    //定时器的重载值
    void InitTimer0(u8 prescaler,u8 mux,u16 count)
    {
    	rCLKCON |= (1<<8);	//打开timer时钟
    	
    	rTCFG0 &= ~0xff;		//清零分频器
    	rTCFG0 |= prescaler;   	//设置预分频器
    	
    	rTCFG1 &= ~(0x0f<<0);
    	rTCFG1 |= (mux<<0);  	//设置选通输入
    	
    	//设置定时器的计数值
    	 rTCMPB0=0x0;
    	 rTCNTB0 =count; //设定初值
    	 
    	 //启动定时器
    	 rTCON |=(1<<1); //更新TCNTB0和TCMPB0
    	 rTCON |= (1<<3);//启动自动重载
    	 rTCON &= ~(1<<1);//清零手动更新
    	 
    	 rSRCPND |= (1<<10);//清除源挂起
    	 rINTPND |= (1<<10);//清除中断挂起
    	 rINTMOD &= ~(1<<10);//设置中断模式为IRQ模式
    
    	 rINTMSK &= ~(1<<10);//使能定时器中断
    	 
    	 pISR_TIMER0 =(unsigned)timer0; //设置中断地址
    	 
    	 rTCON |= (1<<0);//启动定时器0
    }
    


    Timer.h

     

    #ifndef __TIMER_H
    #define __TIMER_H
    #include "2440addr.h"
    #include "led.h"
    #include "uart0.h"
    
    extern u8 timer0Up ;
    
    void InitTimer0(u8 prescaler,u8 mux,u16 count);
    
    
    
    #endif
    
    
    


     

     

     

    PWM波形输出时需要注意几个别的寄存器

    第一:PWM输出不需要开启中断,但是要设置相应的引脚复用功能为pwm功能,如图,TCLK


    第二,使用pwm功能必须要使能比较寄存器,也就是


    第三,根据需要看是否需要反向,何为反向呢


    就是TCNT<TCMP的时候为低电平,否则高电平,正好与正常的相反,基本要点就那么多,pwm连接到蜂鸣器上,可听到声音的状态响一下停一下(因为频率1HZ很低),剩下的请看代码

     

    Pwm.c

    #include "pwm.h"
    
    
    // compare 比较寄存器的值
    void Tomer0PwmInit(u8 prescaler,u8 mux,u16 count,u16 compare)
    {
    	rGPBCON &=~3;
    	rGPBCON |=2;		//设置GPB0为OUT0
    	rGPBUP=0x0;		//使能上拉
    	
    	rCLKCON |= (1<<8);	//打开timer时钟
    	
    	rTCFG0 &= ~0xff;		//清零分频器
    	rTCFG0 |= prescaler;   	//设置预分频器
    	
    	rTCFG1 &= ~(0x0f<<0);
    	rTCFG1 |= (mux<<0);  	//设置选通输入
    	
    	//设置定时器的计数值
    	 rTCMPB0=compare;	//比较寄存器的值
    	 rTCNTB0 =count; //设定初值
    	 
    	  //启动定时器
    	 rTCON |=(1<<1); //更新TCNTB0和TCMPB0
    	 rTCON |= (1<<3);//启动自动重载
    	 rTCON &= ~(1<<1);//清零手动更新
    	 rTCON |= (1<<0);//启动定时器0
    }
    
    
    
    







    Pwm.h

    #ifndef __PWM_H_
    #define __PWM_H_
    #include "2440addr.h"
    #include "def.h"
    
    
    
    // compare 比较寄存器的值
    void Tomer0PwmInit(u8 prescaler,u8 mux,u16 count,u16 compare);
    
    
    
    
    #endif
    
    
    
    
    
    



     

  • 相关阅读:
    OpenStack kolla 多 region 部署配置
    docker rpm 下载地址
    kolla-ansible 源码下载
    Linux下常用压缩 解压命令和压缩比率对比
    Python 获取秒级时间戳与毫秒级时间戳
    OVS 内核KEY值提取及匹配流表代码分析
    字符串压缩 牛客网 程序员面试金典 C++ Python
    奇偶位交换 牛客网 程序员面试金典 C++ Python
    寻找下一个结点 牛客网 程序员面试金典 C++ java Python
    平分的直线 牛客网 程序员面试金典 C++ Python
  • 原文地址:https://www.cnblogs.com/dengxiaojun/p/4279414.html
Copyright © 2011-2022 走看看