【JZ2440笔记】定时器

发布者:innovator8最新更新时间:2022-10-27 来源: csdn关键字:JZ2440  定时器 手机看文章 扫描二维码
随时随地手机看文章

一、前言

定时器可以说是任何单片机中的标配外设了,学过那么多种MCU,定时器模块非常简单,几乎都是一样的工作流程。用一个寄存器不断的计数来标记经过的时间,这个计数寄存器溢出后可以触发中断等事件,定时器模块一般都捆绑有PWM功能,就是再加一个比较寄存器,当比较寄存器中的值与计数器值相等时改变IO的电平,实现PWM控制。当然,S3C2440定时器模块也是一样的。


二、实验目标

采用定时器0实现定时器中断,每隔1秒改变1次开发板上LED的亮灭状态。


三、分析

S3C2440定时器模块方框图如下:

S3C2440A 有 5 个 16 位定时器。其中定时器 0、1、2 和 3 具有脉宽调制(PWM)功能。定时器 4 是一个无输出引脚的内部定时器。定时器 0 还包含用于大电流驱动的死区发生器。定时器 0 和 1 共用一个 8 位预分频器,定时器 2、3 和 4 共用另外的 8 位预分频器。每个定时器都有一个可以生成 5 种不同分频信号(1/2,1/4,1/8,1/16 和 TCLK)的时钟分频器。每个定时器模块从相应 8 位预分频器得到时钟的时钟分频器中得到其自己的时钟信号。8 位预分频器是可编程的,并且按存储在 TCFG0 和 TCFG1 寄存器中的加载值来分频 PCLK。定时计数缓冲寄存器(TCNTBn)包含了一个当使能了定时器时的被加载到递减计数器中的初始值。定时比较缓冲寄存器(TCMPBn)包含了一个被加载到比较寄存器中的与递减计数器相比较的初始值。这种 TCNTBn 和TCMPBn 的双缓冲特征保证了改变频率和占空比时定时器产生稳定的输出。


每个定时器有它自己的由定时器时钟驱动的 16 位递减计数器。当递减计数器到达零时,产生定时器中断请求通知 CPU 定时器操作已经完成。当定时器计数器到达零时,相应的 TCNTBn 的值将自动被加载到递减计数器以继续下一次操作。然而,如果定时器停止了,例如,在定时器运行模式期间清除 TCONn 的定时器使能位,TCNTBn的值将不会被重新加载到计数器中。


TCMPBn 的值是用于脉宽调制(PWM)。当递减计数器的值与定时器控制逻辑中的比较寄存器的值相匹配时定时器控制逻辑改变输出电平。因此,比较寄存器决定 PWM 输出的开启时间(或关闭时间)。


TCFG0设置对PCLK的分频:

TCFG1设置MUX的分频:

TCON可以设置定时器的开、关、使能自动重装载等功能。

设置TCON的时候有个注意点,就是要先设置手动更新位,然后再清除手动更新位。设置手动更新位的时候预装载值进入到TCNTO0,再清除手动更新位后下次定时器计数值到0后自动取TCNTB0中的值装载入TCNTO0中进行下一次递减计数。所以想要循环定时中断的话设置了手动更新位后要立刻再清除掉。


TCNTB0可以设置初始计数值,注意想要读取当前计数值不是读取TCNTB0,而是要去读取TCNTO0。

四、代码编写

代码分为以下几个文件:


head.S:启动文件。


main.c:各种C函数。


Makefile:编译代码。


文件内容分别如下:


head.S


@*************************************************************************

@ File:head.S

@*************************************************************************       

.text

.global _start

_start:

@******************************************************************************       

@ 中断向量,本程序中,除Reset和HandleIRQ外,其它异常都没有使用

@******************************************************************************       

    b   Reset

@ 0x04: 未定义指令中止模式的向量地址

HandleUndef:

    b   HandleUndef 

 

@ 0x08: 管理模式的向量地址,通过SWI指令进入此模式

HandleSWI:

    b   HandleSWI

@ 0x0c: 指令预取终止导致的异常的向量地址

HandlePrefetchAbort:

    b   HandlePrefetchAbort

@ 0x10: 数据访问终止导致的异常的向量地址

HandleDataAbort:

    b   HandleDataAbort

@ 0x14: 保留

HandleNotUsed:

    b   HandleNotUsed

@ 0x18: 中断模式的向量地址

    b   HandleIRQ

@ 0x1c: 快中断模式的向量地址

HandleFIQ:

    b   HandleFIQ

    

Reset: 

ldr     sp, =4096                       @设置堆栈,因为要调用C语言函数 

bl     disable_watch_dog               @关WATCH DOG

    bl      init_system_clk                 @初始化FCLK到400MHz,PCLK到50MHz

    msr cpsr_c, #0xd2       @ 进入中断模式

    ldr sp, =3072           @ 设置中断模式栈指针

    msr cpsr_c, #0xd3       @ 进入管理模式

    ldr sp, =4096           @ 设置管理模式栈指针,

                            @ 其实复位之后,CPU就处于管理模式,

                            @ 前面的“ldr sp, =4096”完成同样的功能,此句可省略

    msr cpsr_c, #0x53       @ 设置I-bit=0,开IRQ中断

    ldr lr, =halt_loop      @ 设置返回地址

    ldr pc, =main           @ 调用main函数

halt_loop:

    b   halt_loop

 

HandleIRQ:

    sub lr, lr, #4                  @ 计算返回地址

    stmdb   sp!,    { r0-r12,lr }   @ 保存使用到的寄存器

                                    @ 注意,此时的sp是中断模式的sp

                                    @ 初始值是上面设置的3072

    

    ldr lr, =int_return             @ 设置调用ISR即EINT_Handle函数后的返回地址  

    ldr pc, =Timer0_Handle            @ 调用中断服务函数

int_return:

    ldmia   sp!,    { r0-r12,pc }^  @ 中断返回, ^表示将spsr的值复制到cpsr


main.c


#define BYTE unsigned char

#define WORD unsigned short

#define DWORD unsigned int 

 

/* WOTCH DOG register */

#define REG_WTCON               (*(volatile unsigned long *)0x53000000)

 

/* Sys Clk Config */

#define REG_CLKDIVN             (*(volatile unsigned long *)0x4C000014)

#define REG_CAMDIVN             (*(volatile unsigned long *)0x4C000018)

#define REG_MPLLCON             (*(volatile unsigned long *)0x4C000004)

 

/* GPIO Configure*/

#define GPFCON (*(volatile unsigned long *)0x56000050)

#define GPFDAT (*(volatile unsigned long *)0x56000054)

#define GPFUP (*(volatile unsigned long *)0x56000058)

 

#define GPGCON (*(volatile unsigned long *)0x56000060)

#define GPGDAT (*(volatile unsigned long *)0x56000064)

#define GPGUP (*(volatile unsigned long *)0x56000068)

 

#define REG_EXTINT0 (*(volatile unsigned long *)0x56000088)

#define REG_EXTINT1 (*(volatile unsigned long *)0x5600008C)

 

/* interrupt Configure */

 

#define REG_EINTMASK (*(volatile unsigned long *)0x560000A4)

#define REG_INTMSK (*(volatile unsigned long *)0X4A000008)

#define REG_INTOFFSET (*(volatile unsigned long *)0x4A000014)

 

#define REG_EINTPEND (*(volatile unsigned long *)0x560000A8)

#define REG_SRCPND (*(volatile unsigned long *)0X4A000000)

#define REG_INTPND (*(volatile unsigned long *)0X4A000010)

 

// #define REG_INTSUBMSK (*(volatile unsigned long *)0x560000A8)

// #define REG_SUBSRCPND (*(volatile unsigned long *)0X4A000018)

 

/* timer Configure */

#define REG_TCFG0 (*(volatile unsigned long *)0x51000000)

#define REG_TCFG1 (*(volatile unsigned long *)0x51000004)

#define REG_TCON (*(volatile unsigned long *)0x51000008)

#define REG_TCNTB0 (*(volatile unsigned long *)0x5100000C)

 

void disable_watch_dog();

void init_system_clk();

void init_led();

void init_timer0();

void Timer0_Handle();

 

/*上电后,WATCH DOG默认是开着的,要把它关掉 */

void disable_watch_dog()

{

REG_WTCON = 0;

}

 

 

void init_system_clk()

{

    //HCLK = FCLK/4, 当 CAMDIVN[9] = 0 时

    //PCLK 设置为 HCLK/2 

    //完成配置FCLK : HCLK : PCLK = 1 : 1/4 : 1/8,DIVN_UPLL是USB的时钟不用管

    REG_CLKDIVN = (2 << 1) | (1 << 0);

 

    /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */

__asm__(

    "mrc    p15, 0, r1, c1, c0, 0n"        /* 读出控制寄存器 */ 

    "orr    r1, r1, #0xc0000000n"          /* 设置为“asynchronous bus mode” */

    "mcr    p15, 0, r1, c1, c0, 0n"        /* 写入控制寄存器 */

    );

 

    //m=MDIV+8, p=PDIV+2, s=SDIV, Mpll = ( 2 × m × Fin ) / ( p × 2^s )

    //FCLK = (2 * (92 + 8) * 12000000) / ((1 + 2) * 2) = 400000000 = 400MHz

    //配置完MPLL后时钟停振,CPU停止运行等待时钟输出稳定,之后FCLK=400MHz,HCLK=100MHz,PCLK=50MHz */

    REG_MPLLCON = (92<<12)|(1<<4)|(1<<0);

}

 

void init_led()

{

GPFCON &= ~((DWORD)(3 << (2 * 4)) | (3 << (2 * 5)) | (3 << (2 * 6)));

GPFCON |= ((DWORD)(1 << (2 * 4)) | (1 << (2 * 5)) | (1 << (2 * 6))); //GPF4、GPF5、GPF6输出模式

 

GPFDAT |= (1 << 4) | (1 << 5) | (1 << 6);   //输出高电平,LED全灭

}

 

void init_timer0()

{

//Prescaler 0设置250分频

REG_TCFG0 &= ~((DWORD)0xFF << 0);

REG_TCFG0 |= ((DWORD)(250 - 1) << 0);

 

//MUX 0 设置4分频

REG_TCFG1 &= ~((DWORD)0xF << 0);

REG_TCFG1 |= ((DWORD)1 << 0);

 

//设置定时器0自动重装载值

REG_TCNTB0 = 50000;

 

//手动更新 TCNTB0 和 TCMPB0

REG_TCON |= ((DWORD)1 << 1);

//清除手动更新 TCNTB0 和 TCMPB0,不加这句定时器不运行

REG_TCON &= ~((DWORD)1 << 1);

 

//开定时器0中断

REG_INTMSK &= ~((DWORD)1 << 10);

 

//启动定时器0,使能自动重装载

REG_TCON |= ((DWORD)9 << 0);

}

 

void Timer0_Handle()

{

BYTE bIntOffset = REG_INTOFFSET;

 

switch(bIntOffset)

{

//定时器0中断

case 10:

GPFDAT ^= ((DWORD)1 << 4); //电平翻转

break;

 

default:

break;

}

 

//清中断

REG_SRCPND = (DWORD)1 << bIntOffset; 

REG_INTPND = REG_INTPND; 

}

 

int main()

{

init_led();

init_timer0();

 

while(1);

 

return 0;

}


Makefile


objs := head.o main.o

 

timer.bin: $(objs)

 

arm-linux-ld -Ttext 0x0000000 -g -o timer_elf $^

arm-linux-objcopy -O binary -S timer_elf $@

arm-linux-objdump -D -m arm timer_elf > timer.dis

%.o:%.c

arm-linux-gcc -Wall -O2 -c -o $@ $<

 

%.o:%.S

arm-linux-gcc -Wall -O2 -c -o $@ $<

 

clean:

rm -f timer.bin timer_elf timer.dis *.o


执行make命令后将生成的bin文件烧写到JZ2440开发板的NandFlash中,然后设置Nand启动,可以看到LED1每隔1秒改变1次亮灭状态。


五、实验总结

定时器的配置方式和寄存器基本都和单片机的一样,也就那些基本的操作。

关键字:JZ2440  定时器 引用地址:【JZ2440笔记】定时器

上一篇:【JZ2440笔记】DMA
下一篇:【JZ2440笔记】串口通信(中断方式)

推荐阅读最新更新时间:2024-11-17 11:45

单片机定时器设置的门铃
这是一个单片机定时器设置的门铃程序,附带源代码及文档,用定时器设计的门铃说明:按下按键时蜂鸣器发出叮咚的门铃声。 程序 /* 下载程序后按键K1按下就会触发蜂鸣器门铃“叮咚”响 */ #include reg52.h typedef unsigned char u8; typedef unsigned int u16; sbit beep=P1^5; sbit k1=P3^1; u8 ding,dong,flag,stop; u16 n; void delay(u16 i) { while(i--); } void time0init() //定时器0初始化 { TMOD=0X01; //
[单片机]
探索STC12C5A60S2定时器
  STC12C5A60S2单片机集成了共4个16位定时器,两个与传统8051兼容的定时器/计数器,16位定时器T0和T1,没有定时器2,但有独立波特率发生器 做串行通讯的波特率发生器,再加上2路PCA模块可再实现2个16位定时器;   1. 基本特性   STC12C5A60S2单片机集成了两个16位定时/计数器。   1)寄存器   1.1)TMOD 定时器工作方式控制寄存器,包括13位寄存器、16位寄存器、8位寄存器等;   1.2)TCON 定时器控制寄存器,主要包括定时器启动控制位等;   1.3)AUXR 辅助寄存器,用以设置分频;默认12分频   1.4)TH0/1:定时器高8位寄存器   1.5)TL0/1:定时器
[单片机]
探索STC12C5A60S2<font color='red'>定时器</font>
STM8S003F3使用总结——定时器
STM8S003F3有三个定时器,分别为16位高级定时器TIM1、16位通用定时器TIM2和8位基础定时器TIM4。其中,TIM1和TIM2支持PWM输出,本项目中用到了TIM1-CH1和TIM2-CH1两个通道作为PWM输出,以及TIM4作为时基,下面进入正文。 编译环境:IAR for STM8 3.10.2 库版本:V2.2.0 1.定时器 关于定时器没什么好说的,直接看下配置代码 void TIM1_Init(u16 psc, u16 arr, u16 duty) { TIM1_TimeBaseInit(psc, TIM1_COUNTERMODE_UP, arr, 0); TIM1_OC1Init(T
[单片机]
STM8S003F3使用总结——<font color='red'>定时器</font>
STM32 定时器正交编码器模式 寄存器配置程序
void Encoder_Init(void) { RCC- APB1ENR|=1 1; //TIM3时钟使能 RCC- APB2ENR|=1 2; //使能PORTA时钟 GPIOA- CRL&=0XF0FFFFFF;//PA6 GPIOA- CRL|=0X04000000;//浮空输入 GPIOA- CRL&=0X0FFFFFFF;//PA7 GPIOA- CRL|=0X40000000;//浮空输入 TIM3- DIER|=1 0; //允许更新中断 TIM3- DIER|=1 6; //允许触发中断 MY_NVIC_Init(1,3,TIM3_IRQChannel,2); TIM3- PSC = 0x0;/
[单片机]
PIC16F877A定时器的学习
由于实时数据的仿真需要用到定时器产生数据,今天晚上完成PIC16F877A产生正弦波形,并将波形数据发送到上位机! 这是一个三角波的仿真程序,并通过串口发送到上位机 #include stdio.h #include stdlib.h #include math.h #include main.h #include t232.h #include lcd.h #include timer.h //define global variable bank1 uchar flag =0 ;//利用flag判断中断时间是否到了! bank1 char dat ; bank2 char str = shan dong qi
[单片机]
VxWorks下的异步通用定时器设计
   1 概 述   VxWorks是WindRiver公司开发的高性能实时嵌入式操作系统内核。在应用软件开发过程中经常会用到定时器。VxWorks下要实现定时功能有2个途径:一,借助taskDelay函数实现;二,使用VxWorks提供的看门狗(watchdog)。使用taskDelay函数实现定时器的缺点在于它是基于任务的,任务优先级会导致定时不准。看门狗基于系统时钟中断,定时精度大大优于前者,但是对用户的回调函数有诸多限制(如不允许使用semTake、printf等需要等待获取某种资源的函数,否则会引起死机)。另外,看门狗只触发一次回调函数,如果用户需要周期定时器就需要重新启动看门狗。   本文设计了基于看门狗机制的
[嵌入式]
N76E003 看门狗定时器 WDCON
一、复位功能配置 N76E003 提供一个看门狗定时器(WDT),它可以配置成一个超时复位定时器用于复位整个设备。一旦由于外界干扰设备进入非正常状态或挂起,看门狗可以复位恢复系统。 WDTEN (CONFIG4 )初始化WDT工作在超时复位定时器或通用定时器模式。 二、通用定时器配置 WDT带一个独立的分频器用于分频10K LIRC时钟。分频器的时钟分频可选,来决定超时间间隔。当达到超时间隔,系统会被从空闲或掉电模式唤醒,且如果WDT中断使能会产生一个中断事件。如果WDT初始化为一个超时复位定时器,在经过一个延时周期而软件没有任何动作后会产生系统复位。 超时复位定时器 当配置 CONFIG 位 WDTEN (CON
[单片机]
N76E003 看门狗<font color='red'>定时器</font> WDCON
51单片机内部定时器/计数器实验
一、实验内容 使用MCS-51内部定时/计数器,定时1秒钟,CPU运用定时中断方式,实现每1秒钟输出状态发生一次反转,即发光管每隔1秒钟亮一次(P1.7接LED)。 根据实验内容编写一个程序,并在实验仪器上调试和验证。 二、仿真图 三、代码 C语言实现: # include reg52.h # include intrins.h # define uint unsigned int # define uchar unsigned char sbit LED=P1^0; uchar t,temp; void init(); void main() { t=0; init(); whil
[单片机]
51单片机内部<font color='red'>定时器</font>/计数器实验
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved