裸奔程序之定时器&PWM

     开发环境:ADS1.2

     实验实现功能:利用TQ2440开发板与PC机通过串口连接,

                              通过PC机的“+”“-”“Esc”键来控制开发板蜂鸣器的频率。

——————————————————————————————————————————————

下面是自己写的main.c程序

——————————————————————————————————————————————

#include "2440addr.h"
#include "2440lib.h"          //这个只使用了这个文件的延迟函数,和串口有关的函数

void Beep_Freq_Set( U32 freq )
{

      rGPBCON &=~3;
      rGPBCON |=2;           //设置GPB0为OUT0

      rGPBUP=0x0;            //使能上拉

      rTCFG0 &=~0xff;
      rTCFG0 |=15;            //预分频值为15

      rTCFG1 &=~0x0f;
      rTCFG1 |=0x02;       //分频值为8

      rTCNTB0 = (PCLK>>7)/freq;   //设定定时器0计数缓冲器的值  
      rTCMPB0 = rTCNTB0>>1;     // 定时器0比较缓冲器的值,PWM输出占空比50%  
 
      rTCON &= ~0x1f; 
      rTCON |= 0xb;               //自动重载,关闭变相,手动更新,开启定时器0  
      rTCON &= ~2;              //清除手动更新位  

 
void Beep_Stop( void ) 

      rGPBCON &= ~3;          //set GPB0 as output  
      rGPBCON |= 1; 
      rGPBDAT &= ~1;       //输出低电平  

void Beep_Init(U32 freq, U32 ms) 

      Beep_Stop() ;
      Delay( ms ) ; 
      Beep_Freq_Set( freq ) ;  
}
 
void Main()
{
      U16 freq=800;

     SelectFclk(2);  //设置系统时钟 400M    
     ChangeClockDivider(2, 1);      //设置分频 1:4:8
     CalcBusClk();           //计算总线频率

     rGPHCON &=~((3<<4)|(3<<6));  
     rGPHCON |=(2<<4)|(2<<6);    //GPH2--TXD[0];GPH3--RXD[0]  
     rGPHUP=0x00;        //使能上拉功能
    
     Uart_Init(0,115200);
     Uart_Select(0);
 
     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" );

     Beep_Init( freq ,50) ;

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

            if( key == '+' )
            {
                    if( freq < 2000 )  //lci  20000
                    freq += 10 ;
   
                    Beep_Freq_Set( freq ) ;
            }

           if( key == '-' )
           {
                   if( freq > 11 )
                   freq -= 10 ;
   
                   Beep_Freq_Set( freq ) ;
           }
 
           Uart_Printf( "\tFreq = %d\n", freq ) ;
           if( key == ESC_KEY )
           {
                   Beep_Stop() ;
                   return ;
           }

    }
}

—————————————————————————————————————————————————

 

   我们来首先上来先分析main函数,SelectFclk(2);  //设置系统时钟 400M

void SelectFclk(int i)                                         //from  2440lib.c
{
       U32 mpll_val=0;
       switch ( i )

      {
               case 0:  mpll_val = (92<<12)|(4<<4)|(1);     break;      //200M
               case 1:  mpll_val = (67<<12)|(1<<4)|(1);     break;     //300M
               case 2:  mpll_val = (92<<12)|(1<<4)|(1);     break;    //400M
               case 3:  mpll_val = (102<<12)|(1<<4)|(1);   break;   //440M!!!
               default:  mpll_val = (92<<12)|(1<<4)|(1);  break;
       }
     rMPLLCON = mpll_val;
}

—————————————————————————————————————————————————

     接着执行 ChangeClockDivider(2, 1);      //设置分频 1:4:8

 

void ChangeClockDivider(int hdivn,int pdivn)          //from 2440lib.c
{
     // hdivn,pdivn FCLK:HCLK:PCLK
     //     0,0         1:1:1
     //     0,1         1:1:2
     //     1,0         1:2:2
     //     1,1         1:2:4
     //     2,0         1:4:4
     //     2,1         1:4:8
     //     3,0         1:3:3
     //     3,1         1:3:6
    rCLKDIVN = (hdivn<<1) | pdivn;   

    if (hdivn == 2)
                          rCAMDIVN = (rCAMDIVN & ~(3<<8)) | (1<<9);  

    if (hdivn == 3)
                         rCAMDIVN = (rCAMDIVN & ~(3<<8)) | (1<<8);

    if(hdivn!=0)
                         MMU_SetAsyncBusMode(); //设置异步总线模式

    else 
                         MMU_SetFastBusMode(); //设置快速总线模式
}

—————————————————————————————————————————————————

      接着执行CalcBusClk();           //计算总线频率

     这个函数在系统时钟那节已经讲过,这里不再重复。

      rGPHCON &=~((3<<4)|(3<<6));  
      rGPHCON |=(2<<4)|(2<<6);    //GPH2--TXD[0];GPH3--RXD[0]  
      rGPHUP=0x00;        //使能上拉功能

     上面这三句的意思是,使用GPH2管脚启动UART复用功能使之变为TXD0管脚,同理GPH3变为RXD0管脚,并使能上拉,让数据传输更稳定。

     Uart_Init(0,115200);
     Uart_Select(0);

    上面这二个函数是设置串口参数,使用UATR0,波特率为115200。这些在UART那一节已经详细介绍过,这里不再详述。

     Beep_Init( freq ,50) ;  这个是我们重点掌握的函数。它里面又调用了二个重要的函数;

void Beep_Init(U32 freq, U32 ms) 

    Beep_Stop() ;
    Delay( ms ) ; 
    Beep_Freq_Set( freq ) ;  
}

void Beep_Stop( void ) 

    rGPBCON &= ~3;          //set GPB0 as output  
    rGPBCON |= 1; 
    rGPBDAT &= ~1;       //输出低电平  

裸奔程序之定时器&PWM_第1张图片

裸奔程序之定时器&PWM_第2张图片

 

 

        TQ2440开发板上蜂鸣器的控制端口是由定时器0输出引脚TOUT0控制的,当TOUT0为低电平时,蜂鸣器不响,反之,则响。
        最后我们进入void Beep_Freq_Set( U32 freq );这个函数看看:
        rGPBCON &=~3;
        rGPBCON |=2;  //设置GPB0为OUT0
        rGPBUP=0x0;  //使能上拉
        上面这个三句表示,选中GPB0作为定时器0的输出引脚TOUT0,并且设置为输出,使能上拉。
 
        rTCFG0 &=~0xff;
        rTCFG0 |=15;  //预分频值为15
        rTCFG1 &=~0x0f;
        rTCFG1 |=0x02; //分频值为8
        因为定时器的选择PCLK作为源时钟频率,但是定时器不可能工作在这么高的频率下,所以我们要通过二次分频来降低定时器的工作频率,上面这四句就是起设置分频值的作用。
       rTCNTB0 = (PCLK>>7)/freq; //设定定时器0计数缓冲器的值
       根据TCFG0 和 TCFG1的配置,就相当于上面这句的配置了。
       rTCMPB0 = rTCNTB0>>1;     // 定时器0比较缓冲器的值,PWM输出占空比50%
       右移1位相当于乘以1/2 ,(左移1位相当于乘以2),故rTCMPB0 = 1/2*TCNB0  所以PWM输出占空比为50%
       rTCON &= ~0x1f; 
       rTCON |= 0xb;   //自动重载,关闭变相,手动更新,开启定时器0  
       rTCON &= ~2;            //清除手动更新位 
      上面三句是定时器控制寄存器(TCON)的配置了。详细请看“定时器&PWM详解”里面的介绍。这里不再重复。
——————————————————————————————————————————————
      进入死循环后,U8 key = Uart_Getch();
      这句相当重要,实现了PC机通过串口数据发送到开发板,实现PC机控制开发板的蜂鸣器频率。
      接着3个if判断 PC机按下“+”“-”“Esc”键中的哪个键,然后分别执行提高频率、降低频率、停止频率。并在PC串口软件上打印出当前频率值为多少。很简单,这里就不多说了。
——————————————————————————————————————————————
     到这里,我们的定时器&PWM就讲解完了。裸奔程序之定时器PWM - 23号的wj - 伟坚的博客

 

你可能感兴趣的:(工作,output,delay)