guolun
发表于 2014-3-31 16:20:52
本帖最后由 guolun 于 2014-3-31 16:24 编辑
foxpro2005 发表于 2014-3-9 23:13
今天有时间看了一下代码,感觉还可以做如下优化:
(声明,本人是小白菜,说错了还望包涵... )
...
我喜欢把注释调成很淡的颜色。这样的话,突出代码,注释淡化。(利用摄影中的背景虚化的想法。)
Gorgon_Meducer
发表于 2014-4-1 10:43:22
guolun 发表于 2014-3-31 16:20
我喜欢把注释调成很淡的颜色。这样的话,突出代码,注释淡化。(利用摄影中的背景虚化的想法。)
...
这个想法不错
cshm0101
发表于 2014-4-1 13:59:02
收藏,学习!
bondxie3
发表于 2014-4-2 11:07:13
请问楼主END_DEF_CLASS中:
sizeof(uint_fast8_t) - 1
要加这个是什么意思,不就是0么?难道有的mcuuint_fast8_t不是1字节?
bondxie3
发表于 2014-4-2 11:11:38
另外,为什么要定义struct+union?union有特殊用途?
感觉还是《UML+OOPC嵌入式C语言开发精讲》书中讲述的CLASS定义简单明了。
ArthurBruin
发表于 2014-4-2 11:18:22
好有前途的说!
y574924080
发表于 2014-4-2 11:18:49
bondxie3 发表于 2014-4-2 11:07
请问楼主END_DEF_CLASS中:
sizeof(uint_fast8_t) - 1
要加这个是什么意思,不就是0么?难道有的mcuuint_f ...
uint_fast8_t 还真不一定是8位的,请看这里:
C_data_types(wiki)
jsntzxh
发表于 2014-4-2 11:19:20
收藏一个,赞一个。
y574924080
发表于 2014-4-2 11:21:31
bondxie3 发表于 2014-4-2 11:11
另外,为什么要定义struct+union?union有特殊用途?
感觉还是《UML+OOPC嵌入式C语言开发精讲》书中讲述的C ...
这是一个封装技巧
具体请看 [交流][微知识]模块的封装(一):C语言类的封装
jiwx2011
发表于 2014-4-2 11:24:50
高高手。。
bondxie3
发表于 2014-4-2 13:03:53
y574924080 发表于 2014-4-2 11:21
这是一个封装技巧
具体请看 [交流][微知识]模块的封装(一):C语言类的封装 ...
谢谢楼主,http://www.cnblogs.com/dylan2011/archive/2012/09/18/2690580.html供大家参考抽象数据类型的介绍。
mainbp
发表于 2014-4-2 14:14:35
这些肯定会用到,稍后慢慢仔细阅读
wxty
发表于 2014-4-8 18:07:15
在QUEUE操作中关中断还是存在问题,什么情况?
atonghua
发表于 2014-4-8 22:06:29
写过矩阵的吗?
y574924080
发表于 2014-4-8 22:16:16
wxty 发表于 2014-4-8 18:07
在QUEUE操作中关中断还是存在问题,什么情况?
有什么问题?能具体描述一下么?
我这边进行过简单的测试,没有发现问题
zyc
发表于 2014-4-9 07:31:26
谢谢分享
xujihu
发表于 2014-4-9 08:42:30
写的很好
wxty
发表于 2014-4-9 11:19:14
y574924080 发表于 2014-4-8 22:16
有什么问题?能具体描述一下么?
我这边进行过简单的测试,没有发现问题
现象是,从队列中取出消息时,会多取,如图:
消息入队列没问题,短按一次,共3个消息: KEY_DONW / KEY_UP / KEY_PRESSED 共三个消息,取了4次才取完。
随机的,一个消息可能会取多次,直到队列为空,楼主可以用串口测试下,每取一次发送一次看看。
ZHW0117
发表于 2014-4-9 11:29:53
果断收藏!
wxty
发表于 2014-4-9 11:37:18
y574924080
发表于 2014-4-9 12:33:05
wxty 发表于 2014-4-9 11:19
现象是,从队列中取出消息时,会多取,如图:
我这边验证过这个,确实没有问题
另外有个想确认一下,你的开关全局中断的函数能保证原子性么?
y574924080
发表于 2014-4-9 12:34:55
wxty 发表于 2014-4-9 11:37
不好意思,我这边没办法复现这个问题
能问一下开关中断函数是怎么实现的么?
这里的开关中断函数需要保证原子的
wxty
发表于 2014-4-9 12:40:56
y574924080 发表于 2014-4-9 12:34
不好意思,我这边没办法复现这个问题
能问一下开关中断函数是怎么实现的么?
#include <intrins.h>
//提供
enable_interrupt();
disable_interrupt();
编译器头文件自带的,应该能保证吧。
y574924080
发表于 2014-4-9 14:18:23
本帖最后由 y574924080 于 2014-4-9 14:25 编辑
不好意思,看错了
y574924080
发表于 2014-4-9 15:05:13
wxty 发表于 2014-4-9 12:40
编译器头文件自带的,应该能保证吧。
我这边怎么也无法重现这个问题。
如果能提供一个范例,重现这个问题的话,我可以尝试找是哪里出现bug {:loveliness:}
liu615
发表于 2014-4-9 15:37:11
好贴,谢谢分享
wxty
发表于 2014-4-9 16:46:27
本帖最后由 wxty 于 2014-4-9 16:51 编辑
y574924080 发表于 2014-4-9 15:05
我这边怎么也无法重现这个问题。
如果能提供一个范例,重现这个问题的话,我可以尝试找是哪里出现bug {: ...
谢谢啊,分析了很久,找到了出问题的地方。
队列的入队出队部分没有问题,问题在主循环中调用
GetKeyEvent(key_event_t* ptdKey)
{
return KeyEventDeQueue(&stdKeyDetectQueue, ptdKey);
}
函数时,出现了问题:
当队列无消息(队列为空)时,本应返回FALSE,却返回了TRUE,所以向串口又发送了一次上次发送的数据。
仔细观察DeQueue()函数内部代码,尚不明白队列为空时如何产生的TRUE返回值。
调试时,bn值为TRUE(非零,却不为0x01)的现象。
分别增加了几个计数器用于调试:
队列操作计数器,入队次数==出队次数。
主循环获得消息次数却大于队列操作中的出队次数。说明在队列为空时,获取消息函数返回了TURE。
另外,我用的是8位单片机,KeyTask()每5ms中断中调用一次,GetKeyEvent()函数在主循环中获取消息并处理。
按键处理函数
#define KEY_11
uint8_t ScanKeyVal(void)
{
if(!P0.0)
{
return KEY_1;
}
return KEY_NULL;
}
宏定义:
#ifndef FALSE
#define FALSE (0)
#endif
#ifdef TRUE
#undef TRUE
#endif
#define TRUE (!FALSE)
编辑:增加代码。
ZYBing
发表于 2014-4-9 20:06:17
学习,谢谢
y574924080
发表于 2014-4-9 21:50:22
wxty 发表于 2014-4-9 16:46
谢谢啊,分析了很久,找到了出问题的地方。
队列的入队出队部分没有问题,问题在主循环中调用
具体问题在哪里我也不能确定
不过我觉得有个需要注意的是:不要和TRUE进行比较(即只和FALSE比较)
因为这会导致本来TRUE的情况变成FALSE。。。。。。
要不修复这个小问题先?
wxty
发表于 2014-4-10 10:28:46
本帖最后由 wxty 于 2014-4-10 11:02 编辑
y574924080 发表于 2014-4-9 21:50
具体问题在哪里我也不能确定
不过我觉得有个需要注意的是:不要和TRUE进行比较(即只和FALSE比较)
嗯,还是按原来的方法处理,把开关中断放到出队列函数外面就OK了。
BOOL GetKeyEvent(key_event_t* ptdKey) //主循环中获取消息并处理,KeyTask()还是放在5MS中断中处理的。
{
BOOL bn;
disable_interrupt(); // 外部关了中断,队列操作内部不需要再关中断
bn = KeyEventDeQueue(&stdKeyDetectQueue, ptdKey);
enable_interrupt(); //然后就一切正常了
return bn; //KeyEventDeQueue(&stdKeyDetectQueue, ptdKey);
}
显示,AD采样,按键,消息入队出队都正常,程序应该没有跑飞。
采用在出队列操作函数内部开关中断时,不知道发生了什么,KeyEventDeQueue()函数返回的BOOL值不正确,队列为空时,不仅返回了TRUE(0X01),还有其他不为FALSE(0X00)的情况,非零的随机数。
编辑:添加注释。
wxty
发表于 2014-4-10 10:35:17
附图一张。
串口接收字节:
后半字节表示键值,这里全为1;
前半字节表示按键事件0-UP,1-DOWN,2-PRESSED,3-DBL_PRESSED,4-LONG_PRESSED,5-REPEAT
入队出队计数器,主循环中获取消息次数三者保持一致。
y574924080
发表于 2014-4-10 14:54:03
wxty 发表于 2014-4-10 10:28
嗯,还是按原来的方法处理,把开关中断放到出队列函数外面就OK了。
显示,AD采样,按键,消息入队出队都 ...
好吧,理解不能。。。。
开关中断是为了保护共享资源的不得不做的操作,
但是开关中断的时间应该尽量短。
能不能做这个尝试:一步一步缩小开关中断的范围,
确定最小的能工作的范围,说不定能找到问题所在{:loveliness:}
wxty
发表于 2014-4-10 18:18:27
y574924080 发表于 2014-4-10 14:54
好吧,理解不能。。。。
开关中断是为了保护共享资源的不得不做的操作,
嗯,经过确认,堆栈余量还很大。
在DeQueue()函数内部开关中断,怎么都不行;不作开关中断处理,还是一样的问题现象。
必须要在函数DeQueue()外部开关中断就正常了。
另外,如果将KeyTask()也放在主循环中,结果是正常的。
实在是不知道为什么了。
分析了一下,其实DeQueue()的重入应该不存在操作共享资源的问题。
昨晚在某16位单片机,32M频率下,KeyTask()放在中断中,DeQueue()放在主循环,没有任何开关中断处理,结果是正常的。
但是对于这款8位单片机,4M频率下运行,只要把KeyTask()放在中断中的话,就需要在DeQueue()外部开关中断,除非两者都放在主循环。
放弃继续往下分析了,按照如下处理:
BOOL GetKeyEvent(key_event_t* ptdKey) //主循环调用,最终获取按键事件并处理。
{
BOOL bn;
disable_interrupt();
bn = KeyEventDeQueue(&stdKeyDetectQueue, ptdKey);
enable_interrupt();
return bn; //KeyEventDeQueue(&stdKeyDetectQueue, ptdKey);
}
y574924080
发表于 2014-4-10 21:00:53
wxty 发表于 2014-4-10 18:18
嗯,经过确认,堆栈余量还很大。
在DeQueue()函数内部开关中断,怎么都不行;不作开关中断处理,还是一 ...
对queue来说,enqueue和dequeue都使用了同样的静态变量,这些静态变量就是共享资源。
操作如果enqueue和dequeue不在同一任务平面,例如说enqueue在中断里,dequeue在主
循环,它们不在同一任务平面,这时候enqueue可能打断dequeue操作,出现不可预料的问
题。
解决办法是加保护。我使用的是关中断保护,这里就要求关中断/关中断是原子的,也就是
开中断只需要一条指令,关中断也只需要一条指令。能确认你的8位MCU有相关的指令支持么?
Jmhh247
发表于 2014-4-11 01:07:49
学习……世界有救啦……
boss2013
发表于 2014-4-11 06:11:50
收藏,谢谢分享
wxty
发表于 2014-4-11 09:18:53
y574924080 发表于 2014-4-10 21:00
对queue来说,enqueue和dequeue都使用了同样的静态变量,这些静态变量就是共享资源。
操作如果enq ...
嗯,其他的不做评论,开关中断的原子性可以确定:
wjjcyy
发表于 2014-4-11 09:40:14
谢谢谢谢,改天试用下?!
Gorgon_Meducer
发表于 2014-4-11 10:26:34
wxty 发表于 2014-4-10 10:28
嗯,还是按原来的方法处理,把开关中断放到出队列函数外面就OK了。
显示,AD采样,按键,消息入队出队都 ...
什么编译器?什么芯片?
电子小生
发表于 2014-4-11 10:33:02
mark下,学习了
机器人天空
发表于 2014-4-11 11:21:52
学习一下
lingergz
发表于 2014-4-11 11:44:07
果断mark啊,这么经典的东西。辛苦了,楼主!
wxty
发表于 2014-4-11 13:41:49
本帖最后由 wxty 于 2014-4-11 16:44 编辑
Gorgon_Meducer 发表于 2014-4-11 10:26
什么编译器?什么芯片?
谢谢傻孩子,这颗芯片不是很常用,较老的RENESAS 740系列的,IDE是HEW,集成的ICC740编译器。
这个按键模块是健全的,其他片子测试也是正常的。应该是其他的原因,俺却无力分析出来。
编辑:修改编译器名称。
Gorgon_Meducer
发表于 2014-4-11 13:59:52
wxty 发表于 2014-4-11 13:41
谢谢傻孩子,这颗芯片不是很常用,较老的RENESAS 740系列的,IDE是HEW,集成的ICC740编译器。
这个按键模 ...
查一下编译器的栈结构,有可能不是标准的栈模型。比如IAR和ICC在AVR芯片上就不是标准的栈模型
——硬件栈(只负责PC指针)和软件栈(负责局部变量分配)就是分开的,这类情况下有可能导致,
看似程序正常执行,但是函数返回值总是出现莫名其妙的问题。
zclcom79
发表于 2014-4-11 14:17:27
mark 一下
wxty
发表于 2014-4-11 18:29:12
Gorgon_Meducer 发表于 2014-4-11 13:59
查一下编译器的栈结构,有可能不是标准的栈模型。比如IAR和ICC在AVR芯片上就不是标准的栈模型
——硬件栈 ...
偶买噶。我怀疑找到问题所在了。。。
关键代码如下:
BOOL KeyEventDeQueue(key_queue_t * ptdKeyQueue, key_event_t *ptdKey)
{
// BOOL bnReturn;
__key_queue_t *ptdQ;// = (__key_queue_t *)ptdKeyQueue; //此处被中断,造成了后果。
disable_interrupt();
ptdQ = (__key_queue_t *)ptdKeyQueue; //放在这里后结果正常。
//…………
CSTACK地址范围0x0100~0x015f,向下增长型。如下图所示,可以看出余量还很大。
设置0X5A..0X5B等做标记,发现每次多发出的数据来栈顶地址0x0101开始的数据,每多发一次,地址往下加1。
注意,因为每次只进行了读操作,所以已使用的栈未遭到破坏,程序没有跑飞。
队列FrontQueue 开始地址0x01BC
队列DetectQueue起始地址0X01C5
分析,不同于16/32位机,对于8位机单机来说,不能保证下面这条语句的原子性。
__key_queue_t *ptdQ = (__key_queue_t *)ptdKeyQueue;
一旦被打断,中断返回后,猜测ptdQ只得到了高字节地址(0X0100),则会得到依次从0x0101往下的数据。
只是DeQueue()的返回值(实际为uint8_t类型)不知道被存储在哪里的,也被打乱了。。。
编辑:请求傻孩子大哥解释。
y574924080
发表于 2014-4-11 19:34:07
wxty 发表于 2014-4-11 18:29
偶买噶。我怀疑找到问题所在了。。。
关键代码如下:
我记得这句代码只是逻辑的转换,不应该生成代码的
Gorgon_Meducer
发表于 2014-4-13 23:07:01
y574924080 发表于 2014-4-11 19:34
我记得这句代码只是逻辑的转换,不应该生成代码的
取决于编译器了,有的编译器比较SB。还有,你看看队列类型是否加了volatile。
Gorgon_Meducer
发表于 2014-4-13 23:14:43
本帖最后由 Gorgon_Meducer 于 2014-4-14 00:39 编辑
wxty 发表于 2014-4-11 18:29
偶买噶。我怀疑找到问题所在了。。。
关键代码如下:
把代码恢复成肯定会出错的形式,然后把ptdQ变量的值(也就是指针的数值)打印出来。
理论上应该是个常熟。出错的时候应该可以打印出不同的数值出来。我大体知道怎么回事了。
xiaobendan
发表于 2014-4-14 08:43:08
顶一下,回头仔细看
gfy200866
发表于 2014-4-14 09:00:02
简单易用啊!!
wxty
发表于 2014-4-14 09:32:04
Gorgon_Meducer 发表于 2014-4-13 23:14
把代码恢复成肯定会出错的形式,然后把ptdQ变量的值(也就是指针的数值)打印出来。
理论上应该是个常熟 ...
看来可以确认了,如图RAM地址0X0101亮了。
串口打印出一次DeQueue的pBuff值为01 01,而打印的(A8 01)为FrontQueue的正确值,(B2 01)为DeQueue的正确值。
另外:
这条语句为一个先定义后赋值的语句,有不产生代码的编译器吗?
y574924080
发表于 2014-4-14 11:34:59
Gorgon_Meducer 发表于 2014-4-13 23:07
取决于编译器了,有的编译器比较SB。还有,你看看队列类型是否加了volatile。
...
没有加。。。。我用的是 DEF_CLASS
y574924080
发表于 2014-4-14 11:40:27
wxty 发表于 2014-4-14 09:32
看来可以确认了,如图RAM地址0X0101亮了。
串口打印出一次DeQueue的pBuff值为01 01,而打印的(A8 01)为 ...
因为是直接把形参进行类型转换,这只是逻辑上的转换而已,不应该生成代码的
Gorgon_Meducer
发表于 2014-4-14 16:38:22
wxty 发表于 2014-4-14 09:32
看来可以确认了,如图RAM地址0X0101亮了。
串口打印出一次DeQueue的pBuff值为01 01,而打印的(A8 01)为 ...
从汇编代码上看,好像只有一个通用寄存器啊……你确认是只有一个通用寄存器么?这个通用寄存器难道被中断
打断的时候不会被PUSH到栈里面,从中断退出以后再POP出来么?
感觉有点奇葩啊。你能沿着这个线索再去看看数据手册么?主要是看看通用寄存器,然后就是中断的出入栈。
hongjie0216
发表于 2014-4-29 10:53:10
没弄明白 两个app_cfg.h的包含关系
Gorgon_Meducer
发表于 2014-4-29 11:07:23
hongjie0216 发表于 2014-4-29 10:53
没弄明白 两个app_cfg.h的包含关系
每个app_cfg.h都自动引用上一级目录下的app_cfg.h,如此往复,直到顶层。
jesseczn
发表于 2014-4-29 14:50:24
这个实在是太强大的!
yutianku
发表于 2014-4-29 15:47:56
本帖最后由 yutianku 于 2014-4-29 15:50 编辑
有在51上移植成功的大侠吗?一步一步来的,keil编译老是不过,求指教
keil中似乎找不到stdint.h stdbool.h这几个头文件……
catwill
发表于 2014-4-29 16:46:15
本帖最后由 Gorgon_Meducer 于 2014-4-29 16:59 编辑
51上可以自己写这两个文件~
但是不要用这个名字就好了——如果以后keilc51编写了这两个文件,你的文件就和系统文件重名了。
只是定义了常用的类型
文件的内容可以类似这样:
/* 定义数据类型 ------------------------------------------------------------- */
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned int uint16_t;
typedef signed int int16_t;
typedef unsigned long uint32_t;
typedef signed long int32_t;
typedef uint8_t bool;
#define false 0
#define true (!false)
写在一个文件里也可以~
yutianku
发表于 2014-4-29 17:07:18
catwill 发表于 2014-4-29 16:46
51上可以自己写这两个文件~
但是不要用这个名字就好了——如果以后keilc51编写了这两个文件,你的文件就和 ...
多谢指点!
OOPC.h文件,没整明白,编译还是报错!
union是否需要定义一下呢?
Gorgon_Meducer
发表于 2014-4-29 18:36:00
本帖最后由 Gorgon_Meducer 于 2014-4-29 18:40 编辑
yutianku 发表于 2014-4-29 17:07
多谢指点!
OOPC.h文件,没整明白,编译还是报错!
你的编译器不支持C99,你找一个支持C99的Keil版本看看。
实在不行,可能要改写部分宏。你先试试看,是否能找到支持C99的Keil。
你也可以先尝试将那一行里面的“...”删除掉,然后把第二行 __VA_ARGS__ 整行删除掉,务必确保宏续航符“\”后面没有任何字符(包括空格)
也就是用下面的内容来替换
#define EXTERN_CLASS(__NAME) \
typedef union __NAME __NAME;\
union __NAME {\
uint_fast8_t chMask[(sizeof(struct{
后面还有类似问题,尝试相同的方法处理。
飞鱼爱上鸟
发表于 2014-4-29 20:51:57
mark 11111
xujihu
发表于 2014-4-29 21:28:14
高手
yutianku
发表于 2014-4-30 23:15:55
Gorgon_Meducer 发表于 2014-4-29 18:36
你的编译器不支持C99,你找一个支持C99的Keil版本看看。
实在不行,可能要改写部分宏。你先试试看,是否 ...
感谢大师的指点!
按照您的指点修改相关宏之后再编译,keil不再报以上错误;又折腾了一下午移植到51单片机基本成功!小结一下:
1、模块中宏定义变量较多,keil编译后生成的hex较大,flash较小的单片机如STC12C2052(2KB),可能不能下载,提示“件大小超出范围,超出部分已被自动截取,换成STC12C5410(10K)后下载成功,此问题也可能是keil和谐的缘故造成……
2、keil2和keil4均不支持C99,不清楚其他版本keil是否支持…?模块中用到的stdint.h stdbool.h这几个头文件所包含的数据类型定义需要手动添加,如大侠“catwill”所述:
/* 定义数据类型 ------------------------------------------------------------- */
typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef unsigned int uint16_t;
typedef signed int int16_t;
typedef unsigned long uint32_t;
typedef signed long int32_t;
/** Fast types.*/
/** Signed.*/
typedef signed char int_fast8_t;
/** Unsigned.*/
typedef unsigned char uint_fast8_t;
typedef uint8_t bool;
#define false 0
#define true (!false)
#define NULL ((void *)0) //定义空指针变量
另外,oopc.H部分按照”傻孩子“大师指点修改。
3、模型文件有少许错误,需要修改
,key_interface.h文件中的枚举定义最后一个量不应该有标点符号,这个问题比较难发现,找了很久才找到,汗……,不过奇怪的是keil4中居然不报错!
,bool print_key1_down(void)相关函数的串口函数需要修改;
4、 key_task();
key_app();貌似只有在超级循环中才有用,在定时器中断处理程序中被周期性的调用 不正常,不知何故……
5、目前还存在一些问题,多次按键程序易卡死,长按与连按还不能很好区分……
总之,经实测试此通用按键模块功能很强大,架构很巧妙,其中很多地方值得反复推敲学习,不过,实际应用还得灵活处理,以上仅小白个人所得,浅陋之处还望高手斧正!
Gorgon_Meducer
发表于 2014-5-1 02:10:22
本帖最后由 Gorgon_Meducer 于 2014-5-1 02:11 编辑
yutianku 发表于 2014-4-30 23:15
感谢大师的指点!
按照您的指点修改相关宏之后再编译,keil不再报以上错误;又折腾了一下午移植到51单片 ...
宏没有变量的概念,也不会实际占用空间,他们在编译阶段就已经不存在了。
代码尺寸较大与宏无关。放在超级循环里面才可以用,而放中断不可用的情况
请检查是否做了中断的临界区保护。这个叙述请看前面的帖子。至于你说的
容易卡死的情况应该不简单是代码逻辑的问题,代码逻辑本身是没有问题的。
需要认真考虑编译环境对结果的影响,我也有点怀疑你的存储器资源太小,而
库默认的队列相对51又太大了。不知道你能不能找到百分百卡死的情况?然后
在这个基础上再分析下?
关于逗号的问题,不是bug,而是C标准不同导致的。C99没有这个限制。
enovo2468
发表于 2014-5-2 12:27:37
我想到了一个问题,组合按键怎么办呢?
enovo2468
发表于 2014-5-2 19:48:54
yutianku 发表于 2014-4-30 23:15
感谢大师的指点!
按照您的指点修改相关宏之后再编译,keil不再报以上错误;又折腾了一下午移植到51单片 ...
搞了一下午,不知哪里出问题了
能把你改的传上来看下吗?
enovo2468
发表于 2014-5-2 21:46:08
test 2F.rar 找不到..\..\device.h
Fatal Error: cannot open source file "..\..\device.h" H:\test 2F\test 2F\systick\systick.c 3
enovo2468
发表于 2014-5-3 17:04:16
终于好了,要把IAR的弄掉
enovo2468
发表于 2014-5-3 18:27:01
当KEY2长按时,KEY1可以打断KEY2
当KEY1长按时,KEY2不可以打断KEY1
o0pingu0o1
发表于 2014-5-3 18:28:53
mark一下子,这个给好好学学
yutianku
发表于 2014-5-4 13:17:09
Gorgon_Meducer 发表于 2014-5-1 02:10
宏没有变量的概念,也不会实际占用空间,他们在编译阶段就已经不存在了。
代码尺寸较大与宏无关。放在超 ...
受教了,多谢指点!
bingshuihuo888
发表于 2014-5-6 10:48:42
没有矩阵的吗?单按键口IO耗费比较大呀
catwill
发表于 2014-5-6 11:30:32
例子是单键的,不代表不支持矩阵按键
Gorgon_Meducer
发表于 2014-5-7 13:19:46
enovo2468 发表于 2014-5-3 18:27
当KEY2长按时,KEY1可以打断KEY2
当KEY1长按时,KEY2不可以打断KEY1
这是KeyScan函数返回值的优先级导致的。组合按键只要KeyScan函数给其一个
编码就可以了,不难。
Ω囿圉Ω
发表于 2014-5-7 19:14:11
标记一下,有空回来看
heyong9
发表于 2014-5-16 17:42:39
标记一下
10xjzheng
发表于 2014-5-16 21:02:31
先收藏着先
10xjzheng
发表于 2014-5-17 11:03:14
好像很牛逼的样子,看不懂,也不懂怎么移植,能不能搞大众点?可能研究起来要花费点功夫
Gorgon_Meducer
发表于 2014-5-17 12:07:27
本帖最后由 Gorgon_Meducer 于 2014-5-17 12:12 编辑
10xjzheng 发表于 2014-5-17 11:03
好像很牛逼的样子,看不懂,也不懂怎么移植,能不能搞大众点?可能研究起来要花费点功夫 ...
模块做出来不是给人看的,是给人用的。如果不好用,欢迎提意见。
本来就不是拿来看的,为什么要“大众一点”?因为大众都用肩扛,我有
车轮却故意不用来博取什么东西么?应该首先推广车轮,然后和少数
有能力发明轮子的人讨论才对吧?人人都发明轮子?实际不可能是这样,
实际也做不到。
移植看一楼,有手把手教程,具体哪一步不懂,提出来,给你解释。只飘了一眼
就这么评论了,你说的话我们也爱莫能助——根本没提出具体问题,怎么给你解释?
我这次说话很冲,针对的是这件事的态度,我觉得不是好苗头。不针对你个人。
10xjzheng
发表于 2014-5-17 12:44:31
Gorgon_Meducer 发表于 2014-5-17 12:07
模块做出来不是给人看的,是给人用的。如果不好用,欢迎提意见。
本来就不是拿来看的,为什么要“大众一 ...
楼主激动了,因为目前项目比较紧,所以移植的话还是要好好看。我懂你说的大众那些,问题是现在你是要写给大众用啊,我说的是移植,可能你用得多,所以就简单。以后有空再看看。
Gorgon_Meducer
发表于 2014-5-17 12:56:16
10xjzheng 发表于 2014-5-17 12:44
楼主激动了,因为目前项目比较紧,所以移植的话还是要好好看。我懂你说的大众那些,问题是现在你是要写给 ...
期待你的回复。是否好移植,你们说了算。
DevLabs
发表于 2014-5-27 23:03:02
本帖最后由 DevLabs 于 2014-5-27 23:20 编辑
Gorgon_Meducer 发表于 2014-5-17 12:56
期待你的回复。是否好移植,你们说了算。
发现一点问题, 但不知道是不是有意为之.
当在一个键按下的状态, 再按另一个键:
此时, s_chLastKeyValue != KEY_NULL, 所以会产生一个KEY_UP事件,
同时因为 s_chNowKeyValue != KEY_NULL 亦成立, 所以还会产生一个KEY_DOWN事件.
而实际上此时没有键放开, 按道理KEY_UP事件不应该存在.
我移植了这个模块试了一下, 确实如此:
上图是先按住KEY2不放, 再按下KEY1, 再松开KEY1, 最后松开KEY2这个过程产生的所有事件, 虽然与实际不符, 但是却能在按下一个键的情况下正常识别另一个按键.
y574924080
发表于 2014-5-28 10:21:27
DevLabs 发表于 2014-5-27 23:03
发现一点问题, 但不知道是不是有意为之.
的确是有意为之~
Gorgon_Meducer
发表于 2014-5-28 10:30:25
DevLabs 发表于 2014-5-27 23:03
发现一点问题, 但不知道是不是有意为之.
有意为之,这主要是增加模块的强壮性。其实这里存在一个按键优先级的问题,而这个优先级是用户的
扫描函数决定的,如果用户扫描函数在某个键按下的时候,其它按键即便被按下也不会返回值,则说明
被按下的键优先级最高。比如,你先按下KEY1保持不动再按KEY2就不会出现你描述的情况。
总结:按键优先级客观存在且不受key模块控制,由用户扫描程序确定,因此,我们只能增加对这类情况
的支持,以提高服务的鲁棒性。
catwill
发表于 2014-5-29 10:44:08
楼主第一个状态图明显和程序不对应
对应的状态图:
zhiyuanzhitian
发表于 2014-5-29 13:07:06
mark..........
ppdd
发表于 2014-6-10 16:09:18
果断收了,学习下。
beaboss
发表于 2014-6-10 17:45:50
按键设计 MARK 学习一下
yytyu
发表于 2014-6-17 14:27:42
标记一下,备用.
guowanling8061
发表于 2014-6-17 14:42:29
好东西不是说出来的,时做出来的!!
zjk
发表于 2014-6-17 17:20:07
mark,标记。。。
mathison
发表于 2014-6-17 20:40:03
按键代码写的比我写的好很多啊 我写的只能说 能用
lizhaoxx
发表于 2014-7-16 10:33:02
KEY Detector 状态图中长按计时的两个迁移条件false分别指的什么,不看代码很难看懂
Gorgon_Meducer
发表于 2014-7-16 12:25:09
lizhaoxx 发表于 2014-7-16 10:33
KEY Detector 状态图中长按计时的两个迁移条件false分别指的什么,不看代码很难看懂 ...
状态的名字叫做“获取按键事件”,则true表示成功的获得了按键事件,false表示没有获得按键事件
ArthurBruin
发表于 2014-7-16 12:31:31
学习
jiespring
发表于 2014-7-16 13:14:33
马克一下,非常实用啊
lizhaoxx
发表于 2014-7-16 15:25:31
static bool key_frontend(void)
{
static uint8_t s_chState = KEY_FRONTEND_START;
static uint8_t s_chNowKeyValue = KEY_NULL;
static uint8_t s_chLastKeyValue = KEY_NULL;
key_event_t tKey = {KEY_NULL, KEY_UP};
return fsm_rt_on_going;
函数返回bool,你的returnfsm_rt_on_going
Gorgon_Meducer
发表于 2014-7-17 10:18:15
lizhaoxx 发表于 2014-7-16 15:25
static bool key_frontend(void)
{
static uint8_t s_chState = KEY_FRONTEND_START;
bug,不多说,就是bug
正确的原型应该是
static fsm_rt_t key_frontend(void);
楼主,请速度改正啊。被人家揪出来了。