想在vxworks设计一个轮询程序,每隔几个毫秒从键盘读入一个字符,如果没有键盘输入,则执行其他代码,工作在非阻塞方式下,请问各位大虾该怎么做??
1。之前采用read函数,但此函数对读键盘是阻塞的,(查了一下资料,用ioctl函数设置非阻塞只对socket有效,对其他i/o无效,不知我的理解对不对?)总是阻塞在read。。
2。本来想尝试用kbhit函数和getchar函数一起使用,但编译器不识别kbhit,感觉vxworks库函数中没有kbhit这个函数,或者是我没找到,请教各位大虾,帮一把,谢谢了!
共7条
1/1 1 跳转至页
怎么用非阻塞的方式从键盘读字符?
vxWorks 下没有类似DOS下的kbHit函数。但是可以自己做一个:
目的是为了不阻塞地读键盘码-可以考虑用一个单独的task专门截获按键输入,形成以下几种方式:1. 消息队列,2. 环型缓冲。
1. 如果采用消息队列,则先判断消息队列中的消息个数,等于0就做别的事情,有消息就读出来进行处理。
2. 如果采用环型缓冲,这种数据结构一端读一段写是天然互斥的,键盘截获task截获按键后写入环型缓冲,工作task则读环型缓冲,判断读得的个数,如果>0则读到了按键内容,按你的控制要求依次处理各个按键输入。如果=0,则没有得到按键输入。
把上述的键盘截获task和数据处理任务合起来,就可以形成自己的kbhit函数了。
另外,还有一种搞法,不知道合不合你的要求,既然你的工作task是每隔几个ms就扫描一下键盘,再看是否有按键决定处理键盘事件还是做别的事情,所以,可以这样考虑:
键盘是有中断的,在键盘中断的ISR里面将获得的键盘代码直接通过消息队列发送给你的工作task。而你的工作task则采用一个带超时的msgQReceive,假如超时时间为2个tick。则调用msgQReceive时,如果键盘ISR已经发送了按键消息,则马上返回,得到了键盘码,进行处理,如果没有,则进入阻塞,2个tick之内的任何时刻有按键输出,马上返回,得到键盘码,如果没有,则2个tick一结束,工作任务就绪,得到执行,msgQreceive返回没有得到消息,进行其它事情的处理。这种做法不会遗漏任何键盘输入,响应也快,但是就是工作任务总要等几个体tick,而且你得改键盘驱动,不再采用标准的IO函数如read进行键盘读取。当然了,只要按键可以通过消息给出来,你完全可以不等,把msgQreceive的等待参数设置为0,有消息没消息都立即返回,也不会阻塞。
希望能对你有点帮助。。。
目的是为了不阻塞地读键盘码-可以考虑用一个单独的task专门截获按键输入,形成以下几种方式:1. 消息队列,2. 环型缓冲。
1. 如果采用消息队列,则先判断消息队列中的消息个数,等于0就做别的事情,有消息就读出来进行处理。
2. 如果采用环型缓冲,这种数据结构一端读一段写是天然互斥的,键盘截获task截获按键后写入环型缓冲,工作task则读环型缓冲,判断读得的个数,如果>0则读到了按键内容,按你的控制要求依次处理各个按键输入。如果=0,则没有得到按键输入。
把上述的键盘截获task和数据处理任务合起来,就可以形成自己的kbhit函数了。
另外,还有一种搞法,不知道合不合你的要求,既然你的工作task是每隔几个ms就扫描一下键盘,再看是否有按键决定处理键盘事件还是做别的事情,所以,可以这样考虑:
键盘是有中断的,在键盘中断的ISR里面将获得的键盘代码直接通过消息队列发送给你的工作task。而你的工作task则采用一个带超时的msgQReceive,假如超时时间为2个tick。则调用msgQReceive时,如果键盘ISR已经发送了按键消息,则马上返回,得到了键盘码,进行处理,如果没有,则进入阻塞,2个tick之内的任何时刻有按键输出,马上返回,得到键盘码,如果没有,则2个tick一结束,工作任务就绪,得到执行,msgQreceive返回没有得到消息,进行其它事情的处理。这种做法不会遗漏任何键盘输入,响应也快,但是就是工作任务总要等几个体tick,而且你得改键盘驱动,不再采用标准的IO函数如read进行键盘读取。当然了,只要按键可以通过消息给出来,你完全可以不等,把msgQreceive的等待参数设置为0,有消息没消息都立即返回,也不会阻塞。
希望能对你有点帮助。。。
5楼
非常感谢yaopg的真诚相助,昨晚尝试用键盘中断的方式进行处理,可是键盘输入总是不能产生中断,直接打印到显示器,不知什么原因,代码如下:
/****************/
main()
{
int i;
intConnect((VOIDFUNCPTR*)INUM_TO_IVEC(1+0x20),(VOIDFUNCPTR)key_ISR,0);
intEnable(1); //键盘中断级别1;
while() //不停循环是为了让程序不死
{
taskDelay(6);
i=i%100;
}
}
void key_ISR()
{
logMsg("This is a ISR!",0,0,0,0,0,0);
}
再次请教yaopg大虾,十分感谢!
xiaojunliu :
你好!
看了你上面的代码,觉得有下面几个问题,仅供参考:
1. 你采用了main函数,在vxWorks 6.x的RTP任务里面是有main函数,但它不能直接调用intConnect之类的系统函数。vxWorks 5.x以及不采用RTP的6.x都不需要main函数。
2. intConnect是有返回值的,你的中断挂接不一定成功了,需要做一下返回值判断,建议编程中尽可能多地对有可能返回错误的系统API调用进行返回值判断,可以增强程序健壮性。
3. 在x86体系中应该使用intEnablePIC进行IRQ使能,如果是PPC等,就没有这个问题了。
4. “INUM_TO_IVEC(1+0x20)”直接使用数字的表述方法不太好,最好使用board.h或者config.h中的宏定义。以免出线纰漏和移植时的麻烦。
5. 某些CPU体系的vxWorks实现,如x86,不支持在一个IRQ上同时挂多个ISR,如果已经挂了一个,必须解挂再挂新的。如果要挂多个,有专门的函数,比如,pciIntConnect,通过ISR链表的方式实现,中断一发生,链表中的所有ISR都得到执行,是为共享中断。但是,如果是PPC等,可以直接挂多个ISR,因为PPC基于一个异常基址,内部已经做了中断共享的数据结构。看到你说到显示屏,看来是包含了PC_CONSOLE组件,那么可以肯定地,键盘中断已经被使用了。
6. 对于上面的实现:只要中断挂成功上了,不管你的main函数是否退出,ISR一样会被触发。所以,测试程序可以不用一直循环。(可能对你的意思理解有误)
7. 要改的话,可以考虑在键盘驱动的ISR里面添加代码,而不是增挂一个ISR。又或者直接使用IO函数来read,变成消息队列或者环型缓冲。会通用且方便一些。另外,环型缓冲对于具有串行特性的应用是一个堪称完美的数据结构,在一般的操作系统中,对中断中的调试、串行(如串口、CAN,USB等)通信驱动中被采用,典型的:vxWorks、windows中的串口驱动使用的是环型缓冲,vxWorks的logMsg,linux的printk都是使用的环型缓冲。天然互斥保证了数据完整性,天然不阻塞的特性避免了复杂的系统API调用又保证了效率,非常值得一试。
仅供参考:)
你好!
看了你上面的代码,觉得有下面几个问题,仅供参考:
1. 你采用了main函数,在vxWorks 6.x的RTP任务里面是有main函数,但它不能直接调用intConnect之类的系统函数。vxWorks 5.x以及不采用RTP的6.x都不需要main函数。
2. intConnect是有返回值的,你的中断挂接不一定成功了,需要做一下返回值判断,建议编程中尽可能多地对有可能返回错误的系统API调用进行返回值判断,可以增强程序健壮性。
3. 在x86体系中应该使用intEnablePIC进行IRQ使能,如果是PPC等,就没有这个问题了。
4. “INUM_TO_IVEC(1+0x20)”直接使用数字的表述方法不太好,最好使用board.h或者config.h中的宏定义。以免出线纰漏和移植时的麻烦。
5. 某些CPU体系的vxWorks实现,如x86,不支持在一个IRQ上同时挂多个ISR,如果已经挂了一个,必须解挂再挂新的。如果要挂多个,有专门的函数,比如,pciIntConnect,通过ISR链表的方式实现,中断一发生,链表中的所有ISR都得到执行,是为共享中断。但是,如果是PPC等,可以直接挂多个ISR,因为PPC基于一个异常基址,内部已经做了中断共享的数据结构。看到你说到显示屏,看来是包含了PC_CONSOLE组件,那么可以肯定地,键盘中断已经被使用了。
6. 对于上面的实现:只要中断挂成功上了,不管你的main函数是否退出,ISR一样会被触发。所以,测试程序可以不用一直循环。(可能对你的意思理解有误)
7. 要改的话,可以考虑在键盘驱动的ISR里面添加代码,而不是增挂一个ISR。又或者直接使用IO函数来read,变成消息队列或者环型缓冲。会通用且方便一些。另外,环型缓冲对于具有串行特性的应用是一个堪称完美的数据结构,在一般的操作系统中,对中断中的调试、串行(如串口、CAN,USB等)通信驱动中被采用,典型的:vxWorks、windows中的串口驱动使用的是环型缓冲,vxWorks的logMsg,linux的printk都是使用的环型缓冲。天然互斥保证了数据完整性,天然不阻塞的特性避免了复杂的系统API调用又保证了效率,非常值得一试。
仅供参考:)
7楼
再次感谢yaopg大虾的指教,我采用一个任务(级别高一点),然后用read函数,设置opt_raw模式,然后让它阻塞,这样当有键盘字符输入的话,立马相应,然后再用switch语句进行操作,尝试了一下,没有什么问题。
真的很感谢yaopg的不吝指教,谢谢!
真的很感谢yaopg的不吝指教,谢谢!
共7条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
与电子爱好者谈读图四被打赏50分 | |
与电子爱好者谈读图二被打赏50分 | |
【FRDM-MCXN947评测】Core1适配运行FreeRtos被打赏50分 | |
【FRDM-MCXN947评测】双核调试被打赏50分 | |
【CPKCORRA8D1B评测】---移植CoreMark被打赏50分 | |
【CPKCORRA8D1B评测】---打开硬件定时器被打赏50分 | |
【FRDM-MCXA156评测】4、CAN loopback模式测试被打赏50分 | |
【CPKcorRA8D1评测】--搭建初始环境被打赏50分 | |
【FRDM-MCXA156评测】3、使用FlexIO模拟UART被打赏50分 | |
【FRDM-MCXA156评测】2、rt-thread MCXA156 BSP制作被打赏50分 |