mini 2440 PWM定时器(led闪烁) 代码下载
http://www.jyguagua.com/bbs/forum.php?mod=viewthread&tid=187&fromuid=1
PWM定时器的原理:
S3C2440的定时器一共有5个,均是16位定时器.根据S3C2440手册,我们可以知道0,1,2,3四个定时器都有PWM(Pulse Width Modulation)功能, 即他们都有一个输出引脚,可以通过定时器来控制引脚周期性的高低电平变化;定时器4没有输出引脚.
定时器部件的时钟源为:PCLK,首先通过两个8位的预分频处理器降低频率:定时器0,1共用一个预分频处理器, 定时器2,3,4共用第二个预分频处理器,紧接着第二级别分频处理器可以产生:2,4,8,16的分频以及外接TCLK0/TCLK1.每个定时器可以从这5中频率中选择.
1:程序初始化,设定:TCMPBn,TCNTBn这两个寄存器,代表的是定时器n的比较值跟初始计数值;
2:随之设置TCON寄存器启动定时器,这时,TCMPBn,TCMTBn这两个寄存器的值被装入TCMPn, TCMTn的寄存器中,在定时器n的工作频率下,TCMTn开始减1,其值可以通过读取TCNTOn寄存器得知;
3:当TCNTn的值等于TCMPn的时候,定时器n的输出管脚TOUTn反转,TCNTn继续减1计数;
4:当TCNTn的值减到0时, 其输出管脚TOUTn再次反转,并触发定时器n的中断(如果中断使能的话);
5:当TCNTn的值为0时,如果再TCON寄存器中将定时器n设为自动加载,则TCMPB0和TCNTB0寄存器的值被自动装入TCMP0和TCNT0寄存器中,下一个计数接着开始.
下面是代码:
head.S
/*中断向量表*/
b Reset
HandleUndef:
b HandleUndef
HandleSWI:
b HandleSWI
HandlePrefetchAbort:
b HandlePrefetchAbort
HandleDataAbort:
b HandleDataAbort
HandleNotUsed:
b HandleNotUsed
b HandleIRQ
HandleFIQ:
b HandleFIQ
Reset:
ldr sp, =4096 @下面都是C语言,设置栈
bl disable_watch_dog @关看门狗
bl clock_init @初始化时钟
bl memsetup @初始化Sdram
bl copy_steppingstone_to_sdram @拷贝前4k代码到0x30000000处
ldr pc, =on_sdram @进入中断
on_sdram:
msr cpsr_c, #0xd2 @进入中断模式
ldr sp, =4096 @设置栈,这个是中断模式的栈
msr cpsr_c, #0xdf @进入系统模式
ldr sp, =0x34000000 @系统模式栈
bl init_led @初始化led,全部关闭
bl timer0_init @初始化定时器
bl init_irq @设置irq寄存器
msr cpsr_c, #0x5f @开IRQ中断
ldr lr, =halt_loop
ldr pc, =main @调用main函数
halt_loop:
b halt_loop
HandleIRQ:
sub lr, lr, #4
stmdb sp!, {r0-r12, lr}
ldr lr, =int_return
ldr pc, =Timer0_Handle
int_return:
ldmia sp!, {r0-r12, pc}^
init.c
#include "s3c2440.h"
void disable_watch_dog(void);
void clock_init(void);
void memsetup(void);
void copy_steppingstone_to_sdram(void);
void init_led(void);
void timer0_init(void);
void init_irq(void);
void disable_watch_dog(void)
{
WTCON = 0;
}
void clock_init(void)
{
CLKDIVN = 0x05;
__asm__(
"mrc p15, 0, r1, c1, c0, 0\n"
"orr r1, r1, #0xc0000000\n"
"mcr p15, 0, r1, c1, c0, 0\n"
);
if ((GSTATUS1 == 0x32410002)) {
MPLLCON = mini2440PLL;
}
}
void memsetup(void)
{
volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;
/* 存储控制器13个寄存器的值 */
p[0] = 0x22011110; //BWSCON
p[1] = 0x00000700; //BANKCON0
p[2] = 0x00000700; //BANKCON1
p[3] = 0x00000700; //BANKCON2
p[4] = 0x00000700; //BANKCON3
p[5] = 0x00000700; //BANKCON4
p[6] = 0x00000700; //BANKCON5
p[7] = 0x00018005; //BANKCON6
p[8] = 0x00018005; //BANKCON7
/* REFRESH,
* HCLK=12MHz: 0x008C07A3,
* HCLK=100MHz: 0x008C04F4
*/
p[9] = 0x008C04f4;
p[10] = 0x000000B1; //BANKSIZE
p[11] = 0x00000030; //MRSRB6
p[12] = 0x00000030; //MRSRB7
}
void copy_steppingstone_to_sdram(void)
{
unsigned int *pdwSrc = (unsigned int *)0;
unsigned int *pdwDest = (unsigned int *)0x30000000;
while (pdwSrc < (unsigned int *)4096) {
*pdwDest = *pdwSrc;
pdwDest++;
pdwSrc++;
}
}
void init_led(void)
{
GPBCON = GPB5_out | GPB6_out | GPB7_out | GPB8_out;
}
void timer0_init(void)
{
TCFG0 = 99;
TCFG1 &= 0X02;
TCNTB0 = 25000;
TCON |= (1<<1);
TCON = 0X9;
}
void init_irq(void)
{
INTMSK &= (~(1<<10));
INTMOD &= (~(1<<10));
}
interrupt.c
#include "s3c2440.h"
void Timer0_Handle(void)
{
if (INTOFFSET == 10) {
GPBDAT = ~(GPBDAT & (0xf << 5));
}
SRCPND = 1 << INTOFFSET;
INTPND = INTPND;
}
interrupt.h
void EINT_Handle();
main.c
int main(void)
{
while(1);
return 0;
}
S3C2440.h
/*chip info register*/ #define GSTATUS1 (*(unsigned long *)0x560000b0) /*watch dog register*/ #define WTCON (*(unsigned long *)0x53000000) /*clock registers*/ #define CLKDIVN (*(volatile unsigned long *)0x4C000014) #define MPLLCON (*(volatile unsigned long *)0x4C000004) #define CLKCON (*(volatile unsigned long *)0x4C00000C) #define mini2440PLL ((0x7f<<12)|(0x02<<4)|(0x00)) /*sdram registers*/ #define MEM_CTL_BASE 0x48000000 #define SDRAM_BASE 0x30000000 /*gpio led registers*/ #define GPBCON (*(volatile unsigned long *)0x56000010) #define GPBDAT (*(volatile unsigned long *)0x56000014) #define GPB5_out (1<<(5*2)) #define GPB6_out (1<<(6*2)) #define GPB7_out (1<<(7*2)) #define GPB8_out (1<<(8*2)) /*key interrupt io registers*/ #define GPG0_eint (2) #define GPG3_eint (2<<(3*2)) #define GPG5_eint (2<<(5*2)) #define GPG6_eint (2<<(6*2)) /*interrupt registers*/ #define INTMSK (*(volatile unsigned long *)0X4A000008) #define INTOFFSET (*(volatile unsigned long *)0x4A000014) #define INTPND (*(volatile unsigned long *)0X4A000010) #define INTMOD (*(volatile unsigned long *)0X4A000004) #define SRCPND (*(volatile unsigned long *)0X4A000000) /*timer registers*/ #define TCFG0 (*(volatile unsigned long *)0x51000000) #define TCFG1 (*(volatile unsigned long *)0x51000004) #define TCON (*(volatile unsigned long *)0x51000008) #define TCNTB0 (*(volatile unsigned long *)0x5100000C)
timer.lds
SECTIONS {
. = 0x30000000;
.text : { *(.text) }
.rodata ALIGN(4) : {*(.rodata)}
.data ALIGN(4) : { *(.data) }
.bss ALIGN(4) : { *(.bss) *(COMMON) }
}
main.c
int main(void)
{
while(1);
return 0;
}
文章的脚注信息由WordPress的wp-posturl插件自动生成

微信扫一扫,打赏作者吧~![[分享]分享曾经做过的一个嵌入式系统application框架](http://www.jyguagua.com/wp-content/themes/begin/timthumb.php?src=http://www.jyguagua.com/wp-content/uploads/2015/03/1.jpg&w=280&h=210&zc=1)
![[转载]linux中的热插拔和mdev机制(深入理解嵌入式linux文件系统的制作)](http://www.jyguagua.com/wp-content/themes/begin/img/random/16.jpg)
![[2]real210 uboot_Makefile编译过程分析](http://www.jyguagua.com/wp-content/themes/begin/timthumb.php?src=http://www.jyguagua.com/wp-content/uploads/2013/08/ubootmake.jpg&w=280&h=210&zc=1)
