打印

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

[复制链接]
6254|55
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
雷影少年|  楼主 | 2012-8-23 20:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
求C高手指点下
下面的For循环和不用for有什么区别

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


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


seg[4][2*i]=seg[4][2*i]<<1;
Bit=CY;
seg[4][2*i]=seg[4][2*i]|BIT;
seg[4][2*i+1]=seg[4][2*i+1]<<1;
BIT=CY;
seg[4][2*i+1]=seg[4][2*i+1]|Bit;

seg[3][2*i]=seg[3][2*i]<<1;
Bit=CY;
seg[3][2*i]=seg[3][2*i]|BIT;
seg[3][2*i+1]=seg[3][2*i+1]<<1;
BIT=CY;
seg[3][2*i+1]=seg[3][2*i+1]|Bit;

seg[2][2*i]=seg[2][2*i]<<1;
Bit=CY;
seg[2][2*i]=seg[2][2*i]|BIT;
seg[2][2*i+1]=seg[2][2*i+1]<<1;
BIT=CY;
seg[2][2*i+1]=seg[2][2*i+1]|Bit;

seg[1][2*i]=seg[1][2*i]<<1;
Bit=CY;
seg[1][2*i]=seg[1][2*i]|BIT;
seg[1][2*i+1]=seg[1][2*i+1]<<1;
BIT=CY;
seg[1][2*i+1]=seg[1][2*i+1]|Bit;

seg[0][2*i]=seg[0][2*i]<<1;
Bit=CY;
seg[0][2*i]=seg[0][2*i]|BIT;
seg[0][2*i+1]=seg[0][2*i+1]<<1;
BIT=CY;
seg[0][2*i+1]=seg[0][2*i+1]|Bit;

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

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 | 只看该作者
不是,是两个位。

使用特权

评论回复
5
雷影少年|  楼主 | 2012-8-23 21:22 | 只看该作者
经过单步调试N久,终于早到了问题,
for循环无法跳出,我试着把循环改为for(j=6;j>0;j--)问题居然解决了,好奇怪哦~

使用特权

评论回复
6
chenhao8060| | 2012-8-23 21:28 | 只看该作者
5# 雷影少年
你的变量j是不是定义成unsigned了,无符号的话你的j>=0恒成立

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
tuzihog + 1 不错 这是一个要注意的地方
7
雷影少年|  楼主 | 2012-8-23 21:29 | 只看该作者
本帖最后由 雷影少年 于 2012-8-24 10:09 编辑

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

#include<reg51.h>

typedef        unsigned char        u8;
typedef unsigned int        u16;

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

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

void zuoyi()
{
        u8        i,j;
        bit        Bit,BIT; //定义两个位,保存移位时CY的数据
        for (i=0;i<16;i++)
        {
                Bit=BIT=0;
                for(j=22;j>0;j--)
                {
                        seg[j-1][2*i]=seg[j-1][2*i]<<1;                   //左移将最高位移入CY
                        Bit=CY;                                                           //保存CY,
                        seg[j-1][2*i]=seg[j-1][2*i]|BIT;           //将上次移出的最高位移放到最低位
                        seg[j-1][2*i+1]=seg[j-1][2*i+1]<<1;           //左移将最高位移入CY
                        BIT=CY;                                                           //保存CY
                        seg[j-1][2*i+1]=seg[j-1][2*i+1]|Bit;   //将上次移出的最高位移放到最低位
                 }
                seg[21][2*i]=seg[21][2*i]|BIT;                    //在循环结束后将最后一次移位时的CY做第一次移位的最低位
                                                                                                //完成一行字模的一次移位
        }
}
void write(u8 dat)                                   //写入一个字节
{
        u8        i;
        for (i=0;i<8;i++)
        {
                dat=dat>>1;
                R=CY;
                CLK=0;
                CLK=1;
        }
}


void main()
{
        EA =1;                                                //开中断
        ET0 =1;
        TMOD =0x01;
        TH0 =-(_TR0/256);
        TL0 =-(_TR0%256);
        TR0 =1;
        while (1)
        {
                u8        i;
                if(flag_10ms<100)                                          //控制移动速度
                {
                        for (i=0;i<16;i++)
                        {
                                write(~seg[0][2*i]);                          //第i行字模写入595
                                write(~seg[0][2*i+1]);
                                LINE=i;                                                  //选择第i行
                                STB=1;
                                STB=0;                                                  //显示
                         }
                }
                else                                                         
                {
                        flag_10ms=0;
                        zuoyi();                                                 //移动一次(1列)
                }
        }
}

void time_10ms() interrupt 1                                   //每10ms中断一次
{
        TH0=-(_TR0/256);
        TL0=-(_TR0%256);
        flag_10ms++;
}

使用特权

评论回复
8
雷影少年|  楼主 | 2012-8-23 21:32 | 只看该作者
问题出在哪儿?是芯片的容量不够,还是我程序有问题?是不是还是for循环出错了?

使用特权

评论回复
9
雷影少年|  楼主 | 2012-8-23 21:34 | 只看该作者
闪烁的原因我想到了,是因为处理zuoyi程序用的时间太长了,起不了视觉暂留作用,有什么好的解决办法吗?

使用特权

评论回复
10
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
11
雷影少年|  楼主 | 2012-8-23 22:12 | 只看该作者
10# chenbb8
“for( i = xx; i >= 0; i-- ),使用1代入分析时,有两种情况,首先i是无符号数,循环不会终止”原来这就是刚ofr循环无法跳出的原因啊,是不是意味着unsigned char类型的书减到0之后继续减的话就变成255了?
看了以后循环用0做条件的时候要注意了

使用特权

评论回复
12
雷影少年|  楼主 | 2012-8-23 22:21 | 只看该作者
我刚测试了一下,好像无论是unsigned char还是char类型的数位0时继续减一的话都是变成0xff的,即unsigned char为0是减1后是变成255的,char类型的减1后是-1

使用特权

评论回复
13
tuzihog| | 2012-8-24 00:19 | 只看该作者
12# 雷影少年
楼主要好好的研究一下数值在计算机内部的表示方式。这是基础中的基础!
推荐阅读《深入理解计算机系统》,有中文版的!

使用特权

评论回复
14
谈的元| | 2012-8-24 01:09 | 只看该作者
说一点,如果你J是无符号的,大于等于0就永远成立,

就是J已经为0,执行J--,也会判断为大于等于0的

使用特权

评论回复
15
谈的元| | 2012-8-24 01:11 | 只看该作者
前面已经有人说了,对无符号数,只有少数编译器会通过高位是否为1来判断是否为负数

使用特权

评论回复
16
optical85| | 2012-8-24 09:27 | 只看该作者
在循环外先做
temp=2*i;
temp1 = 2*i+1;
然后在循环里的相应元素表达都用temp和temp1代替。这样可以省很多指令时间。另外注意开启编译器的优化。一般是右键点击工程文件,选择build options里面,找optimization level。

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
雷影少年 + 1 有理
17
雷影少年|  楼主 | 2012-8-24 09:36 | 只看该作者
13# tuzihog
我现在只是知道无符号数是以原码形式表示的,有符号数是以补码形式表示,正数最高位为0,补码和原码相同,负数最高位位1,其余对原码按位取反再在最低位加1

使用特权

评论回复
18
雷影少年|  楼主 | 2012-8-24 09:36 | 只看该作者
15# 谈的元
这个刚刚意识到

使用特权

评论回复
19
雷影少年|  楼主 | 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个字,当时不需要注意这种情况,等到显示的字数比较多的时候就把这种情况给忘了,
关于编译器优化问题以前还没接触过,学习了~

使用特权

评论回复
20
雷影少年|  楼主 | 2012-8-24 10:04 | 只看该作者
本帖最后由 雷影少年 于 2012-8-24 10:26 编辑

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

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

11

主题

714

帖子

0

粉丝