令我崩溃的AT91SAM7S64的定时器中断问题【恢复】
从早晨开始一直在调AT91SAM7S64的定时器中断,就是用定时器定时1S,然后产生中断实现二极管闪亮,中断已经实现,但是进一次中断后,定时器就不再产生中断了,让我近乎崩溃,哪位朋友指点一下啊,源码如下:#include "Board.h"
#include "dbgu.h"
unsigned char m=0,n=3;
/********************************************************************************************************
** 函数名称:DelayNS()
** 函数功能:长软件延时
** 入口参数:dly 延时参数,值越大,延时越久
** 出口参数:无
********************************************************************************************************/
void DelayNS(unsigned long dly)
{
unsigned long i;
for(; dly>0; dly--)
for(i=0; i<60000; i++);
}
/********************************************************************************************************
** 函数名称:cuowu()
** 函数功能:警报
** 入口参数:无
** 出口参数:无
********************************************************************************************************/
void cuowu (void)
{
while(1)
{
DelayNS(50);
*AT91C_PIOA_ODSR&=0x00000002;
DelayNS(50);
*AT91C_PIOA_ODSR|=0xfffffffd;
}
}
/********************************************************************************************************
** 函数名称:time_init()
** 函数功能:定时器初始化
** 入口参数:无
** 出口参数:无
********************************************************************************************************/
void time_init(void)
{
*AT91C_PMC_PCER=(1<<12); // 打开电源
*AT91C_TC0_CCR=0x01;
*AT91C_TC0_CMR=((0x1<<15)|(0x2<<13)|0x4); // 波形模式 up带RC比较 1024分频
*AT91C_TC0_RC= 65000; // 这里在晶振18.432时正好是 1秒钟
*AT91C_TC0_IER=(0x1<<4);//使能RC比较中断
*AT91C_TC0_CCR=0x04; // 启动定时器
}
/********************************************************************************************************
** 函数名称:TC2ISR()
** 函数功能:中断执行
** 入口参数:无
** 出口参数:无
********************************************************************************************************/
void TC2ISR_c_irq_handler(void)
{
if(n%2)
{
*AT91C_PIOA_ODSR&=0xfffffffd;
}
else
{
*AT91C_PIOA_ODSR|=0x00000002;
}
n++;
*AT91C_AIC_EOICR =0x01; /* 结束中断 */
}
/********************************************************************************************************
** 函数名称:AIC_init()
** 函数功能:中断初试化
** 入口参数:无
** 出口参数:无
********************************************************************************************************/
void AIC_init(void)
{
AT91C_AIC_SMR = (0x0|(0x3<<5)); //优先级最低,沿边触发
AT91C_AIC_SVR=(unsigned int)TC2ISR_c_irq_handler; //中断入口
*AT91C_AIC_IECR=(1<<12);//系统级使能TC2中断
}
int main( void )
{
*AT91C_PIOA_PER=0xffffffff; //PIOA作为I/O使用
*AT91C_PIOA_OER=0x00000006; //PIOA1-2输出使能
*AT91C_PIOA_OWER=0x00000006;
*AT91C_PIOA_SODR=0xffffffff;
time_init(); //初始化定时器
AIC_init(); //初始化中断
while(1)
{
DelayNS(30);
*AT91C_PIOA_ODSR|=0x00000004; //熄灭
DelayNS(30);
*AT91C_PIOA_ODSR&=0xfffffffb; //点亮
}
}
点击此处下载 ourdev_590484.rar(文件大小:281K) (原文件名:LED.rar) 感觉国内用at91sam7s的人好少
at定时器这个玩意比较变态,每次进中断以后都要读一下SR来清除SR,否则中断就阻塞了
定时器中断要这样写
void TC2_Int_Handler(void) __irq
{
// Read TC_SR to clear it
DWORD dwKeyPort = AT91C_BASE_TC2->TC_SR; // 没这句是不行的,没这句中断只能玩一次
AT91C_BASE_TC2->TC_CCR = AT91C_TC_SWTRG;
AT91C_BASE_AIC->AIC_EOICR = 0;
} 在此,我非常非常感谢各位对我的解答,我按"Tomcat 菜猫"说的清除SR后,终于实现了能多次进入中断
为什么非要清空SR才行呢?AT真的太变态了,这个陷阱对于我来说实在太恶心了. 太谢谢各位的解答了,我这就试试,谢谢!! mark 这是iar4.30下一个标准的工程例子,仔细对比下看看初始化和中断服务函数的写法,个人经验觉得你的中断函数不对 ourdev_592264.rar(文件大小:620K) (原文件名:AT91SAM7X256-TC-IAR.rar) 哎!这问题竟然也没人回答,得学会自立了 请问楼主改成怎样才好的啊 ?
我刚刚才接触,有点不明白 extern void SpiADCUpdate(void);
extern void TimerCallback(void);
void timer0_c_irq_handler(void)
{
int temp = AT91C_BASE_TC0->TC_SR;
temp = temp;
TimerCallback();
// AT91C_BASE_ADC->ADC_CR = 0x2;
// ADC_flag = 1;
// SpiADCUpdate();
// printfd("0");
}
extern OS_EVENT *semTimer50us;
extern OS_EVENT *semTimer2;
void timer1_c_irq_handler(void)
{
// static int flag=0;
int temp = AT91C_BASE_TC1->TC_SR;
temp = temp;
AT91F_AIC_DisableIt (AT91C_BASE_AIC, AT91C_ID_TC1);
OSSemPost(semTimer50us);
// if(flag){
// AT91F_PIO_SetOutput(AT91C_BASE_PIOA, LED1);
// }
// else{
// AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, LED1);
// }
// flag=(flag+1)&1;
// printf("1");
}
void timer2_c_irq_handler(void)
{
// static int flag=0;
int temp = AT91C_BASE_TC2->TC_SR;
if(temp&AT91C_TC_LDRAS)
{
}
// AT91F_AIC_DisableIt (AT91C_BASE_AIC, AT91C_ID_TC2);
// OSSemPost(semTimer2);
// if(flag){
// AT91F_PIO_SetOutput(AT91C_BASE_PIOA, LED2);
// }
// else{
// AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, LED2);
// }
// flag=(flag+1)&1;
// printf("2");
}
void AT91F_TC_Open ( AT91PS_TC TC_pt, unsigned int Mode, unsigned int TimerId)
{
unsigned int dummy;
//* First, enable the clock of the TIMER
AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1<< TimerId ) ;
//* Disable the clock and the interrupts
TC_pt->TC_CCR = AT91C_TC_CLKDIS ;
TC_pt->TC_IDR = 0xFFFFFFFF ;
//* Clear status bit
dummy = TC_pt->TC_SR;
//* Suppress warning variable "dummy" was set but never used
dummy = dummy;
//* Set the Mode of the Timer Counter
TC_pt->TC_CMR = Mode ;
//* Enable the clock
TC_pt->TC_CCR = AT91C_TC_CLKEN ;
}
void TimerInit0(void)
{
// Open timer0
AT91F_TC_Open(AT91C_BASE_TC0,AT91C_TC_CLKS_TIMER_DIV2_CLOCK|(1<<15)|(2<<13),AT91C_ID_TC0);
AT91C_BASE_TC0->TC_RC = MCK/8UL/100UL;//div:8 , 100Hz interrupt
// Open Timer 0 interrupt
AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0, TIMER0_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, timer0_c_irq_handler);
AT91C_BASE_TC0->TC_IER = AT91C_TC_CPCS;//IRQ enable CPC
AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_TC0);
// Generate interrupt by software
//AT91F_AIC_Trig (AT91C_BASE_AIC,AT91C_ID_TC0) ;
// Start timer0
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG ;
}
void TimerInit1(void)
{
// Open timer1
AT91F_TC_Open(AT91C_BASE_TC1,AT91C_TC_CLKS_TIMER_DIV1_CLOCK|(1<<15)|(2<<13)|(AT91C_TC_CPCSTOP),AT91C_ID_TC1);
AT91C_BASE_TC1->TC_RC = MCK/2UL/20000UL;
// Open Timer 1 interrupt
AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC1, TIMER1_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, timer1_c_irq_handler);
AT91C_BASE_TC1->TC_IER = AT91C_TC_CPCS;//IRQ enable CPC
// AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_TC1);
// Generate interrupt by software
// AT91F_AIC_Trig (AT91C_BASE_AIC,AT91C_ID_TC1) ;
// Start timer1
// AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG ;
}
#if 0
void TimerInit2(void)
{
// Open timer2
AT91F_TC_Open(AT91C_BASE_TC2,AT91C_TC_CLKS_TIMER_DIV1_CLOCK|(1<<15)|(2<<13)|(AT91C_TC_CPCSTOP),AT91C_ID_TC2);
AT91C_BASE_TC2->TC_RC = MCK/2UL/20000UL;
// Open Timer 2 interrupt
AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC2, TIMER2_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, timer2_c_irq_handler);
AT91C_BASE_TC2->TC_IER = AT91C_TC_CPCS;//IRQ enable CPC
}
#endif 老外的代码唯一没看懂的地方,就是计算rc触发时间长度,,只看见一个100hz 的提示,然后我反着算,觉得不对,arm可是有48mhz呢,用2分频的话,每个间断也得有0.03us啊? 然后就开始迷糊了,特别是UL这个单位,,,,恐怕得找到定义。。
不过老外写的蛮容易懂的。
页:
[1]