s3c2440之PWM


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

 用到的寄存器:

                              GPBCON:引脚配置寄存器

                              GPBUP:端口使能上拉寄存器

                              GPBDAT:端口数据寄存器

                              TCFG0:配置两个8位预分频器

                              TCFG1:5路多路选择器和DMA模式选择寄存器

                              TCNTB0:  定时器0计数缓冲寄存器

                              TCMPB0: 定时器0比较缓冲寄存器

                              TCON:     定时器控制寄存器

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

	rGPBCON &= ~3;	//clear	2bits	
	rGPBCON |= 2;//set GPB0 as tout0, pwm output,10为GPB0第二功能,TOUT0的pwm输出

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

定时器输出时钟频率=PCLK ÷ (prescaler+1) ÷ divider

其中prescaler值由TCFG0决定,divider值由TCFG1决定,而prescaler只能取0~255之间的整数,divider只能取2、4、8和16。比如已知PCLK为50MHz,而我们想得到某一定时器的输出时钟频率为25kHz,则依据公式可以使prescaler等于249,divider等于8。有了这个输出时钟频率,理论上我们通过设置寄存器TCNTBn就可以得到任意与0.04毫秒(1÷25000×1000)成整数倍关系的时间间隔了。例如我们想要得到1秒钟的延时,则使TCNTBn为25000(1000÷0.04)即可。

	rTCFG0 &= ~0xff;//clear all
	rTCFG0 |= 15;			//prescaler = 15,15+1=16预分频值
	rTCFG1 &= ~0xf;//clear all
	rTCFG1 |= 2;			//mux = 1/8分频值___Tclk=PCLK/(prescaler+1)*mux

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

	rTCNTB0 = (PCLK>>7)/freq;//TCNTB0赋值,TCNTO0减为0时会加载TCNTB0的值
	rTCMPB0 = rTCNTB0>>1;	// 50%占空比TCNTO0递减过程中会与TCMPB0比较,相等时pwm置位

原理图如下:

s3c2440之PWM_第1张图片

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

	rTCON &= ~0x1f;			//清0~4位
	rTCON |= 0xb;			//1011_disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0;
	rTCON &= ~2;			//clear manual update bit必须清除
通常情况下,也可以将该IO口设置为非第二功能,即普通IO模式,即可停止PWM:

	rGPBCON &= ~3;			//set GPB0 as output,then stop pwm output
	rGPBCON |= 1;
	rGPBDAT &= ~1;//output 0


PWM.c源代码

实现对蜂鸣器声调的控制,频率加减,以及暂停。蜂鸣器接在GPB0.

void Buzzer_Freq_Set( U32 freq )
{
	rGPBCON &= ~3;	//clear	2bits	
	rGPBCON |= 2;//set GPB0 as tout0, pwm output,10为GPB0第二功能,TOUT0的pwm输出
		
	rTCFG0 &= ~0xff;//clear all
	rTCFG0 |= 15;			//prescaler = 15,15+1=16预分频值
	rTCFG1 &= ~0xf;//clear all
	rTCFG1 |= 2;			//mux = 1/8分频值___Tclk=PCLK/(prescaler+1)*mux
	rTCNTB0 = (PCLK>>7)/freq;//TCNTB0赋值,TCNTO0减为0时会加载TCNTB0的值
	rTCMPB0 = rTCNTB0>>1;	// 50%占空比TCNTO0递减过程中会与TCMPB0比较,相等时pwm置位
	rTCON &= ~0x1f;			//清0~4位
	rTCON |= 0xb;			//1011_disable deadzone, auto-reload, inv-off, update TCNTB0&TCMPB0, start timer 0;
	rTCON &= ~2;			//clear manual update bit必须清除
}

void Buzzer_Stop( void )
{
	rGPBCON &= ~3;			//set GPB0 as output,then stop pwm output
	rGPBCON |= 1;
	rGPBDAT &= ~1;//output 0
}

//***************************[ BOARD BEEP ]*******************************
void Beep(U32 freq, U32 ms)
{
	Buzzer_Freq_Set( freq ) ;
	Delay( ms ) ;
	Buzzer_Stop() ;
}

/****************************************************************************
【功能说明】蜂鸣器PWM测试
****************************************************************************/
void BUZZER_PWM_Test( void )
{
	U16 freq = 1000 ;//频率初值
	
	Uart_Printf( "\nBUZZER TEST ( PWM Control )\n" );//打印信息
   	Uart_Printf( "Press +/- to increase/reduce the frequency of BUZZER !\n" ) ;
	Uart_Printf( "Press 'ESC' key to Exit this program !\n\n" );
	
	Buzzer_Freq_Set( freq ) ;//pwm设置

    while( 1 )
    {
		U8 key = Uart_Getch();

		if( key == '+' )
		{
			if( freq < 20000 )//pwm++
				freq += 10 ;
				
			Buzzer_Freq_Set( freq ) ;
		}

		if( key == '-' )
		{
			if( freq > 11 )//pwm--
				freq -= 10 ;
				
			Buzzer_Freq_Set( freq ) ;
		}
		
		Uart_Printf( "\tFreq = %d\n", freq ) ;
		if( key == ESC_KEY )
		{
			Buzzer_Stop() ;//pwm stop
			return ;
		}

	}

}

效果图:


要想取得源代码,可以在 这里下载


你可能感兴趣的:(c,timer,IO,测试,output,delay)