十一月 | ||||||
---|---|---|---|---|---|---|
日 | 一 | 二 | 三 | 四 | 五 | 六 |
27 | 28 | 29 | 30 | 31 | 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
又是被优先级问题折腾了三天
因为换用了一颗第三方前面板芯片,需要把第三方提供的驱动合到我们的系统里。上周整合好驱动,前面板的四个8段显示正常,按键有问题。
前面板排插5根pin分别是:data,clock,3.3V电压,接地,IR。
驱动是这样读取键值的(SomePanel_Read()):先写一个命令字,然后读一个byte,判断读回byte的第6位,如果是1,认为是有按键按下,送出键值;如果是0,认为不是有效键值,返回0。
u_int8 SomePanel_Read( void ) { u_int8 keycode = 0; SomePanel_Start(); SomePanel_WrByte((u_SomePanel_GET_KEY>>7)&0x2E|0x01|0x40); keycode=SomePanel_RdByte(); SomePanel_Stop(); if(keycode&0x40 ==0) keycode = 0; return keycode; }
task的while(1)循环里,调用SomePanel_Read()读取键值,如果是0,稍微sleep一会,再调用SomePanel_Read()读键值;如果不是0,处理处理,填好按键key结构,放到缓存队尾,再继续读。
很简单的流程,出问题了。
前面板排插和JTAG复用,无法单步调试,只能用串口打印调试。在while(1)里读回键值后如果不是0,打印输出该键值。
开电后,没有按键按下,却一直送出键值。
送出的键值第6位并不是1。是一个无效键值。
按下某个按键后,能读出一个有效键值,然后又不停地送出另一个无效键值。每一个按键按下后都会送出一个不一样的无效键值。这些无效键值被放到的缓存中,于是乱套。
咨询第三方工程师,先建议我们调整SomePanel_RdByte()中拉高拉底data pin和clock pin中间的delay。增加和减少延时都没有效果。
再咨询,又建议我们把3.3V电压改为5V。也是没有效果。
量波形也没有帮助,data pin上一直有波形,没错,循环里一直很在读。只不过第6位是0的无效键值应该不会被送出啊。但它们确实送出来了。我们都觉得很奇怪。
被这个问题困扰了两天,无解。
终于,今天,在又一次又一次阅读相关的驱动代码后,找到问题所在,修改SomePanel_Read()函数后,正常。
u_int8 SomePanel_Read( void ) { u_int8 keycode = 0; SomePanel_Start(); SomePanel_WrByte((u_SomePanel_GET_KEY >> 7) & 0x2E | 0x01 | 0x40); keycode = SomePanel_RdByte(); SomePanel_Stop(); if((keycode & 0x40) == 0) keycode = 0; return keycode; }
又是依赖运算符优先级出了错。
不知道为什么正式发布的驱动程序里居然会有这样的问题。
其他方案里用这颗芯片也会出问题,现象可能会是丢键值,按很多下按键都没有反应,不按了突然又噌噌噌连续响应。
写程序时还是不要太相信自己对优先级的记忆,靠括号很靠谱。