求助,会C的帮忙看下,for循环的使用哪错了?

[复制链接]
 楼主| 雷影少年 发表于 2012-8-23 20:13 | 显示全部楼层 |阅读模式
求C高手指点下
下面的For循环和不用for有什么区别

  1. for(j=5;j>=0;j--)
  2. {
  3. seg[j][2*i]=seg[j][2*i]<<1; //左移将最高位移入CY
  4. Bit=CY; //保存CY,
  5. seg[j][2*i]=seg[j][2*i]|BIT; //将上次移出的最高位移放到最低位
  6. seg[j][2*i+1]=seg[j][2*i+1]<<1; //左移将最高位移入CY
  7. BIT=CY; //保存CY
  8. seg[j][2*i+1]=seg[j][2*i+1]|Bit; //将上次移出的最高位移放到最低位
  9. }
  10. seg[5][2*i]=seg[5][2*i]|BIT; //在循环结束后将最后一次移位时的CY做第一次移位的最低位
  11. //完成一行字模的一次移位*/


上面的和下面哪里有区别?为什么用下面的程序点阵能够正常左移,用for循环之后就不亮了
  1. seg[5][2*i]=seg[5][2*i]<<1;
  2. Bit=CY;
  3. seg[5][2*i]=seg[5][2*i]|BIT;
  4. seg[5][2*i+1]=seg[5][2*i+1]<<1;
  5. BIT=CY;
  6. seg[5][2*i+1]=seg[5][2*i+1]|Bit;


  7. seg[4][2*i]=seg[4][2*i]<<1;
  8. Bit=CY;
  9. seg[4][2*i]=seg[4][2*i]|BIT;
  10. seg[4][2*i+1]=seg[4][2*i+1]<<1;
  11. BIT=CY;
  12. seg[4][2*i+1]=seg[4][2*i+1]|Bit;

  13. seg[3][2*i]=seg[3][2*i]<<1;
  14. Bit=CY;
  15. seg[3][2*i]=seg[3][2*i]|BIT;
  16. seg[3][2*i+1]=seg[3][2*i+1]<<1;
  17. BIT=CY;
  18. seg[3][2*i+1]=seg[3][2*i+1]|Bit;

  19. seg[2][2*i]=seg[2][2*i]<<1;
  20. Bit=CY;
  21. seg[2][2*i]=seg[2][2*i]|BIT;
  22. seg[2][2*i+1]=seg[2][2*i+1]<<1;
  23. BIT=CY;
  24. seg[2][2*i+1]=seg[2][2*i+1]|Bit;

  25. seg[1][2*i]=seg[1][2*i]<<1;
  26. Bit=CY;
  27. seg[1][2*i]=seg[1][2*i]|BIT;
  28. seg[1][2*i+1]=seg[1][2*i+1]<<1;
  29. BIT=CY;
  30. seg[1][2*i+1]=seg[1][2*i+1]|Bit;

  31. seg[0][2*i]=seg[0][2*i]<<1;
  32. Bit=CY;
  33. seg[0][2*i]=seg[0][2*i]|BIT;
  34. seg[0][2*i+1]=seg[0][2*i+1]<<1;
  35. BIT=CY;
  36. seg[0][2*i+1]=seg[0][2*i+1]|Bit;

  37. seg[5][2*i]=seg[5][2*i]|BIT;

  38. Bit=BIT=0;

看看这两程序有什么区别 ?
学了这么就C连个for循环都搞不定:'(
 楼主| 雷影少年 发表于 2012-8-23 20:21 | 显示全部楼层
在线等答案,单身的哥们帮帮忙啊
shell.albert 发表于 2012-8-23 20:58 | 显示全部楼层
LZ你的变量BIT和Bit是一个东东吗?
如果不是,问题就出在这里!
 楼主| 雷影少年 发表于 2012-8-23 21:20 | 显示全部楼层
不是,是两个位。
 楼主| 雷影少年 发表于 2012-8-23 21:22 | 显示全部楼层
经过单步调试N久,终于早到了问题,
for循环无法跳出,我试着把循环改为for(j=6;j>0;j--)问题居然解决了,好奇怪哦~
chenhao8060 发表于 2012-8-23 21:28 | 显示全部楼层
5# 雷影少年
你的变量j是不是定义成unsigned了,无符号的话你的j>=0恒成立

评分

参与人数 1威望 +1 收起 理由
tuzihog + 1 不错 这是一个要注意的地方

查看全部评分

 楼主| 雷影少年 发表于 2012-8-23 21:29 | 显示全部楼层
本帖最后由 雷影少年 于 2012-8-24 10:09 编辑

不过旧问题刚解决就出新问题了,数组里的字是6个的时候完全没问题,但是当我把字改为22个并将数组设为xdata时问题出现了,左移前8个字的时候点阵每次移动都有闪烁现象,8个字移完后点阵全亮。
(注:经测试,当数组里的字模书达到22个时,全部左移一位需80ms左右)
程序的作用是在16x16的点阵上左移循环显示汉字“武汉电力职业技术学院信息工程系***"
为方便dx了解程序,下面是源码

  1. #include<reg51.h>

  2. typedef        unsigned char        u8;
  3. typedef unsigned int        u16;

  4. #define        _TR0        10000                        //定义定时器初始值10ms
  5. #define        LINE        P1
  6. sbit R=P2^0;
  7. sbit CLK=P2^1;
  8. sbit STB=P2^2;
  9. u8        flag_10ms;

  10. /*--  新宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
  11.                 /*--  文字:  武  --*/
  12. u8 xdata seg[22][32]={{0x40,0x00,0x50,0x00,0x48,0x3F,0x48,0x00,0x40,0x00,0xFE,0xFF,0x40,0x00,0x40,0x04,
  13.                 0x40,0x04,0x40,0x27,0x20,0x24,0x22,0x24,0x12,0x24,0x8A,0x27,0x06,0xF8,0x02,0x40},
  14.                 {....}};

  15. void zuoyi()
  16. {
  17.         u8        i,j;
  18.         bit        Bit,BIT; //定义两个位,保存移位时CY的数据
  19.         for (i=0;i<16;i++)
  20.         {
  21.                 Bit=BIT=0;
  22.                 for(j=22;j>0;j--)
  23.                 {
  24.                         seg[j-1][2*i]=seg[j-1][2*i]<<1;                   //左移将最高位移入CY
  25.                         Bit=CY;                                                           //保存CY,
  26.                         seg[j-1][2*i]=seg[j-1][2*i]|BIT;           //将上次移出的最高位移放到最低位
  27.                         seg[j-1][2*i+1]=seg[j-1][2*i+1]<<1;           //左移将最高位移入CY
  28.                         BIT=CY;                                                           //保存CY
  29.                         seg[j-1][2*i+1]=seg[j-1][2*i+1]|Bit;   //将上次移出的最高位移放到最低位
  30.                  }
  31.                 seg[21][2*i]=seg[21][2*i]|BIT;                    //在循环结束后将最后一次移位时的CY做第一次移位的最低位
  32.                                                                                                 //完成一行字模的一次移位
  33.         }
  34. }
  35. void write(u8 dat)                                   //写入一个字节
  36. {
  37.         u8        i;
  38.         for (i=0;i<8;i++)
  39.         {
  40.                 dat=dat>>1;
  41.                 R=CY;
  42.                 CLK=0;
  43.                 CLK=1;
  44.         }
  45. }


  46. void main()
  47. {
  48.         EA =1;                                                //开中断
  49.         ET0 =1;
  50.         TMOD =0x01;
  51.         TH0 =-(_TR0/256);
  52.         TL0 =-(_TR0%256);
  53.         TR0 =1;
  54.         while (1)
  55.         {
  56.                 u8        i;
  57.                 if(flag_10ms<100)                                          //控制移动速度
  58.                 {
  59.                         for (i=0;i<16;i++)
  60.                         {
  61.                                 write(~seg[0][2*i]);                          //第i行字模写入595
  62.                                 write(~seg[0][2*i+1]);
  63.                                 LINE=i;                                                  //选择第i行
  64.                                 STB=1;
  65.                                 STB=0;                                                  //显示
  66.                          }
  67.                 }
  68.                 else                                                         
  69.                 {
  70.                         flag_10ms=0;
  71.                         zuoyi();                                                 //移动一次(1列)
  72.                 }
  73.         }
  74. }

  75. void time_10ms() interrupt 1                                   //每10ms中断一次
  76. {
  77.         TH0=-(_TR0/256);
  78.         TL0=-(_TR0%256);
  79.         flag_10ms++;
  80. }
 楼主| 雷影少年 发表于 2012-8-23 21:32 | 显示全部楼层
问题出在哪儿?是芯片的容量不够,还是我程序有问题?是不是还是for循环出错了?
 楼主| 雷影少年 发表于 2012-8-23 21:34 | 显示全部楼层
闪烁的原因我想到了,是因为处理zuoyi程序用的时间太长了,起不了视觉暂留作用,有什么好的解决办法吗?
chenbb8 发表于 2012-8-23 22:05 | 显示全部楼层
使用for之类的循环的时候要注意用特殊的数字代进去分析
比如for( i = xx; i > 0; i-- ),就用1来如替XX来分析,循环1次,得出这个循环只进行XX次的结论。
如果是for( i = xx; i >= 0; i-- ),使用1代入分析时,有两种情况,首先i是无符号数,循环不会终止。
其次i是有符号数,循环进行两次,因此循环次数是xx+1
while和do…while循环的分析也类似。

解决zuoyi程序速度慢的办法是优化程序,降低程序运行时间。
我先去洗个澡,回来没人回答的话就帮你看下~

评分

参与人数 1威望 +1 收起 理由
雷影少年 + 1

查看全部评分

 楼主| 雷影少年 发表于 2012-8-23 22:12 | 显示全部楼层
10# chenbb8
“for( i = xx; i >= 0; i-- ),使用1代入分析时,有两种情况,首先i是无符号数,循环不会终止”原来这就是刚ofr循环无法跳出的原因啊,是不是意味着unsigned char类型的书减到0之后继续减的话就变成255了?
看了以后循环用0做条件的时候要注意了
 楼主| 雷影少年 发表于 2012-8-23 22:21 | 显示全部楼层
我刚测试了一下,好像无论是unsigned char还是char类型的数位0时继续减一的话都是变成0xff的,即unsigned char为0是减1后是变成255的,char类型的减1后是-1
tuzihog 发表于 2012-8-24 00:19 | 显示全部楼层
12# 雷影少年
楼主要好好的研究一下数值在计算机内部的表示方式。这是基础中的基础!
推荐阅读《深入理解计算机系统》,有中文版的!
谈的元 发表于 2012-8-24 01:09 | 显示全部楼层
说一点,如果你J是无符号的,大于等于0就永远成立,

就是J已经为0,执行J--,也会判断为大于等于0的
谈的元 发表于 2012-8-24 01:11 | 显示全部楼层
前面已经有人说了,对无符号数,只有少数编译器会通过高位是否为1来判断是否为负数
optical85 发表于 2012-8-24 09:27 | 显示全部楼层
在循环外先做
temp=2*i;
temp1 = 2*i+1;
然后在循环里的相应元素表达都用temp和temp1代替。这样可以省很多指令时间。另外注意开启编译器的优化。一般是右键点击工程文件,选择build options里面,找optimization level。

评分

参与人数 1威望 +1 收起 理由
雷影少年 + 1 有理

查看全部评分

 楼主| 雷影少年 发表于 2012-8-24 09:36 | 显示全部楼层
13# tuzihog
我现在只是知道无符号数是以原码形式表示的,有符号数是以补码形式表示,正数最高位为0,补码和原码相同,负数最高位位1,其余对原码按位取反再在最低位加1
 楼主| 雷影少年 发表于 2012-8-24 09:36 | 显示全部楼层
15# 谈的元
这个刚刚意识到
 楼主| 雷影少年 发表于 2012-8-24 09:40 | 显示全部楼层
在循环外先做
temp=2*i;
temp1 = 2*i+1;
然后在循环里的相应元素表达都用temp和temp1代替。这样可以省很多指令时间。另外注意开启编译器的优化。一般是右键点击工程文件,选择build options里面,找optimization lev ...
optical85 发表于 2012-8-24 09:27

循环里计算表达式太浪费时间了,因为我程序开始只是显示3个字,当时不需要注意这种情况,等到显示的字数比较多的时候就把这种情况给忘了,
关于编译器优化问题以前还没接触过,学习了~
 楼主| 雷影少年 发表于 2012-8-24 10:04 | 显示全部楼层
本帖最后由 雷影少年 于 2012-8-24 10:26 编辑

调试了半天,好像最多只能显示8个字,后面的就全亮无法显示了,不知道是为什么?莫非这样一次让数组里的数全部移位不行?难道要建立个数据缓冲区,把也要显示的数转存的缓冲区里,并在缓冲区中左移?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:高明的设计不在于是否用了最新的技术,在于是否能用最小的成本做出可靠的东西来。

11

主题

714

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部