打印

ARM中断问题,不知为何这样?

[复制链接]
2857|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yancf|  楼主 | 2012-10-30 16:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
主要是中断和全局变量的问题:
问题1:一开机,定时器中断正常运行,但当串口接收到数据后,定时器不再工作。
     2:全局变量在定时中断程序中修改后在主程序中可以检测到,而当全局变量在接收中断程序中修改后在主程序中检测不到


大致程序如下:

//target.c
extern volatile unsigned char Serial_Data_receive;
extern volatile unsigned char NEW_Data_receive_flag;

//串口接收中断子程序
void __irq Uart0_Receive(void) //IRQ_Exception(void)
{
     unsigned char rcvData = 0;
     
     if((U0LSR&0x1) == 1)
     {
         rcvData = U0RBR;
         if(rcvData == 0xaa)
         {
            NEW_Data_receive_flag = 1;
            Serial_Data_receive = rcvData;
         }
     }
  
     VICVectAddr = 0;     //清中断向量
}

void __irq IRQ_Time0(void)
{            
   T0IR = 0x01;                       // 清除中断标志

   NEW_Data_receive_flag = 1;
   
   VICVectAddr = 0x00;                   // 通知VIC中断处理结束
}


//串口中断配置
void TargetInit(void)
{
   
    U0FCR  =  0x01; //接收一个字符
    U0IER  =  0x01; //开接收中断   发送中断为:0x02  
    VICIntSelect = 0x00000000;  //设置UART0为IRQ中断,其他中断为IRQ中断
    VICVectCntl0=0x26;
    VICVectAddr0 =(unsigned int)Uart0_Receive;

   
T0PR = 9999;                   // 设置定时器0分频为100分频,

T0MCR = 0x03;                      // 匹配通道0匹配中断并复位T0TC
T0MR0 = 18432/1;              // 比较值(1秒定时值) ###100us
T0TCR = 0x03;                      // 启动并复位T0TC
T0TCR = 0x01;
// 设置定时器0中断IRQ //
//VICIntSelect = 0x00;             // 所有中断通道设置为IRQ中断
VICVectCntl1 = 0x24;                 // 定时器0中断通道分配最高优先级(向量控制器0)
VICVectAddr1 = (unsigned int)IRQ_Time0;       // 设置中断服务程序地址向量

VICIntEnable = 0x00000040 + 0x00000010;      //使能定时器0和UART0中断
}


//main.c
volatile unsigned char Serial_Data_receive = 0;
volatile unsigned char NEW_Data_receive_flag = 0;

int main(void)
{
    PLLCON = 0;
    VPBDIV=1;
    PINSEL0 = 5;  /*串口UART0有效*/
    PINSEL1 = 0;
    IO0DIR = 0x01000000;

   TargetInit();  //中断初始化
   while(1)
   {
        if(NEW_Data_receive_flag == 1)        

       {           
           NEW_Data_receive_flag = 0;
           UART0SendByte(0xdd);   //往串口发送数据
        }
   }
}

问题1:一开机,定时器中断正常运行,但当串口接收到数据后,定时器不再工作。
     2:全局变量在定时中断程序中修改后在主程序中可以检测到,而当全局变量在接收中断程序中修改后在主程序中检测不到

相关帖子

沙发
阿南| | 2012-10-30 22:39 | 只看该作者
楼主是定时器不工作了?还是不产生定时中断了?
重点查一下这个VICVectAddr = 0x00

使用特权

评论回复
板凳
yancf|  楼主 | 2012-10-31 10:35 | 只看该作者
定时器是否工作,我不知如何查,但可以确定的是没有产生定时中断。

使用特权

评论回复
地板
阿南| | 2012-10-31 11:10 | 只看该作者
查看定时器寄存器是否被关闭,查看定时中断寄存器是否被屏蔽

使用特权

评论回复
5
yancf|  楼主 | 2012-12-11 16:15 | 只看该作者
前些日子没时间,刚才又继上述问题再测试了下,发现只要进入串口中断后,没有退出中断,就如同一直处于查询( if((U0LSR&0x1) == 1))的状态,可以继续接收,主程度和其它程序不再响应。不知是为何?如何查?请各位帮帮忙!

使用特权

评论回复
6
yancf|  楼主 | 2012-12-11 16:17 | 只看该作者
不知是否与启动代码有关?此芯片为:LPC2214
启动代码如下:如有问题,请指教。

;define the stack size
;定义堆栈的大小
SVC_STACK_LEGTH         EQU         256
FIQ_STACK_LEGTH         EQU         0
IRQ_STACK_LEGTH         EQU         256
ABT_STACK_LEGTH         EQU         0
UND_STACK_LEGTH         EQU         0

NoInt       EQU 0x80

USR32Mode   EQU 0x10
SVC32Mode   EQU 0x13
SYS32Mode   EQU 0x1f
IRQ32Mode   EQU 0x12
FIQ32Mode   EQU 0x11

PINSEL2     EQU 0xE002C014

BCFG0       EQU 0xFFE00000
BCFG1       EQU 0xFFE00004
BCFG2       EQU 0xFFE00008
BCFG3       EQU 0xFFE0000C

  ;  IMPORT __use_no_semihosting_swi
  ;  IMPORT __use_two_region_memory

;The imported labels
;引入的外部标号在这声明
    IMPORT  FIQ_Exception                   ;Fast interrupt exceptions handler 快速中断异常处理程序
    IMPORT  __main                          ;The entry point to the main function C语言主程序入口
    IMPORT  TargetResetInit                 ;initialize the target board 目标板基本初始化

;The emported labels
;给外部使用的标号在这声明
    EXPORT  bottom_of_heap
    EXPORT  bottom_of_Stacks
    EXPORT  top_of_heap
    EXPORT  StackUsr
   
    EXPORT  _Reset
    EXPORT __user_initial_stackheap

    CODE32

    AREA    vectors,CODE,READONLY
        ENTRY
;interrupt vectors
;中断向量表
_Reset
        LDR     PC, ResetAddr
        LDR     PC, UndefinedAddr
        LDR     PC, SWI_Addr
        LDR     PC, PrefetchAddr
        LDR     PC, DataAbortAddr
        DCD     0xb9205f80
        LDR     PC, [PC, #-0xff0]
        LDR     PC, FIQ_Addr

ResetAddr           DCD     ResetInit
UndefinedAddr       DCD     Undefined
SWI_Addr            DCD     SoftwareInterrupt
PrefetchAddr        DCD     PrefetchAbort
DataAbortAddr       DCD     DataAbort
Nouse               DCD     0
IRQ_Addr            DCD     0
FIQ_Addr            DCD     FIQ_Handler

;未定义指令
Undefined
        B       Undefined

;软中断
SoftwareInterrupt                       
        B       SoftwareInterrupt       

;取指令中止
PrefetchAbort
        B       PrefetchAbort

;取数据中止
DataAbort
        B       DataAbort

;快速中断
FIQ_Handler
        STMFD   SP!, {R0-R3, LR}
        BL      FIQ_Exception
        LDMFD   SP!, {R0-R3, LR}
        SUBS    PC,  LR,  #4
InitStack   
        MOV     R0, LR
;Build the SVC stack
;设置管理模式堆栈
        MSR     CPSR_c, #0xd3               
        LDR     SP, StackSvc
;Build the IRQ stack                       
;设置中断模式堆栈
        MSR     CPSR_c, #0xd2
        LDR     SP, StackIrq
;Build the FIQ stack
;设置快速中断模式堆栈
        MSR     CPSR_c, #0xd1
        LDR     SP, StackFiq
;Build the DATAABORT stack
;设置中止模式堆栈
        MSR     CPSR_c, #0xd7
        LDR     SP, StackAbt
;Build the UDF stack
;设置未定义模式堆栈
        MSR     CPSR_c, #0xdb
        LDR     SP, StackUnd
;Build the SYS stack
;设置系统模式堆栈
        MSR     CPSR_c, #0x5f
        LDR     SP, =StackUsr

        MOV     PC, R0
ResetInit
;Initial extenal bus controller.
;初始化外部总线控制器,根据目标板决定配置

        LDR     R0, =PINSEL2
    IF :DEF: EN_CRP
        LDR     R1, =0x0f814910
    ELSE
        LDR     R1, =0x0f814914
    ENDIF
        STR     R1, [R0]

        LDR     R0, =BCFG0
        LDR     R1, =0x1000ffef
        STR     R1, [R0]

        LDR     R0, =BCFG1
        LDR     R1, =0x1000ffef
        STR     R1, [R0]

;        LDR     R0, =BCFG2
;        LDR     R1, =0x2000ffef
;        STR     R1, [R0]

;        LDR     R0, =BCFG3
;        LDR     R1, =0x2000ffef
;        STR     R1, [R0]
        
        BL      InitStack               ;初始化堆栈 Initialize the stack
        BL      TargetResetInit         ;目标板基本初始化 Initialize the target board
                                        ;跳转到c语言入口 Jump to the entry point of C program
        B       __main
__user_initial_stackheap   
    LDR   r0,=bottom_of_heap
;    LDR   r1,=StackUsr
    LDR   r2,=top_of_heap
    LDR   r3,=bottom_of_Stacks
    MOV   pc,lr


StackSvc           DCD     SvcStackSpace + (SVC_STACK_LEGTH - 1)* 4
StackIrq           DCD     IrqStackSpace + (IRQ_STACK_LEGTH - 1)* 4
StackFiq           DCD     FiqStackSpace + (FIQ_STACK_LEGTH - 1)* 4
StackAbt           DCD     AbtStackSpace + (ABT_STACK_LEGTH - 1)* 4
StackUnd           DCD     UndtStackSpace + (UND_STACK_LEGTH - 1)* 4

    IF :DEF: EN_CRP
        IF  . >= 0x1fc
        INFO    1,"\nThe data at 0x000001fc must be 0x87654321.\nPlease delete some source before this line."
        ENDIF
CrpData
    WHILE . < 0x1fc
    NOP
    WEND
CrpData1
    DCD     0x87654321          ;/*When the Data is 为0x87654321,user code be protected. 当此数为0x87654321时,用户程序被保护 */
    ENDIF
   
;/* 分配堆栈空间 */
        AREA    MyStacks, DATA, NOINIT, ALIGN=2
SvcStackSpace      SPACE   SVC_STACK_LEGTH * 4  ;Stack spaces for Administration Mode 管理模式堆栈空间
IrqStackSpace      SPACE   IRQ_STACK_LEGTH * 4  ;Stack spaces for Interrupt ReQuest Mode 中断模式堆栈空间
FiqStackSpace      SPACE   FIQ_STACK_LEGTH * 4  ;Stack spaces for Fast Interrupt reQuest Mode 快速中断模式堆栈空间
AbtStackSpace      SPACE   ABT_STACK_LEGTH * 4  ;Stack spaces for Suspend Mode 中止义模式堆栈空间
UndtStackSpace     SPACE   UND_STACK_LEGTH * 4  ;Stack spaces for Undefined Mode 未定义模式堆栈

        AREA    Heap, DATA, NOINIT
bottom_of_heap    SPACE   1

        AREA    StackBottom, DATA, NOINIT
bottom_of_Stacks    SPACE   1

        AREA    HeapTop, DATA, NOINIT
top_of_heap

        AREA    Stacks, DATA, NOINIT
StackUsr

    END

使用特权

评论回复
7
xinzha| | 2012-12-11 21:43 | 只看该作者
你没清串口中断标志

使用特权

评论回复
8
yancf|  楼主 | 2012-12-12 17:01 | 只看该作者
请问如何清除串口中断标志?我总找不到那个寄存器。

使用特权

评论回复
9
阿南| | 2012-12-12 17:04 | 只看该作者
查看规格书直接找,或者看官方的中断服务程序,里面一定有中断标志寄存器的,往里面写就是直接清除了。

使用特权

评论回复
10
xinzha| | 2012-12-12 18:30 | 只看该作者
这个只能靠你自己看芯片手册或者例程了,既然你都能写出下面的代码
  U0FCR  =  0x01; //接收一个字符
  U0IER  =  0x01; //开接收中断   发送中断为:0x02  
那应该很容易找出来怎么清串口中断,应该就在附近。

使用特权

评论回复
11
yancf|  楼主 | 2012-12-13 11:21 | 只看该作者
官方的中断服务程序如下:
uint8  rcv_buf[8];                       // UART0数据接收缓冲区
volatile uint8  rcv_new;             // 接收新数据标志
/****************************************************************************
* 名称:IRQ_UART0()
* 功能:串口UART0接收中断。
* 入口参数:无
* 出口参数:无
****************************************************************************/
void   __irq IRQ_UART0(void)
{  uint8  i;
     
   if( 0x04==(U0IIR&0x0F) ) rcv_new = 1;// 设置接收到新的数据标志
   for(i=0; i<8; i++)
   { rcv_buf[i] = U0RBR;                      // 读取FIFO的数据,并清除中断标志
   }
   
   VICVectAddr = 0x00;                      // 中断处理结束
}

从以上可以说明:只要从U0RBR读出数量据,就可以清除中断标志。

就是不明白,我的串口接收中断为什么是这样的呢?还请大家再分析一下吧。

使用特权

评论回复
12
yancf|  楼主 | 2012-12-13 11:39 | 只看该作者
谢谢各位的提醒,清中断还需读U0IIR。问题解决了。

使用特权

评论回复
13
zh5202| | 2012-12-13 16:40 | 只看该作者
ARM落跑,不错

使用特权

评论回复
14
lxj19901115| | 2013-1-7 17:54 | 只看该作者
这个问题 ,你主要查下你的中断向量表,和中断处理函数在向量内是否有链接定义,这个问题,我在STM32 使用串口的时候,也碰到过,最后发现是没有找到中断入口,,,函数的地址

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

7

帖子

0

粉丝