s3c2440中PWM应用

发布者:qinghong最新更新时间:2024-07-25 来源: cnblogs关键字:s3c244  PWM应用  定时器 手机看文章 扫描二维码
随时随地手机看文章

s3c2440芯片中一共有5个16位的定时器,其中有4个定时器(定时器0~定时器3)具有脉宽调制功能,因此用s3c2440可以很容易地实现PWM功能。下面就具体介绍如何实现PWM功能。

1、PWM是通过引脚TOUT0~TOUT3输出的,而这4个引脚是与GPB0~GPB3复用的,因此要实现PWM功能首先要把相应的引脚配置成TOUT输出。

2、再设置定时器的输出时钟频率,它是以PCLK为基准,再除以用寄存器TCFG0配置的prescaler参数,和用寄存器TCFG1配置的divider参数。

3、然后设置脉冲的具体宽度,它的基本原理是通过寄存器TCNTBn来对寄存器TCNTn(内部寄存器)进行配置计数,TCNTn是递减的,如果减到零,则它又会重新装载TCNTBn里的数,重新开始计数,而寄存器TCMPBn作为比较寄存器与计数值进行比较,当TCNTn等于TCMPBn时,TOUTn输出的电平会翻转,而当TCNTn减为零时,电平会又翻转过来,就这样周而复始。因此这一步的关键是设置寄存器TCNTBn和TCMPBn,前者可以确定一个计数周期的时间长度,而后者可以确定方波的占空比。由于s3c2440的定时器具有双缓存,因此可以在定时器运行的状态下,改变这两个寄存器的值,它会在下个周期开始有效。

4、最后就是对PWM的控制,它是通过寄存器TCON来实现的,一般来说每个定时器主要有4个位要配置(定时器0多一个死区位):启动/终止位,用于启动和终止定时器;手动更新位,用于手动更新TCNTBn和TCMPBn,这里要注意的是在开始定时时,一定要把这位清零,否则是不能开启定时器的;输出反转位,用于改变输出的电平方向,使原先是高电平输出的变为低电平,而低电平的变为高电平;自动重载位,用于TCNTn减为零后重载TCNTBn里的值,当不想计数了,可以使自动重载无效,这样在TCNTn减为零后,不会有新的数加载给它,那么TOUTn输出会始终保持一个电平(输出反转位为0时,是高电平输出;输出反转位为1时,是低电平输出),这样就没有PWM功能了,因此这一位可以用于停止PWM。

PWM有很多用途,在这里我利用开发板的资源,用它来驱动蜂鸣器,并通过改变脉宽来改变蜂鸣器发声的频率。下面的程序就是利用PWM来驱动蜂鸣器,脉宽从低到高,再从高到低,周而复始。我们还利用4个LED来指示频率的高低,最高时LED全亮,最低时LED全灭。并且我们用两个按钮来分别暂停蜂鸣器和重新开启蜂鸣器:

 

#define _ISR_STARTADDRESS 0x33ffff00

 

#define U32 unsigned int

typedef unsigned char BOOL;

#define TRUE       1  

#define FALSE     0

 

#define pISR_EINT0            (*(unsigned *)(_ISR_STARTADDRESS+0x20))

#define pISR_EINT1            (*(unsigned *)(_ISR_STARTADDRESS+0x24))

 

#define rSRCPND     (*(volatile unsigned *)0x4a000000)     //Interrupt request status

#define rINTMSK     (*(volatile unsigned *)0x4a000008)      //Interrupt mask control

#define rINTPND     (*(volatile unsigned *)0x4a000010)      //Interrupt request status

 

#define rGPBCON    (*(volatile unsigned *)0x56000010)      //Port B control

#define rGPBDAT    (*(volatile unsigned *)0x56000014)       //Port B data

#define rGPBUP     (*(volatile unsigned *)0x56000018) //Pull-up control B

 

#define rGPFCON    (*(volatile unsigned *)0x56000050)       //Port F control

 

#define rEXTINT0   (*(volatile unsigned *)0x56000088) //External interrupt control register 0

 

#define rTCFG0  (*(volatile unsigned *)0x51000000)      //Timer  configuration

#define rTCFG1  (*(volatile unsigned *)0x51000004)      //Timer  configuration

#define rTCON   (*(volatile unsigned *)0x51000008)      //Timer control

#define rTCNTB0 (*(volatile unsigned *)0x5100000c)       //Timer count buffer 0

#define rTCMPB0 (*(volatile unsigned *)0x51000010)      //Timer compare buffer 0

 

BOOL stop;

 

static void __irq Key1_ISR(void)         //暂停键,关闭蜂鸣器

{

       rSRCPND = rSRCPND | (0x1<<1);

       rINTPND = rINTPND | (0x1<<1);

      

       rTCON &= ~0x8;          //禁止定时器自动重载,即关闭定时器

       stop = TRUE;

}

 

void __irq Key4_ISR(void)          //重启键,开启蜂鸣器

{

       rSRCPND = rSRCPND | 0x1;

       rINTPND = rINTPND | 0x1;

      

       stop = FALSE;

}

 

 

void delay(int a)

{

       int k;

       for(k=0;k
              ;

}

 

void Main(void)

{

       int freq;

      

       rGPBCON = 0x155556;        //B0为TOUT0,B5~B8为输出,给LED

       rGPBUP  = 0x7ff;

       rGPFCON = 0xaaaa;             //F口为EINT,给按钮

       //按钮的一些必要配置

       rSRCPND = 0x07;

       rINTMSK = ~0x07;

       rINTPND =0x07;

       rEXTINT0 = 0x22;

      

       freq = 2500;

      

       rTCFG0 &= 0xFFFF00;

       rTCFG0 |= 0x31;    //prescal 是49

       rTCFG1 &= ~0xF;    //1/2,因为PCLK为50MHz,所以50MHz/50/2=500kHz

       rTCNTB0 = 5000;

       rTCMPB0 = freq;

       rTCON &= ~0x1F;       

       rTCON |= 0xf;              //死区无效,自动装载,电平反转,手动更新,定时器开启

       rTCON &= ~0x2 ;  //手动更新位清零,PWM开始工作

      

       pISR_EINT0 = (U32)Key4_ISR;

       pISR_EINT1 = (U32)Key1_ISR;

 

       stop = FALSE;

      

       rGPBDAT = ~0x60;              //两个LED亮

      

       while(1)

       {

              //频率递增

              for ( ; freq<4950 ; )

              {

                     freq+=10;

                     rTCMPB0 = freq;          //重新赋值

                     delay(20000);

                    

                     while (stop == TRUE)          //暂停

                     {

                            delay(1000);

                            if (stop ==FALSE)        //判断是否重启

                            {

                                   rTCON &= ~0x1F;

                                   rTCON |= 0xf;

                                   rTCON &= ~0x2 ;               //恢复PWM功能

                            }

                     }

                     //4个LED随着频率的高低,时灭时亮

                     if(freq == 100)

                            rGPBDAT = ~0x1e0;

                     if(freq == 1300)

                     rGPBDAT = ~0xe0;

                     if(freq == 2500)

                            rGPBDAT = ~0x60;

                     if(freq == 3700)

                            rGPBDAT = ~0x20;

                     if(freq == 4900)

                            rGPBDAT = ~0x0;

                           

              }

             

              //频率递减

              for( ; freq>50 ; )

              {

                     freq-=10;

                     rTCMPB0 = freq;

                     delay(20000);

                     while (stop == TRUE)

                     {

                            delay(1000);

                            if (stop ==FALSE)

                            {

                                   rTCON &= ~0x1F;

                                   rTCON |= 0xf;

                                   rTCON &= ~0x2 ;

                            }

                     }

                     if(freq == 100)

                            rGPBDAT = ~0x1e0;

                     if(freq == 1300)

                            rGPBDAT = ~0xe0;

                     if(freq == 2500)

                            rGPBDAT = ~0x60;

                     if(freq == 3700)

                            rGPBDAT = ~0x20;

                     if(freq == 4900)

                            rGPBDAT = ~0x0;

              }

       }    

}

 

这里还需要说明几点:

1、开发板上的蜂鸣器是高电平发声,低电平停止,而TOUT0定时无效时,是高电平输出,因此为了使PWM无效时,蜂鸣器不发声,我把输出电平进行了反转处理(置TCON中的输出反转位);

2、在这里,我是通过按键把stop标志变量置为FALSE来跳出while循环,重新开始蜂鸣,但不知什么原因,如果在while循环内不加一段等待时间,则永远不能跳出循环体,因此我不得不加了一个delay函数,让它等待一段时间。关于这个问题,我还给不出一个满意的解释,也不知是哪里出了问题!

[1] [1]
关键字:s3c244  PWM应用  定时器 引用地址:s3c2440中PWM应用

上一篇:2440的外部中断操作过程
下一篇:s3c2440 上txt 小说阅读器

推荐阅读最新更新时间:2024-11-05 19:33

STM32-systick系统定时器
systick系统定时器 系统定时器存在内核中,是24位的定时器,只能向下递减,嵌套在NVIC中 counter 在时钟的驱动下 在reload的初值开始向下递减计时到0,产生中断置位标志然后又从reload值开始重新递减计数,循环 定时时间计算 t=reload*(1/clk) clk=72M时,t=72*(1/72m)=1us clk=72M时,t=72000*(1/72m)=1ms clk=72M时,t=72000000*(1/72m)=1s 1s=1000MS =1000 000US=1000 000 000NS sysTick属于内核中的外设,他的中断优先级和外设的中断优先级相比,哪个
[单片机]
STM32-systick系统<font color='red'>定时器</font>
STM32学习日志——定时器中断实验
今天学习的是通用定时器及其中断,首先是内部时钟的选择,定时器的时钟Tclk是由APB1时钟乘以1或2决定的,至于是1还是2,要看APB1的分频系数(AHB/APB1),如果为1,则乘以1,否则乘以2。接着就可以根据我们想设定的时间Tout,去配置ARR跟PSC,这两个数是存在16位的寄存器,所以他们的范围为(0-65535),在这个范围内任意取值,满足公式即可。如果我么要配置500ms,可将ARR配置为2499,PSC配置为14399。也就是定时器计数的一个周期为500ms。(ARR为自动重装载值,PSC为Tclk的预分频系数) 根据步骤去写程序就很简单了。 实现功能:通过定时器的中断控制一个绿灯翻转,时间为500ms
[单片机]
STM32学习日志——<font color='red'>定时器</font>中断实验
STM32 定时器中断配置心得【自用】
1.IO配置 略 2.TIM配置 void TIM2_Config(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); /* Time base configuration */ TIM_TimeBaseStructure.TIM_Period =359999; TIM_TimeBaseStructure.TIM_Prescaler = 99; TIM_TimeBas
[单片机]
msp430g2231基础定时器设置
本实验的目的是了解用于执行对MSP430 Value Line设备的初始化过程的步骤。在这个练习中,您将编写初始化代码,并运行该设备使用各种时钟资源。 1、写初始化代码 2、运行CPU的MCLK的来源方式:VLO 、32768晶体、DCO 3、主体程序部分 4、观察LED闪光灯速度 MSP430时钟: 1、在MSP430单片机中一共有三个时钟源: 一个LFXT1CLK,为低速/高速晶振源,通常接32.768khz,也可以接(400khz~8Mhz); 一个为XT2CLK,外接标准高速晶振,通常是接8Mhz,也可以接(400khz~8Mhz); 还有一个叫DCOCLK,为内部晶振,有RC震荡回路构成。 2、在MSP4
[单片机]
STM8单片机ADC采样功能通过定时器触发
  在使用STM8单片机的ADC功能时,读取ADC数据时一般有两种方式,一种是通常不断地读取采样标志位,来判断ADC采样是否结束,一种是通过中断的方式来通知系统采样是否结束。   有时候采样ADC数据的时候,需要按照一定的时间间隔,定点的去采样数据。一般使用的方式就是通过定时器定时,然后在定时中断函数中再去读取ADC采样的数据。但是这种方式采样的时间是不固定的,比如进入定时器中断后,ADC采样刚结束,就可以直接使用当前采样到的数据。但是如果运气不好的话,进入定时中断后,ADC采样刚开始,那么此时就需要等到ADC采样结束后,才能使用数据。这样就好导致每次读取ADC数据时还会有随机的一段等到ADC数据的延时。   通常查阅ST
[单片机]
STM8单片机ADC采样功能通过<font color='red'>定时器</font>触发
MSP430F5529 DriverLib 库函数学习笔记(七)定时器B
平台:Code Composer Studio 10.3.1 MSP430F5529 LaunchPad™ Development Kit (MSP‑EXP430F5529LP) 硬知识 16位定时器B(Timer_B)和Timer_A一样,是MSP430单片机的重要资源。Timer_B往往比Timer_A功能更强大一些,MSP430F5529单片机的Timer_B定时器具有7个捕获/比较寄存器。 Timer_B特点及结构 Timer_B定时器具有以下特点:  具有4种工作模式和4种可选计数长度的异步16位定时/计数器;  参考时钟源可配置;  高达7个可配置的捕获/比较寄存器;  具有PWM输出能
[单片机]
MSP430F5529 DriverLib 库函数学习笔记(七)<font color='red'>定时器</font>B
单片机定时器与单片机计数器
  本文主要介绍单片机芯片解密的相关基础知识:单片机计数器和单片机定时器。   一、计数概念的引入   在介绍单片机计数器和定时器之前,先从选票的统计谈起:画“正”。这就是计数,生活中计数的例程处处可见。例:录音机上的计数器、家里面用的电度表、汽车上的里程表等等,再举一个工业生产中的例程,线缆行业在电线生产出来之后要计米,也就是测量长度,怎么测法呢?用尺量?不现实,太长不说,要一边做一边量呢,怎么办呢?行业中有很巧妙的办法,用一个周长是1米的轮子,将电缆绕在上面一周,由线带轮转,这样轮转一周不就是线长1米嘛,所以只要记下轮转了多少圈,就能知道走过的线有多长了。   二、单片机计数器的容量   从一个生活中的例程看起:一个水盆在
[单片机]
定时器的输出比较模式产生的PWM波的频率计算
定时器的输出比较模式产生的PWM波的频率计算的公式:72M/((2*(arr+1))*(psc+1) ) 比如设置: PWM_Init(1000-1,72-1); (PWM_Init(arr,psc);) 则每路PWM频率为500Hz 。 PWM_Init(arr,psc) { TIM_TimeBaseStructure.TIM_Period = arr; TIM_TimeBaseStructure.TIM_Prescaler =psc; }
[单片机]
小广播
设计资源 培训 开发板 精华推荐

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

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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