共2条
1/1 1 跳转至页
ARM,uCOS,II 刚学ARM开发,问个问题,多多指教(在uCOS-II系统下的中断、消息邮箱问题)
问
刚学习“周立功”的开发教程,打算实现:
在键盘的外部中断处理子程序中发送消息到消息邮箱,task0一直等待消息收到后对LED进行相应的控制。
问题是:我的中断进入几次后就再不进入了,还有调试时现象也不一致(代码没该动)。
现把拼凑的(呵呵)代码贴上,望指教!!!
#include "config.h"
#define TaskStkLengh 64 //Define the Task0 stack length 定义用户任务0的堆栈长度
#define KEY1 (1 << 20) /* P0.20为KEY1 */
// LED控制宏函数定义。LED1--LED4的控制I/O为P2.28--P2.31
#define LED_ADJ 28
#define LED_IOCON (0xFF<<LED_ADJ)
#define LED_OFF() IO2SET=LED_IOCON
#define LED_DISP(dat) LED_OFF(); IO2CLR=((dat)<<LED_ADJ)
#define KeyNo1 0x01 //按键1
#define KeyNo2 0x02 //按键2
#define KeyNo3 0x03 //按键3
#define KeyNo4 0x03 //按键4
OS_STK TaskStk [TaskStkLengh]; //Define the Task0 stack 定义用户任务0的堆栈
void Task0(void *pdata); //Task0 任务0
OS_EVENT *MyMailBox=NULL;
void __irq IRQ_Key1(void)
{
INT8U buf[8],i;
OS_ENTER_CRITICAL();
EXTINT = 1<<3;
buf[0]=KeyNo1;
for(i=1;i<8;i++)
buf[i]=0;
OSMboxPost(MyMailBox,(void *)buf);
EXTINT = 1<<3;
VICVectAddr = 0;
OS_EXIT_CRITICAL();
}
int main (void)
{
OSInit ();
OSTaskCreate (Task0,(void *)0, &TaskStk[TaskStkLengh - 1], 1);
OSStart ();
return 0;
}
/*********************************************************************************************************
** Task0 任务0
********************************************************************************************************/
void Task0 (void *pdata)
{
INT8U *err,i;
INT8U *Msg;
const uint8 DISP_TAB[24] = { 0x0F,0x00,0x0F,0x00,0x0F,0x00,0x0F,0x00,
0x01,0x02,0x04,0x08,0x04,0x02,0x01,0x00,
0x05,0x0A,0x05,0x0A,0x05,0x0A,0x05,0x00 };
pdata = pdata;
MyMailBox=OSMboxCreate(NULL);
if (MyMailBox == NULL)
while (1);
TargetInit ();
PINSEL1 = 3<<8; // 设置管脚连接,P0.20设置为EINT3
PINSEL0 = 0x00000000; // 设置P0口管脚连接GPIO
IO0DIR &= ~KEY1;
IO2DIR = LED_IOCON; // 设置LED1--LED4的控制口为输出
LED_OFF();
// 设置KEY1的控制I/O为输入 // 3<<8 等价于 0x00000180
EXTMODE = 0x00; // 设置EINT3中断为电平触发模式
/* 打开EINT3中断(使用非向量IRQ) */
VICIntSelect = 0x00000000; // 设置所有中断分配为IRQ中断
VICDefVectAddr = (int)IRQ_Key1; // 设置中断服务程序地址
VICVectCntl0 = 0x29;
EXTINT = 1<<3; // 清除EINT3中断标志
VICIntEnable = 1<<17; // 使能EINT3中断,EINT3在Bit17上
for (;;)
{
Msg=(INT8U *)OSMboxPend(MyMailBox,0,err);
switch(Msg[0])
{
case KeyNo1:
{
for(i=0; i<4; i++)
{
LED_DISP(DISP_TAB[i]); // 输出LED显示数据
OSTimeDly(OS_TICKS_PER_SEC/2); // 延时0.5S
}
break;
}
default:
{
OSMboxAccept(MyMailBox);
break;
}
}
}
}
/*********************************************************************************************************
** End Of File
********************************************************************************************************/
答 1: 都是周立功书上的代码,只不过想测试一下中断和消息邮箱上 答 2: 调试中。。。我把这句删除
VICVectCntl0 = 0x29;
并删除了IRQ_Key1(void)中的第一句:EXTINT = 1<<3;
问题更奇怪了,
1。我不加断点:AXD起来后,按一下键盘则4个LED亮起(一直亮),而后再没有反映
2.我在IRQ_Key1(void)中设断点:AXD起来后,按一下键盘,跳到断点处,执行效果如预期的,再按几次键盘,总会有一次断点后执行,LED没有反映,且以后也不能停在断点处
3。我在switch(Msg[0])处设断点:效果如(2.)所列,基本相同
我觉得是程序在哪里跑飞掉了,又不是很确定,请大家调试下看看。。
我的环境是SmartARM2200 + ADSv1_2
谢谢了。
答 3: 我用的LPC2134调过。把堆栈设大点再试试。 答 4: 堆栈大了也没影响哦堆栈设大还一样啊。
我在我以为跑飞的时候stop它,程序停在startup.s文件中的
;取指令中止
PrefetchAbort
B PrefetchAbort------》停在这里
是不是它跑飞掉了啊?正常不是应该停在消息等待处呢?
答 5: 难道这种中断+消息邮箱的机制有问题么?我觉得应该不会啊~~~! 答 6: 那么大家是怎么处理按键中断的中断处理函数里面不能写太多的处理,因此必须放在task中完成,
开始考虑用消息队列,想想可能会有延时的操作,对实时的系统比较难以接受,
那么我就选择了消息邮箱,
下一阶段,就尝试对不同的按键进行响应,大家有什么建议 答 7: 没人气啊是不是我要把程序烧到FLASH里面,才正常呢 答 8: 中断EINT3的中断号错了
EXTMODE = 0x00; // 设置EINT3中断为电平触发模式
/* 打开EINT3中断(使用非向量IRQ) */
VICIntSelect = 0x00000000; // 设置所有中断分配为IRQ中断
VICDefVectAddr = (int)IRQ_Key1; // 设置中断服务程序地址
VICVectCntl0 = 0x29; //分配给向量的中断请求和软 件 编号,EINT3是17号中断,所以设置VIC通道号为17的EINT3的中断源为优先级0的中断应该是VICVectCnt10 = 0x31; (0x20|17);既然设置EINT3为向量中断,就要设置向量中断的地址VICVectAddr0=(int)IRQ_Key1;而不是非向量中断的地址;
EXTINT = 1<<3; // 清除EINT3中断标志
VICIntEnable = 1<<17; // 使能EINT3中断,EINT3在Bit17上
答 9: 还是不行啊??我设为:
VICIntSelect = 0x00000000; // 设置所有中断分配为IRQ中断
VICVectCntl0 = 0x31;
VICVectAddr0=(int)IRQ_Key1;
EXTINT = 1<<3; // 清除EINT3中断标志
VICIntEnable = 1<<17; // 使能EINT3中断,EINT3在Bit17上
中断时候怎么跳转到target.c下面的IRQ_Exception()函数中了呢?
我自己的IRQ_Key1没有响应啊。。。~
答 10: 改为使用非向量IRQ使用非向量IRQ:
EXTMODE = 0x00; // 设置EINT3中断为电平触发模式
VICIntSelect = 0x00000000; // 设置所有中断分配为IRQ中断
VICDefVectAddr = (int)IRQ_Key1; // 设置中断服务程序地址
EXTINT = 1<<3; // 清除EINT3中断标志
VICIntEnable = 1<<17; // 使能EINT3中断,EINT3在Bit17上
然后,我的中断可以进入,但只有我在IRQ_Key1(void)中下了断点,才可以响应,如果去掉断点,就再也进不去了。。。
有没有人用这个设备调试的? 答 11: re你应该看以下,targer.c里面的东西
中断服务程序应该是 irqhander hander IRQ_Key1;
VICVectAddr0 = irqhander; 答 12: 中断问题已经解决,谢谢各位定义:IRQ_KeyHandler HANDLER IRQ_Key1;
然后再指向IRQ_KeyHandler;
多谢《《xiao李》》
顺便问个:如何防止按键抖动? 答 13: re用个延时程序就可以了
例如:
判断有键按下
延时
再判断是否键仍然按下
这样就可以去抖动,延时一般为1到十几个ms! 答 14: 我现在按一下键,就触发两次中断这个算是按键的抖动么?
再问《xiao李》,我的延时是不是加在中断处理子函数中啊?因为只有这里我才知道我触发了按键啊。
可是加了延时,它还是执行一次延时一会再执行一次,就是说还是执行了两次。
是不是程序里的问题啊? 答 15: re你如果用中断来确定按键的话
那你需要设置外部中断寄存器,应该设置为电平触发,好像就可以了,如果是普通IO口,上面的方法可用来去除查询式的抖动! 答 16: 我也遇到中断程序中使用邮箱的问题了请看我在本版的问题《奇怪的定时器中断》
帮我看一下好吗?
我的QQ:272184176
msn:linsf@ustc.edu
希望能讨论一下,
或者回复一下我的帖子,多谢!
在键盘的外部中断处理子程序中发送消息到消息邮箱,task0一直等待消息收到后对LED进行相应的控制。
问题是:我的中断进入几次后就再不进入了,还有调试时现象也不一致(代码没该动)。
现把拼凑的(呵呵)代码贴上,望指教!!!
#include "config.h"
#define TaskStkLengh 64 //Define the Task0 stack length 定义用户任务0的堆栈长度
#define KEY1 (1 << 20) /* P0.20为KEY1 */
// LED控制宏函数定义。LED1--LED4的控制I/O为P2.28--P2.31
#define LED_ADJ 28
#define LED_IOCON (0xFF<<LED_ADJ)
#define LED_OFF() IO2SET=LED_IOCON
#define LED_DISP(dat) LED_OFF(); IO2CLR=((dat)<<LED_ADJ)
#define KeyNo1 0x01 //按键1
#define KeyNo2 0x02 //按键2
#define KeyNo3 0x03 //按键3
#define KeyNo4 0x03 //按键4
OS_STK TaskStk [TaskStkLengh]; //Define the Task0 stack 定义用户任务0的堆栈
void Task0(void *pdata); //Task0 任务0
OS_EVENT *MyMailBox=NULL;
void __irq IRQ_Key1(void)
{
INT8U buf[8],i;
OS_ENTER_CRITICAL();
EXTINT = 1<<3;
buf[0]=KeyNo1;
for(i=1;i<8;i++)
buf[i]=0;
OSMboxPost(MyMailBox,(void *)buf);
EXTINT = 1<<3;
VICVectAddr = 0;
OS_EXIT_CRITICAL();
}
int main (void)
{
OSInit ();
OSTaskCreate (Task0,(void *)0, &TaskStk[TaskStkLengh - 1], 1);
OSStart ();
return 0;
}
/*********************************************************************************************************
** Task0 任务0
********************************************************************************************************/
void Task0 (void *pdata)
{
INT8U *err,i;
INT8U *Msg;
const uint8 DISP_TAB[24] = { 0x0F,0x00,0x0F,0x00,0x0F,0x00,0x0F,0x00,
0x01,0x02,0x04,0x08,0x04,0x02,0x01,0x00,
0x05,0x0A,0x05,0x0A,0x05,0x0A,0x05,0x00 };
pdata = pdata;
MyMailBox=OSMboxCreate(NULL);
if (MyMailBox == NULL)
while (1);
TargetInit ();
PINSEL1 = 3<<8; // 设置管脚连接,P0.20设置为EINT3
PINSEL0 = 0x00000000; // 设置P0口管脚连接GPIO
IO0DIR &= ~KEY1;
IO2DIR = LED_IOCON; // 设置LED1--LED4的控制口为输出
LED_OFF();
// 设置KEY1的控制I/O为输入 // 3<<8 等价于 0x00000180
EXTMODE = 0x00; // 设置EINT3中断为电平触发模式
/* 打开EINT3中断(使用非向量IRQ) */
VICIntSelect = 0x00000000; // 设置所有中断分配为IRQ中断
VICDefVectAddr = (int)IRQ_Key1; // 设置中断服务程序地址
VICVectCntl0 = 0x29;
EXTINT = 1<<3; // 清除EINT3中断标志
VICIntEnable = 1<<17; // 使能EINT3中断,EINT3在Bit17上
for (;;)
{
Msg=(INT8U *)OSMboxPend(MyMailBox,0,err);
switch(Msg[0])
{
case KeyNo1:
{
for(i=0; i<4; i++)
{
LED_DISP(DISP_TAB[i]); // 输出LED显示数据
OSTimeDly(OS_TICKS_PER_SEC/2); // 延时0.5S
}
break;
}
default:
{
OSMboxAccept(MyMailBox);
break;
}
}
}
}
/*********************************************************************************************************
** End Of File
********************************************************************************************************/
答 1: 都是周立功书上的代码,只不过想测试一下中断和消息邮箱上 答 2: 调试中。。。我把这句删除
VICVectCntl0 = 0x29;
并删除了IRQ_Key1(void)中的第一句:EXTINT = 1<<3;
问题更奇怪了,
1。我不加断点:AXD起来后,按一下键盘则4个LED亮起(一直亮),而后再没有反映
2.我在IRQ_Key1(void)中设断点:AXD起来后,按一下键盘,跳到断点处,执行效果如预期的,再按几次键盘,总会有一次断点后执行,LED没有反映,且以后也不能停在断点处
3。我在switch(Msg[0])处设断点:效果如(2.)所列,基本相同
我觉得是程序在哪里跑飞掉了,又不是很确定,请大家调试下看看。。
我的环境是SmartARM2200 + ADSv1_2
谢谢了。
答 3: 我用的LPC2134调过。把堆栈设大点再试试。 答 4: 堆栈大了也没影响哦堆栈设大还一样啊。
我在我以为跑飞的时候stop它,程序停在startup.s文件中的
;取指令中止
PrefetchAbort
B PrefetchAbort------》停在这里
是不是它跑飞掉了啊?正常不是应该停在消息等待处呢?
答 5: 难道这种中断+消息邮箱的机制有问题么?我觉得应该不会啊~~~! 答 6: 那么大家是怎么处理按键中断的中断处理函数里面不能写太多的处理,因此必须放在task中完成,
开始考虑用消息队列,想想可能会有延时的操作,对实时的系统比较难以接受,
那么我就选择了消息邮箱,
下一阶段,就尝试对不同的按键进行响应,大家有什么建议 答 7: 没人气啊是不是我要把程序烧到FLASH里面,才正常呢 答 8: 中断EINT3的中断号错了
EXTMODE = 0x00; // 设置EINT3中断为电平触发模式
/* 打开EINT3中断(使用非向量IRQ) */
VICIntSelect = 0x00000000; // 设置所有中断分配为IRQ中断
VICDefVectAddr = (int)IRQ_Key1; // 设置中断服务程序地址
VICVectCntl0 = 0x29; //分配给向量的中断请求和软 件 编号,EINT3是17号中断,所以设置VIC通道号为17的EINT3的中断源为优先级0的中断应该是VICVectCnt10 = 0x31; (0x20|17);既然设置EINT3为向量中断,就要设置向量中断的地址VICVectAddr0=(int)IRQ_Key1;而不是非向量中断的地址;
EXTINT = 1<<3; // 清除EINT3中断标志
VICIntEnable = 1<<17; // 使能EINT3中断,EINT3在Bit17上
答 9: 还是不行啊??我设为:
VICIntSelect = 0x00000000; // 设置所有中断分配为IRQ中断
VICVectCntl0 = 0x31;
VICVectAddr0=(int)IRQ_Key1;
EXTINT = 1<<3; // 清除EINT3中断标志
VICIntEnable = 1<<17; // 使能EINT3中断,EINT3在Bit17上
中断时候怎么跳转到target.c下面的IRQ_Exception()函数中了呢?
我自己的IRQ_Key1没有响应啊。。。~
答 10: 改为使用非向量IRQ使用非向量IRQ:
EXTMODE = 0x00; // 设置EINT3中断为电平触发模式
VICIntSelect = 0x00000000; // 设置所有中断分配为IRQ中断
VICDefVectAddr = (int)IRQ_Key1; // 设置中断服务程序地址
EXTINT = 1<<3; // 清除EINT3中断标志
VICIntEnable = 1<<17; // 使能EINT3中断,EINT3在Bit17上
然后,我的中断可以进入,但只有我在IRQ_Key1(void)中下了断点,才可以响应,如果去掉断点,就再也进不去了。。。
有没有人用这个设备调试的? 答 11: re你应该看以下,targer.c里面的东西
中断服务程序应该是 irqhander hander IRQ_Key1;
VICVectAddr0 = irqhander; 答 12: 中断问题已经解决,谢谢各位定义:IRQ_KeyHandler HANDLER IRQ_Key1;
然后再指向IRQ_KeyHandler;
多谢《《xiao李》》
顺便问个:如何防止按键抖动? 答 13: re用个延时程序就可以了
例如:
判断有键按下
延时
再判断是否键仍然按下
这样就可以去抖动,延时一般为1到十几个ms! 答 14: 我现在按一下键,就触发两次中断这个算是按键的抖动么?
再问《xiao李》,我的延时是不是加在中断处理子函数中啊?因为只有这里我才知道我触发了按键啊。
可是加了延时,它还是执行一次延时一会再执行一次,就是说还是执行了两次。
是不是程序里的问题啊? 答 15: re你如果用中断来确定按键的话
那你需要设置外部中断寄存器,应该设置为电平触发,好像就可以了,如果是普通IO口,上面的方法可用来去除查询式的抖动! 答 16: 我也遇到中断程序中使用邮箱的问题了请看我在本版的问题《奇怪的定时器中断》
帮我看一下好吗?
我的QQ:272184176
msn:linsf@ustc.edu
希望能讨论一下,
或者回复一下我的帖子,多谢!
共2条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
vscode+cmake搭建雅特力AT32L021开发环境被打赏30分 | |
【换取逻辑分析仪】自制底板并驱动ArduinoNanoRP2040ConnectLCD扩展板被打赏47分 | |
【分享评测,赢取加热台】RISC-V GCC 内嵌汇编使用被打赏38分 | |
【换取逻辑分析仪】-基于ADI单片机MAX78000的简易MP3音乐播放器被打赏48分 | |
我想要一部加热台+树莓派PICO驱动AHT10被打赏38分 | |
【换取逻辑分析仪】-硬件SPI驱动OLED屏幕被打赏36分 | |
换逻辑分析仪+上下拉与多路选择器被打赏29分 | |
Let'sdo第3期任务合集被打赏50分 | |
换逻辑分析仪+Verilog三态门被打赏27分 | |
换逻辑分析仪+Verilog多输出门被打赏24分 |