裸机程序开发之蜂鸣器程序
程序实现了控制蜂鸣器输入pwm频率和开关功能。输入数字1开启蜂鸣器,输入数字0关闭蜂鸣器,输入字符+增加蜂鸣器输入pwm频率,输入字符-减少蜂鸣器输入pwm频率。代码如下:
1 #include "def.h"
2 #include "option.h"
3 #include "2440addr.h"
4 #include "2440lib.h"
5 #include "2440slib.h"
6
7 void dely(U32 tt)
8 {
9 U32 i;
10 for(;tt>0;tt--)
11 {
12 for(i=0;i<10000;i++){}
13 }
14 }
15
16 int Main(int argc, char **argv)
17 {
18 int i;
19 U8 key;
20 U32 mpll_val=0;
21 int data;
22 int readLength = 0;
23 int buzzerWork = 0;
24 U16 freq = 1000;
25
26 mpll_val = (92<<12)|(1<<4)|(1);
27
28 //init FCLK=400M, so change MPLL first
29 ChangeMPllValue((mpll_val>>12)&0xff, (mpll_val>>4)&0x3f, mpll_val&3);
30 ChangeClockDivider(key, 12);
31
32 Uart_Init( 0,115200 );
33 Uart_Select( 0 );
34 Uart_SendByte('\n');
35 Uart_Printf("<***********************************************>\n");
36 Uart_Printf(" Uart Test Program V1.0\n");
37 Uart_Printf(" Input 1:Buzzer Work.0:Buzzer not work.\n");
38 Uart_Printf( "Press +/- to increase/reduce the frequency of BUZZER !\n" ) ;
39 Uart_Printf("<***********************************************>\n");
40 //Enable NAND, USBD, PWM TImer, UART0,1 and GPIO clock,
41 rCLKCON = 0xfffff0;
42
43 MMU_DisableICache();
44 MMU_DisableDCache();
45
46 rGPBCON = 0x155555;
47
48 while(1)
49 {
50 U8 key = 0;
51 Uart_Printf("\nPlease input command : \n");
52 key = Uart_Getch();
53 Uart_Printf("Your input string : \n");
54 Uart_SendByte(key);
55 if(key == '1'){
56 buzzerWork = 1;
57 Buzzer_Freq_Set( freq ) ;
58 }else if(key == '0'){
59 buzzerWork = 0;
60 Buzzer_Stop();
61 }else if(key == '+'){
62 if(buzzerWork == 1){
63 if( freq < 20000 )
64 freq += 10 ;
65 Buzzer_Freq_Set( freq ) ;
66 }
67 }else if(key == '-'){
68 if(buzzerWork == 1){
69 if( freq > 11 )
70 freq -= 10 ;
71 Buzzer_Freq_Set( freq ) ;
72 }
73 }else{
74 }
75 }
76 return 0;
77 }
蜂鸣器的工作发声原理是:方波信号输入谐振装置转换为声音信号输出,蜂鸣器的工作发声原理图如下:
图3-3-1
开发板对应的原理图为:
图3-3-2
输出GPBO的引脚为GPB0。
Main函数Line57 Buzzer_Freq_Set( freq )中,Buzzer_Freq_Set的定义为:
void Buzzer_Freq_Set( U32 freq )
{
rGPBCON &= ~3; //set GPB0 as tout0, pwm output
rGPBCON |= 2;
rTCFG0 &= ~0xff;
rTCFG0 |= 15;
rTCFG1 &= ~0xf;
rTCFG1 |= 2;
rTCNTB0 = (PCLK>>7)/freq;
rTCMPB0 = rTCNTB0>>1;
rTCON &= ~0x1f;
rTCON |= 0xb;
rTCON &= ~2;
}
GPBCON(PORT B CONTROL)寄存器,用于控制B端口所有引脚的状态。从下表可知GPB0的引脚被设置为了TOUT0,TOUT表示PWM输出。
定时器0和定时器1共享一个8位的预分频器。定时器0自带一个可以分成5中不同信号(1/2,1/4,1/8,1/16以及TCLK)的时钟信号分频器。定时器模块从时钟分频器接收时钟信号,时钟分频器又从8位预分频器接收时钟信号。8位预分频器可编程并且将PCLK信号进行分频。控制寄存器主要为TCFG0和TCFG1。控制原理参看图3-3-4。
TCFG0(TIMER CONFIGURATION REGISTER0)用于配置2个8位预分频器。
定时器输入时钟频率=PCLK/(预分频器的值+1)/分频器的值。
图3-3-5定义了预分频器的值,代码设置了15。
图3-3-6定义了分频器的值,代码设置了1/8。
图3-3-3
图3-3-4. 16位PWM定时器模块图
图3-3-5
图3-3-6
TCNTB0和TCMPB0定时器分别设置定时0的计算器缓存值和比较缓存值。
当定时器为启用时,定时器计数缓冲寄存器(TCNTBn)具有一个初始值。定时器比较缓冲寄存器(TCMPBn)具有一个初始值,该初始值被加载到比较寄存器中以与递减计数器值进行比较。 TCNTBn和TCMPBn的双重缓冲功能使定时器在频率和占空比改变时产生稳定的输出。
每个定时器都有自己的16位递减计数器,由定时器时钟驱动。当倒数计数器到达时零时,将产生定时器中断请求,以通知CPU定时器操作已完成。当定时器计数器达到零时,相应的TCNTBn的值将自动加载到递减计数器中继续下一个操作。但是,如果定时器停止,例如,通过清除TCONn的定时器使能位在定时器运行模式下,TCNTBn的值不会重新加载到计数器中。
TCMPBn的值用于脉冲宽度调制(PWM)。当递减计数器的值与定时器控制逻辑中比较寄存器的值匹配时,计时器控制逻辑更改输出电平。因此,比较寄存器确定PWM输出的开启时间(或关闭时间)。即设置PWM的占空比。
图3-3-7
TCON(TIMER CONTROL)寄存器用于控制定时器状态。通过图3-3-8可知,代码设置的状态为:启动定时器,不手动更新定时器,不反转定时器,间隔模式,不进行死区操作。
图3-3-8
Main函数Line60 Buzzer_Stop()中Buzzer_Stop的定义为:
void Buzzer_Stop( void )
{
rGPBCON &= ~3; //set GPB0 as output
rGPBCON |= 1;
rGPBDAT &= ~1;
}
根据上面定义可知,此处代码将端口B的引脚0定义为输出引脚,并设置为低电平,因此引脚不再发出pwm信号给蜂鸣器,蜂鸣器不发声。
实际运行程序设置的2中频率的pwm波形图如下: