楼主: whm407

[分享] 接受中断连续进入两次,k60 UART3

[复制链接]

该用户从未签到

8

主题

46

帖子

0

新手上路

Rank: 1

积分
89
最后登录
1970-1-1
发表于 2012-9-29 17:49:19 | 显示全部楼层 |阅读模式
        程序中使能了接受中断,我在串口中断中加了一条打印语句,我的发送设备是每隔1秒发送1次数据,发现串口中断一直往外打印数据,好像不能从串口中断中出来,后来我对S1寄存器的RDRF位写1(貌似datasheet中说,对这位写无效)之后,发现每隔1秒打印两条信息,就是连续进了两次中断。我只使能了接受中断,怎么会连续进两次中断,哪位大侠解释一下,谢谢。
       我的中断接受程序如下:
void UART3_IRQHander(void)
{
uint8 RxCh = 0;
RxCh = UART_D_REG(UART3_BASE_PTR); //取出接受的数据
printf("uart接收到%d\n",RxCh);

UART_S1_REG(UART3_BASE_PTR) |= UART_S1_RDRF_MASK; //不加这句的话,printf就一直不停地打印。加上这句的话,每接受一次printf打印两次。
}
 
回复

使用道具 举报

该用户从未签到

16

主题

53

帖子

0

新手上路

Rank: 1

积分
130
最后登录
1970-1-1
发表于 2012-9-30 00:34:33 | 显示全部楼层

RE:接受中断连续进入两次,k60 UART3

你在中断里面调用接收数据的语句,中断自动会清除,一定要把数据寄存器的值取出来
回复 支持 反对

使用道具 举报

该用户从未签到

37

主题

327

帖子

1

高级会员

Rank: 4

积分
886
最后登录
2023-7-19
发表于 2012-9-30 11:59:34 | 显示全部楼层

RE:接受中断连续进入两次,k60 UART3

对,一定把数据寄存器的值取出来 我的接收程序,一直没问题(参考苏大的)
u8 UART_Re1 (UART_Type *uartch,u8 *ch)
{
    u32 k;
    for (k = 0; k S1 & UART_S1_RDRF_MASK)!= 0)//判断接收缓冲区是否满,参见手册1223页
                 {
                   *ch =(uartch->D);        //接受数据,参见手册1230页
                   return 1;                         //接受成功
                 }
     }
    return 0;                        //如果超时,接受失败
}
回复 支持 反对

使用道具 举报

该用户从未签到

8

主题

46

帖子

0

新手上路

Rank: 1

积分
89
最后登录
1970-1-1
 楼主| 发表于 2012-10-2 11:10:46 | 显示全部楼层

RE:接受中断连续进入两次,k60 UART3

我的中断接受程序如下:
void UART3_IRQHander(void)
{
   uint8 RxCh = 0;
   RxCh = UART_D_REG(UART3_BASE_PTR);     //取出接受的数据
   printf("uart接收到%d\n",RxCh);
   
   UART_S1_REG(UART3_BASE_PTR) |= UART_S1_RDRF_MASK;  //不加这句的话,printf就一直不停地打印。加上这句的话,每接受一次printf打印两次。
}
回复 支持 反对

使用道具 举报

该用户从未签到

8

主题

46

帖子

0

新手上路

Rank: 1

积分
89
最后登录
1970-1-1
 楼主| 发表于 2012-10-4 23:24:33 | 显示全部楼层

RE:接受中断连续进入两次,k60 UART3

自己顶下,别沉了。
回复 支持 反对

使用道具 举报

该用户从未签到

8

主题

46

帖子

0

新手上路

Rank: 1

积分
89
最后登录
1970-1-1
 楼主| 发表于 2012-10-8 14:35:57 | 显示全部楼层

RE:接受中断连续进入两次,k60 UART3

刚才仔细查了一下datasheet,发现要清除RDRF标志,是要有顺序限制的,一定要查询S1的RDRF位,再读取data寄存器。只有这样的顺序才能成功清除RDRF标志,如果像我以前那样,不查询就直接读取数据寄存器的值是能不能清除RDRF标志的,如果程序这样
void UART3_IRQHander(void)
{
uint8 RxCh = 0;
RxCh = UART_D_REG(UART3_BASE_PTR); //取出接受的数据
printf("uart接收到%d\n",RxCh);
//UART_S1_REG(UART3_BASE_PTR) |= UART_S1_RDRF_MASK; //不加这句的话,printf就一直不停地打印。加上这句的话,每接受一次printf打印两次。
}
因为没有成功的清除RDRF,所以会一直产生中断,所以才会一直不停地打印数据,至于加上那条给RDRF置1的语句之后,就每次接到数据就中断两次,打印两次的原因,暂时还没有想明白。
回复 支持 反对

使用道具 举报

该用户从未签到

16

主题

53

帖子

0

新手上路

Rank: 1

积分
130
最后登录
1970-1-1
发表于 2012-10-8 14:47:00 | 显示全部楼层

回复:接受中断连续进入两次,k60 UART3

回复第 6 楼 于2012-10-08 14:35:57发表:
刚才仔细查了一下datasheet,发现要清除RDRF标志,是要有顺序限制的,一定要查询S1的RDRF位,再读取data寄存器。只有这样的顺序才能成功清除RDRF标志,如果像我以前那样,不查询就直接读取数据寄存器的值是能不能清除RDRF标志的,如果程序这样
void UART3_IRQHander(void)
{
uint8 RxCh = 0;
RxCh = UART_D_REG(UART3_BASE_PTR); //取出接受的数据
printf("uart接收到%d\n",RxCh);
//UART_S1_REG(UART3_BASE_PTR) |= UART_S1_RDRF_MASK; //不加这句的话,printf就一直不停地打印。加上这句的话,每接受一次printf打印两次。
}
因为没有成功的清除RDRF,所以会一直产生中断,所以才会一直不停地打印数据,至于加上那条给RDRF置1的语句之后,就每次接到数据就中断两次,打印两次的原因,暂时还没有想明白。
 

你加了这句话相当于进两次中断清除一次标志位
回复 支持 反对

使用道具 举报

该用户从未签到

8

主题

46

帖子

0

新手上路

Rank: 1

积分
89
最后登录
1970-1-1
 楼主| 发表于 2012-10-8 17:34:34 | 显示全部楼层

回复:接受中断连续进入两次,k60 UART3

回复第 7 楼 于2012-10-08 14:47:00发表:
回复第 6 楼 于2012-10-08 14:35:57发表:
刚才仔细查了一下datasheet,发现要清除RDRF标志,是要有顺序限制的,一定要查询S1的RDRF位,再读取data寄存器。只有这样的顺序才能成功清除RDRF标志,如果像我以前那样,不查询就直接读取数据寄存器的值是能不能清除RDRF标志的,如果程序这样
void UART3_IRQHander(void)
{
uint8 RxCh = 0;
RxCh = UART_D_REG(UART3_BASE_PTR); //取出接受的数据
printf("uart接收到%d\n",RxCh);
//UART_S1_REG(UART3_BASE_PTR) |= UART_S1_RDRF_MASK; //不加这句的话,printf就一直不停地打印。加上这句的话,每接受一次printf打印两次。
}
因为没有成功的清除RDRF,所以会一直产生中断,所以才会一直不停地打印数据,至于加上那条给RDRF置1的语句之后,就每次接到数据就中断两次,打印两次的原因,暂时还没有想明白。
 

你加了这句话相当于进两次中断清除一次标志位
 

我也是这么想的,第一次中断操作了状态寄存器,在第二个中断中操作了数据寄存器,这样两次中断,完成了清除标志位的操作。datasheet上说先读状态寄存器,再操作数据寄存器,完成清除标志位。从我两次进中断的情况来看,先写状态寄存器,再操作数据寄存器同样也能清除标志位。像这样
void UART3_IRQHander(void)
{
uint8 RxCh = 0;
UART_S1_REG(UART3_BASE_PTR) |= UART_S1_RDRF_MASK;
RxCh = UART_D_REG(UART3_BASE_PTR); //取出接受的数据
printf("uart接收到%d\n",RxCh);

}
 
回复 支持 反对

使用道具 举报

该用户从未签到

16

主题

53

帖子

0

新手上路

Rank: 1

积分
130
最后登录
1970-1-1
发表于 2012-10-8 22:33:18 | 显示全部楼层

回复:接受中断连续进入两次,k60 UART3

回复第 8 楼 于2012-10-08 17:34:34发表:
回复第 7 楼 于2012-10-08 14:47:00发表:
回复第 6 楼 于2012-10-08 14:35:57发表:
刚才仔细查了一下datasheet,发现要清除RDRF标志,是要有顺序限制的,一定要查询S1的RDRF位,再读取data寄存器。只有这样的顺序才能成功清除RDRF标志,如果像我以前那样,不查询就直接读取数据寄存器的值是能不能清除RDRF标志的,如果程序这样
void UART3_IRQHander(void)
{
uint8 RxCh = 0;
RxCh = UART_D_REG(UART3_BASE_PTR); //取出接受的数据
printf("uart接收到%d\n",RxCh);
//UART_S1_REG(UART3_BASE_PTR) |= UART_S1_RDRF_MASK; //不加这句的话,printf就一直不停地打印。加上这句的话,每接受一次printf打印两次。
}
因为没有成功的清除RDRF,所以会一直产生中断,所以才会一直不停地打印数据,至于加上那条给RDRF置1的语句之后,就每次接到数据就中断两次,打印两次的原因,暂时还没有想明白。
 

你加了这句话相当于进两次中断清除一次标志位
 

我也是这么想的,第一次中断操作了状态寄存器,在第二个中断中操作了数据寄存器,这样两次中断,完成了清除标志位的操作。datasheet上说先读状态寄存器,再操作数据寄存器,完成清除标志位。从我两次进中断的情况来看,先写状态寄存器,再操作数据寄存器同样也能清除标志位。像这样
void UART3_IRQHander(void)
{
uint8 RxCh = 0;
UART_S1_REG(UART3_BASE_PTR) |= UART_S1_RDRF_MASK;
RxCh = UART_D_REG(UART3_BASE_PTR); //取出接受的数据
printf("uart接收到%d\n",RxCh);

}
 
 

你理解的还是不对,UART的状态寄存器是只读的,你怎么能进行写操作呢?UART_S1_REG(UART3_BASE_PTR) |= UART_S1_RDRF_MASK; 这句话其实执行的就是读了一下状态寄存器,根本没有写的作用。所以第一次中断从这开始,到第二次中断操作数据寄存器完成一个清除中断标志位。
回复 支持 反对

使用道具 举报

该用户从未签到

0

主题

26

帖子

0

新手上路

Rank: 1

积分
61
最后登录
1970-1-1
发表于 2012-10-13 18:41:12 | 显示全部楼层

回复:接受中断连续进入两次,k60 UART3

哈哈,ARM M4是有这个毛病,我在调试CAN的时候也遇到这个问题了,解决的方法是把最后那个清除标志位的语句放到中断函数的最前面就行了,其实只要清除标志位的语句不是中断服务子程序的最后一句就行了。希望对你有帮助。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|恩智浦技术社区

GMT+8, 2025-7-19 15:50 , Processed in 0.160323 second(s), 27 queries , MemCache On.

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

快速回复 返回顶部 返回列表