⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lib_pwm.c

📁 IAR编译环境下的AT91SAM7S64芯片的PWM输出演示
💻 C
字号:
//*--------------------------------------------------------------------------------------
//*      ATMEL Microcontroller Software Support  -  ROUSSET  -
//*--------------------------------------------------------------------------------------
//* The software is delivered "AS IS" without warranty or condition of any
//* kind, either express, implied or statutory. This includes without
//* limitation any warranty or condition with respect to merchantability or
//* fitness for any particular purpose, or against the infringements of
//* intellectual property rights of others.
//*--------------------------------------------------------------------------------------
//* File Name           : Lib_PWM.c
//* Object              : Basic PWM  driver
//* Translator          :
//* 1.0 07/Apr/05 JPP   : Creation
//*--------------------------------------------------------------------------------------

#include "board.h"
#include "lib_pwm.h"
#include "Audio.h"


#define TRACE_MODE
#ifdef TRACE_MODE
#include "init.h"
extern void Trace_Toggel_LED (unsigned int Led);
static unsigned int counterAudioIRQ = 0;

#ifdef TRACE_MODE_1
static unsigned int counterIRQ = 0;
static unsigned int IRQ_time = 0;
#endif
#endif

static unsigned int overSampling = 0;
//*=========================================================
//*		IRQ
//*=========================================================
__ramfunc void Audio_interrupt(void)
{
   // This interrupt occurs when INDEX_MAX are sent
   // set the next value by call
     (*OutputSample.func)((char *) &OutputSample.sample[OutputSample.state] ,INDEX_MAX);

#ifdef TRACE_MODE
     counterAudioIRQ++;
     if ( counterAudioIRQ == SAMPLE_FREQUENCY/INDEX_MAX +1) {
         Trace_Toggel_LED(LED3);
	 counterAudioIRQ=0;
#ifdef TRACE_MODE_1
         sprintf((char*) message,":%d\n\r",(unsigned int) counterAudioIRQ );
         AT91F_DBGU_Printk(message);
#endif
     }

#endif

}
//*----------------------------------------------------------------------------
//* \fn  Interrupt for PWM
//* \brief Initialization
//*----------------------------------------------------------------------------
__ramfunc void PWM_handler(void)
{
  unsigned int Tmp;
  // Hand check the interrupt
     Tmp = AT91C_BASE_PWMC->PWMC_ISR;
     Tmp = Tmp;
   //* oversampling
   if (overSampling != (OVER_SAMPLING_RATE-1))
   {
	   overSampling++;
   } else {
   overSampling=0;

  // update the duty value for the next sampling
     if (OutputSample.sample[OutputSample.index] == 0) {
       //* Initialise the Update register write only
	    AT91C_BASE_PWMC_CH0->PWMC_CUPDR = 1 ;
    } else  {
       //* Initialise the Update register write only
	    AT91C_BASE_PWMC_CH0->PWMC_CUPDR = OutputSample.sample[OutputSample.index] ;
     }
  // update the duty value for the next sampling
     if (OutputSample.index == INDEX_MAX-1 ){
		 OutputSample.state = 0 ;
     //* generate software interrupt to set the new val
        AT91F_AIC_Trig (AT91C_BASE_AIC,AT91C_ID_SYS) ;
	 }
     if (OutputSample.index == ((INDEX_MAX*2)-1) ){
		 OutputSample.index=0;
		 OutputSample.state = INDEX_MAX ;
     //* generate software interrupt to set the new val
        AT91F_AIC_Trig (AT91C_BASE_AIC,AT91C_ID_SYS) ;
     } else {
       OutputSample.index++;
     }
#ifdef TRACE_MODE_1
     counterIRQ++;
     if ( counterIRQ == SAMPLE_FREQUENCY+1) {
		 Trace_Toggel_LED(LED4);
		 counterIRQ=0;
         IRQ_time++;
         sprintf((char*) message,"%d\n\r",(unsigned int) IRQ_time );
         AT91F_DBGU_Printk(message);
     }
#endif
    }
}
//*=========================================================
//*		INIT
//*=========================================================
//*----------------------------------------------------------------------------
//* \fn    AT91F_Set_PWM_Channel0
//* \brief Channel 0 configuration
//*----------------------------------------------------------------------------
void AT91F_Set_PWM_Channel0(void)
{
    //*
	//* Set the Clock
	//         - divider clock A
	//         - CALG=0 Left aligned
	//         - CPOL=1 sart at High level (0 inverse output)
        //         - CPD=0 update the dute cycle
 	AT91C_BASE_PWMC_CH0->PWMC_CMR = AT91C_PWMC_CPRE_MCKA | CPD_OFF | CPOL_ON | CALG_OFF ;

    //* Set the Period register (sample size bit fied )
        AT91C_BASE_PWMC_CH0->PWMC_CPRDR = SAMPLE_SIZE;

	//* For firts value
    //* Set the duty cycle register (output value)
	    AT91C_BASE_PWMC_CH0->PWMC_CDTYR = SAMPLE_SIZE >> 1 ;
    //* Initialise the Update register write only
	    AT91C_BASE_PWMC_CH0->PWMC_CUPDR = SAMPLE_SIZE >> 1 ;
}

//*----------------------------------------------------------------------------
//* \fn    AT91F_PWM_Open
//* \brief Initializes PWM channel 0 device
//*----------------------------------------------------------------------------
void AT91F_PWM_Open(void)
{
	unsigned int Tmp;
    //* Enabling a PWM output through the PIO
        AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, 0, AT91C_PA11_PWM0);

    //* Configure PMC by enabling PWM clock
        AT91F_PWMC_CfgPMC ();
        AT91F_PWMC_StopChannel(AT91C_BASE_PWMC,AT91C_PWMC_CHID0);

    //* Set the Clock A divider
        AT91C_BASE_PWMC->PWMC_MR = (( MCKtoPWM << 8 ) | DIVIDER);
    //* sET CHANNEL 0
        AT91F_Set_PWM_Channel0();
    //*
        AT91F_PWM_OutputSample_init();

    //* Open PWM interrupt
       AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_PWMC, PWM_INTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, PWM_handler);
       AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_PWMC);

    //* Open the software interrupt on the AIC
        AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_SYS, SOFT_INTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED,  Audio_interrupt);
        AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_SYS);
    //* Enable IRQ
        AT91F_PWMC_InterruptEnable(AT91C_BASE_PWMC,AT91C_PWMC_CHID0);
        Tmp = AT91C_BASE_PWMC->PWMC_ISR;
        Tmp = Tmp;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -