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);

楼主,请速度改正啊。被人家揪出来了。
页: 1 2 [3] 4 5 6
查看完整版本: [分享][交流]发一个通用按键模块,简单易用 [2014-3-24 Update]