📄 lib_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 + -