[讨论] 这算不算是STM32的BUG

lingking   2019-1-12 16:47 楼主
小弟编程水平和C语言都比较菜,如果犯了什么低级错误还望高手们直接指出。事情是这样的,小弟最近在学编程,这两天在STM32开发板上对XPT2046这个型号的电阻屏触摸检测芯片写驱动代码。读取触摸芯片的电压值的函数已经实现了,现在开始构思电阻屏的校准函数。初步的想法是在屏幕上面依次画4个点,点击一个点之后采集坐标的电压值然后清除这个点再画下一个,采集4个点的电压值之后开始计算电阻屏的参数。上面画4个点的过程我用了一个for循环和switch语句来组合实现。可是在这段代码里面就出现了匪夷所思的现象:点击完第一个点之后直接跳到了第三个点,然后是第四个点,第二个点直接被忽略了,然而从代码上看这四段代码除了参数以外都没有任何区别。 已经确定了是最后一个case导致出了问题,我新增了一个k变量,将i换成k,出来的结果就正常了,下面是能正常使用的代码和对应的结果:。以下是会出错的源码:
  1. u16 Xpos[3],Ypos[3];
  2. void TP_Calibration(void)
  3. {
  4. u8 flag,j;
  5. u16 i,k = 0;
  6. printf("void TP_Calibration(void) V2.1 \r\n");
  7. for(j = 0;j < 5;j++)
  8. {
  9. switch(j)
  10. {
  11. case 0: /* 画第一个点 */
  12. {
  13. i = 500;
  14. flag = 0;
  15. TP_DrawPoint(20,20,RED);
  16. while(i--)
  17. {
  18. delay_ms(10);
  19. flag = TP_Scan_Voltage(Xpos,Ypos);
  20. if(flag == 1)
  21. {
  22. i = 0;
  23. printf("读取到第1个点的电压\r\n");
  24. }
  25. }
  26. TP_DrawPoint(20,20,WHITE);
  27. }
  28. break;
  29. case 1: /* 画第二个点 */
  30. {
  31. i = 500;
  32. flag = 0;
  33. TP_DrawPoint(20,lcddev.height - 20,RED);
  34. while(i--)
  35. {
  36. delay_ms(10);
  37. flag = TP_Scan_Voltage(Xpos + 1,Ypos + 1);
  38. if(flag == 1)
  39. {
  40. i = 0;
  41. printf("读取到第2个点的电压\r\n");
  42. }
  43. }
  44. TP_DrawPoint(20,lcddev.height - 20,WHITE);
  45. }
  46. break;
  47. case 2:
  48. {
  49. i = 500;
  50. flag = 0;
  51. TP_DrawPoint(lcddev.width - 20,lcddev.height - 20,RED);
  52. while(i--)
  53. {
  54. delay_ms(10);
  55. flag = TP_Scan_Voltage(Xpos + 2,Ypos + 2);
  56. if(flag == 1)
  57. {
  58. i = 0;
  59. printf("读取到第3个点的电压\r\n");
  60. }
  61. }
  62. TP_DrawPoint(lcddev.width - 20,lcddev.height - 20,WHITE);
  63. }
  64. break;
  65. case 3:
  66. {
  67. i = 500;
  68. flag = 0;
  69. TP_DrawPoint(lcddev.width - 20,20,RED);
  70. while(i--)
  71. {
  72. delay_ms(10);
  73. flag = TP_Scan_Voltage(Xpos + 3,Ypos + 3);
  74. if(flag == 1)
  75. {
  76. i = 0;
  77. printf("读取到第4个点的电压\r\n");
  78. }
  79. }
  80. TP_DrawPoint(lcddev.width - 20,20,WHITE);
  81. }
  82. break;
  83. default:
  84. break;
  85. }
  86. }
  87. }
有错的实验现象: 新建位图图像.png 已经确定了是最后一个case导致出了问题,我新增了一个k变量,将i换成k,出来的结果就正常了,下面是能正常使用的代码和对应的结果:
  1. u16 Xpos[3],Ypos[3];
  2. void TP_Calibration(void)
  3. {
  4. u8 flag,j;
  5. u16 i,k = 0;
  6. printf("void TP_Calibration(void) V2.1 \r\n");
  7. for(j = 0;j < 5;j++)
  8. {
  9. switch(j)
  10. {
  11. case 0: /* 画第一个点 */
  12. {
  13. i = 500;
  14. flag = 0;
  15. TP_DrawPoint(20,20,RED);
  16. while(i--)
  17. {
  18. delay_ms(10);
  19. flag = TP_Scan_Voltage(Xpos,Ypos);
  20. if(flag == 1)
  21. {
  22. i = 0;
  23. printf("读取到第1个点的电压\r\n");
  24. }
  25. }
  26. TP_DrawPoint(20,20,WHITE);
  27. }
  28. break;
  29. case 1: /* 画第二个点 */
  30. {
  31. i = 500;
  32. flag = 0;
  33. TP_DrawPoint(20,lcddev.height - 20,RED);
  34. while(i--)
  35. {
  36. delay_ms(10);
  37. flag = TP_Scan_Voltage(Xpos + 1,Ypos + 1);
  38. if(flag == 1)
  39. {
  40. i = 0;
  41. printf("读取到第2个点的电压\r\n");
  42. }
  43. }
  44. TP_DrawPoint(20,lcddev.height - 20,WHITE);
  45. }
  46. break;
  47. case 2:
  48. {
  49. i = 500;
  50. flag = 0;
  51. TP_DrawPoint(lcddev.width - 20,lcddev.height - 20,RED);
  52. while(i--)
  53. {
  54. delay_ms(10);
  55. flag = TP_Scan_Voltage(Xpos + 2,Ypos + 2);
  56. if(flag == 1)
  57. {
  58. i = 0;
  59. printf("读取到第3个点的电压\r\n");
  60. }
  61. }
  62. TP_DrawPoint(lcddev.width - 20,lcddev.height - 20,WHITE);
  63. }
  64. break;
  65. [color=Red] case 3:
  66. {
  67. [b] k = 500;[/b]
  68. flag = 0;
  69. TP_DrawPoint(lcddev.width - 20,20,RED);
  70. while(k--)
  71. {
  72. delay_ms(10);
  73. flag = TP_Scan_Voltage(Xpos + 3,Ypos + 3);
  74. if(flag == 1)
  75. {
  76. k = 0;
  77. printf("读取到第4个点的电压\r\n");
  78. }
  79. }
  80. TP_DrawPoint(lcddev.width - 20,20,WHITE);
  81. }
  82. break;[/color]
  83. default:
  84. break;
  85. }
  86. }
  87. }
新建位图图像.png 是不是我的第一段代码有逻辑问题呢?还是这原来就是STM32的BUG ?实在想不通,所以发上来和大家请教一下了 另外附件中也上传了整个工程的代码,供参考 本帖最后由 lingking 于 2019-1-12 16:55 编辑
拿PADS和Allegro软件来吹牛的都是些土鳖

回复评论 (15)

是不是我的第一段代码有逻辑问题呢?还是这原来就是STM32的BUG ?实在想不通,所以发上来和大家请教一下了
另外附件中也上传了整个工程的代码,供参考
拿PADS和Allegro软件来吹牛的都是些土鳖
点赞  2019-1-12 16:49
貌似和编译器优化有关,将编译器优化改成default就不出错了
拿PADS和Allegro软件来吹牛的都是些土鳖
点赞  2019-1-12 17:35
厄,你写这个 for 循环的用意何在?
点赞  2019-1-12 19:29
凡与编译相关的,均与芯片bug无关。
上传了一些书籍资料,也许有你想要的:https://download.eeworld.com.cn/user/chunyang
点赞  2019-1-12 19:59
不用问了,是编程的事不是BUG,因为四点效验我搞过。OVER
http://shop34182318.taobao.com/ https://shop436095304.taobao.com/?spm=a230r.7195193.1997079397.37.69fe60dfT705yr
点赞  2019-1-12 20:35
引用: ddllxxrr 发表于 2019-1-12 20:35
不用问了,是编程的事不是BUG,因为四点效验我搞过。OVER

我找到问题就是编译器的优化造成的,编译器默认的-O1优化会出问题,任选一个其他级别的优化就可以了
拿PADS和Allegro软件来吹牛的都是些土鳖
点赞  2019-1-12 21:19
引用: cruelfox 发表于 2019-1-12 19:29
厄,你写这个 for 循环的用意何在?

程序的东西不是一想出来就是最简洁的,但是这个完完全全是我自己想出来的,功能完成了,后面怎么改都行
拿PADS和Allegro软件来吹牛的都是些土鳖
点赞  2019-1-12 21:24
10.        for(j = 0;j < 5;j++)

11.        {

12.

13.                switch(j)

你这个逻辑语句很奇葩,j的值已经确定了还要去switch
点赞  2019-1-14 10:27
你这个程序不能假定用户校准时按下电阻屏的时间,还是要以电阻屏的采样值变化作为切换校准点的依据,所以for 或者(一定是或者,用一个就行) switch的条件要重新考虑
点赞  2019-1-14 10:31
应该是编译器优化问题  i改成volatile试试?
点赞  2019-1-14 10:38
引用: 常见泽1 发表于 2019-1-14 10:38
应该是编译器优化问题  i改成volatile试试?

验证过了,就是keil默认的-O1优化导致出现问题,改成其他的优化等级就不会错了
拿PADS和Allegro软件来吹牛的都是些土鳖
点赞  2019-1-14 20:36
引用: huo_hu 发表于 2019-1-14 10:27
10.        for(j = 0;j < 5;j++)

11.        {

12.

13.                switch(j)

你这个逻辑 ...

j是用来选画点的个数的,这不是重点。我克服了上面所说的优化产生的奇怪问题之后还是按照上面的逻辑来做,没有任何问题
拿PADS和Allegro软件来吹牛的都是些土鳖
点赞  2019-1-21 11:31
引用: lingking 发表于 2019-1-21 11:31
j是用来选画点的个数的,这不是重点。我克服了上面所说的优化产生的奇怪问题之后还是按照上面的逻辑来做 ...

触屏抬起切换到下一个点
点赞  2019-1-21 11:38
引用: huo_hu 发表于 2019-1-21 11:38
触屏抬起切换到下一个点

没错啊,我的程序就是画点校准的时候,笔尖抬起就画下一个点然后继续采集电压值
拿PADS和Allegro软件来吹牛的都是些土鳖
点赞  2019-1-21 20:45
那不知道了,你调试一下进去看看
点赞  2019-1-23 11:43
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复