写这个程序,想在网上找个现成的改改,没找到,这里做好了贴一贴,方便后来者。
用定时器的WAVE模式,产生RA、RC比较中断,RA比较中断将PA29引脚置高,RC比较中断将PA29置低,而且RA刚好是RC的一半,因此可以产生方波,改变RC就改变频率,驱动步进电机。
unsigned int TimerAttribute[][2] = {
{5 * 2, BOARD_MCK / 8 / (300 * 2) },
{5 * 2, BOARD_MCK / 8 / (350 * 2) },
{6 * 2, BOARD_MCK / 8 / (400 * 2) },
{6 * 2, BOARD_MCK / 8 / (450 * 2) },
{7 * 2, BOARD_MCK / 8 / (500 * 2) },
{7 * 2, BOARD_MCK / 8 / (550 * 2) },
{8 * 2, BOARD_MCK / 8 / (600 * 2) },
{9 * 2, BOARD_MCK / 8 / (650 * 2) },
{9 * 2, BOARD_MCK / 8 / (700 * 2) },
{10 * 2, BOARD_MCK / 8 / (750 * 2) },
{24 * 2 * 68, BOARD_MCK / 8 / (800 * 2) }
};
volatile unsigned int CurMicroSteps;
volatile unsigned int CurLevel;
volatile unsigned int UpOrDown;
volatile unsigned int RunningFlag;
//------------------------------------------------------------------------------
/// Interrupt handler for TC0 interrupt. Toggles the state of LED\#2.
//------------------------------------------------------------------------------
void ISR_Tc0(void)
{
unsigned int state;
// Clear status bit to acknowledge interrupt
state = AT91C_BASE_TC0->TC_SR;
if(state & AT91C_TC_CPAS){
//置高
AT91C_BASE_PIOA->IO_SODR = AT91C_PIO_PA29;
return;
}
if(state & AT91C_TC_CPCS){
//置低
AT91C_BASE_PIOA->IO_CODR = AT91C_PIO_PA29;
CurMicroSteps--;
//当前台阶走完
if(0 == CurMicroSteps){
if(1 == UpOrDown){//加速阶段
if(CurLevel < 10){
CurLevel++;//上升一个台阶
}else{
CurLevel--;//最高台阶走完,开始减速,下降一个台阶
UpOrDown = 0;
}
}else{//减速阶段
if(CurLevel > 0){
CurLevel--;//下降一个台阶
}else{
RunningFlag = 0;//最低台阶走完,停止转动
TC_Stop(AT91C_BASE_TC0);
}
}
//未结束,继续发脉冲
if(1 == RunningFlag){
CurMicroSteps = TimerAttribute[CurLevel][0];
AT91C_BASE_TC0->TC_RC = TimerAttribute[CurLevel][1];
AT91C_BASE_TC0->TC_RA = TimerAttribute[CurLevel][1]/2;
TC_Start(AT91C_BASE_TC0);
}
}//CurMicroSteps
}//AT91C_TC_CPCS
}
//------------------------------------------------------------------------------
/// Configure Timer Counter 0 to generate an interrupt every 250ms.
//------------------------------------------------------------------------------
void ConfigureTc(void)
{
//unsigned int div;
//unsigned int tcclks;
// Enable peripheral clock
AT91C_BASE_PMC->MC_PCER = 1 << AT91C_ID_TC0;
// Configure TC for a 4Hz frequency and trigger on RC compare
//TC_FindMckDivisor(4, BOARD_MCK, &div, &tcclks);
TC_Configure(AT91C_BASE_TC0, AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_CLKS_TIMER_DIV2_CLOCK);
//AT91C_BASE_TC0->TC_RC = (BOARD_MCK / div) / 4; // timerFreq / desiredFreq
// Configure and enable interrupt on RC compare
AIC_ConfigureIT(AT91C_ID_TC0, AT91C_AIC_PRIOR_LOWEST, ISR_Tc0);
AT91C_BASE_TC0->TC_IER = AT91C_TC_CPAS | AT91C_TC_CPCS;
AIC_EnableIT(AT91C_ID_TC0);
} |