发新帖我要提问
123
返回列表
打印

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

[复制链接]
楼主: 雷影少年
手机看帖
扫描二维码
随时随地手机跟帖
41
雷影少年|  楼主 | 2012-8-25 12:06 | 只看该作者 回帖奖励 |倒序浏览
传上咱滴代码

#include<reg51.h>

typedef        unsigned char        u8;
typedef unsigned int        u16;
typedef        unsigned long        u32;
#define        _TR0        10000                        //定义定时器初始值10ms
#define        LINE        P1
sbit R=P2^0;
sbit CLK=P2^1;
sbit STB=P2^2;
u8        flag_10ms;
u16        dat,dat0;

/*--  新宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
                /*--  文字:  武  --*/
u8 code seg[26][32]={};         //数组比较长就不传上来恶心人了

/*缓冲数组(存储1个字模)便于读取数据*/
u16        sbuf[16]={0};

/*sbuf1初始化*/
void sbuf_init()
{
        u8        i;
        for(i=0;i<16;i++)
        {
           sbuf[i]=(sbuf[i]|seg[0][2*i+1]);
           sbuf[i]=(sbuf[i]<<8)|seg[0][2*i];
        }
}

/*更新缓冲区数据*/
void sbuf_update()
{
        u8        i;
        u16        temp0,temp1;
        static        u8        m=0;                //存储左移字数
        static        u8        n=0;                //存储左移次数

        if(m<25)                        //未更新到最后一个字模
        {
                if(n<16)
                {       
                        for(i=0;i<16;i++)
                        {
                                temp0=temp1=0;                                        //中间变量清零
                                temp0=temp0|seg[m][2*i+1];               
                                temp0=(temp0<<8)|seg[m][2*i];         //将前一个字代码赋给temp0
                                temp1=temp1|seg[m+1][2*i+1];
                                temp1=(temp1<<8)|seg[m+1][2*i];         //将后一个字代码赋给temp1
                                sbuf[i]=(temp0<<n)|(temp1>>(16-n));           //合成要显示的代码
                        }
                        n++;                                                                           //移位次数+1;
                }
                else
                {                                                                 
                        n=0;                                                 //达到16次移位次数清0;
                        m++;                                                 //移动字数加1
                        sbuf_update();                                 //重新加载缓冲区字模
                }
        }
        else
        {
                if(n<16)
                {       
                        for(i=0;i<16;i++)
                        {
                                temp0=temp1=0;                                        //中间变量清零
                                temp0=temp0|seg[m][2*i+1];               
                                temp0=(temp0<<8)|seg[m][2*i];         //将前一个字代码赋给temp0
                                temp1=temp1|seg[0][2*i+1];
                                temp1=(temp1<<8)|seg[0][2*i];         //将后一个字代码赋给temp1
                                sbuf[i]=(temp0<<n)|(temp1>>(16-n));           //合成要显示的代码
                        }
                        n++;                                                                           //移位次数+1;
                }
                else
                {                                                                 
                        n=0;                                                 //达到16次移位次数清0;
                         m=0;                                                //最后一个字已移出,移动字数清0
                        sbuf_update();                                 //重新加载缓冲区字模
                }
        }
}

void write(u16 dat)                                   //写入一个字节
{
        u8        i;
        for (i=0;i<16;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;
        sbuf_init();
        while (1)
        {
                u8        i;
                if(flag_10ms<5)                                          //控制移动速度
                {
                        for (i=0;i<16;i++)
                        {
                                dat=sbuf[i];
                                write(~dat);                          //第i行字模写入595
                                LINE=i;                                                  //选择第i行
                                STB=1;
                                STB=0;                                                  //显示
                         }
                }
                else                                                          
                {
                        flag_10ms=0;
                        sbuf_update();                                                //移动一次(1列)
                }
        }
}

void time_10ms() interrupt 1                                   //每10ms中断一次
{
        TH0=-(_TR0/256);
        TL0=-(_TR0%256);
        flag_10ms++;
}
欢迎拍砖哦~
您的砖头是我进步的源泉
不可怕的不是有错,而是明明错了还不知道在哪?
吃饭去了,下午学习下怎么用指针调用二维数组~

使用特权

评论回复
42
sfesdm| | 2012-8-25 12:33 | 只看该作者
从1加到100,1000,你可以逐个加,也可以用for循环加,逐个加你会耗费大量储存空间,for循环加可以省很多事,不过for循环会加大cpu的处理负担,具体的应用中,逐个加,还是用for循环,要根据具体情况而定。

使用特权

评论回复
43
雷影少年|  楼主 | 2012-8-25 21:37 | 只看该作者
搞定

这是用指针的代码
/*sbuf1初始化*/
void sbuf_init()
{
u8 i=0;
u8 *p;
for(p=seg[0];p<seg[0]+32;p++)
{
sbuf[i]=p;
sbuf[i]=(sbuf[i]<<8)|(*(++p));
i++;
}
}

/*更新缓冲区数据*/
void sbuf_update()
{
u8 i,*p,*q;
u16 temp0,temp1;
static u8 m=0; //存储左移字数
static u8 n=0; //存储左移次数
if(m>25) m=0; //最后一个字已移出,左移次数清0
else if(m==25) //最后一个字已移入,开始移入第一个字
{
p=seg[m];
q=seg[0];
}
else
{
p=seg[m]; //确定要显示字的位置
q=seg[m+1];
}

if(n<16)
{
i=0;
for(p;p<&seg[m]+32;p++)
{
temp0=temp1=0; //中间变量清零
temp0=temp0|(*p);
temp0=(temp0<<8)|(*(++p)); //将前一个字代码赋给temp0
temp1=temp1|(*q);
temp1=(temp1<<8)|(*(++q)); //将后一个字代码赋给temp1
sbuf[i]=(temp0<<n)|(temp1>>(16-n)); //合成要显示的代码
// dat0=sbuf[i]; 测试代码
q++;
i++;
}
n++; //移位次数+1 ;
}
else //上一字已完全移出
{
m++; //左移字数加1
n=0; //移位次数清0
sbuf_update(); //重新加载缓冲区字模
}
}
我测试了下

使用指针时第一次调用sbuf_update用时5.358ms;占用date=58,xdate=0,code=1557;

不使用指针时第一次调用sbuf_update用时5.241ms;占用date=52,xdate=0,code=1717;

是不是因为我指针使用的有问题,书上不是说使用指针程序执行速度回提高吗?

使用特权

评论回复
44
雷影少年|  楼主 | 2012-8-25 21:41 | 只看该作者
引用秋婷姐一句话"我觉得程序写的不难,难的是调试。。。"
我现在是深有体会啊~
程序个把小时就学出来了,调时往往要花上数倍甚至数十倍的时间。
怪不得都强调程序书写要规范~

使用特权

评论回复
45
chenbb8| | 2012-8-25 22:47 | 只看该作者
5MS?!!!!5us我都嫌长了
你应该没利用滑动滤波的原理或者是FIFO的更好,主要思想就是头指针和数据长度相结合。
每次只增加头指针,这个头指针虽然名字叫指针其实是一唯数组的下标~~

使用特权

评论回复
46
雷影少年|  楼主 | 2012-8-26 00:02 | 只看该作者
本帖最后由 雷影少年 于 2012-8-26 09:22 编辑

51单片机,11.0592的晶振,5ms就是不到5000个机器周期,程序怎么优化都不可能到5us;以我目前的知识也做不了太多的优化了~
正在百度滑动滤波原理和FIFO,学习下看看~

使用特权

评论回复
47
chenbb8| | 2012-8-26 10:42 | 只看该作者
51也有快有慢的,比如STC比如C8051F~对于改进型的51程序执行时间的计算,不要相信软件仿真,要是纠结于5us的时间话,需要用定时器中的计数器来算,或者看反汇编和数据手册中每个指令的执行时间来计算~~反正效果超级好就是了。
#define SEG_NUM 22      //有多少个就填多少个
#define SEG_MAX  SEG_NUM*16    //22*16,这是一维数组的长度
#define SEG_LENG 16     //每次传送的元素数目

uint16_t Seg_Head = 0;  //一维数组的头指针
uint16_t Seg_Data = 0;  //一维数组的数组指针

uint16_t *pSeg = (uint16_t *) &seg[0][0];

#define WEIYI  ( if( ++Disp_Head >=  SEG_MAX )   {Disp_Head -= SEG_MAX} )

void Disp_On_LED(void)
{
……
    Seg_Data = Seg_Head;
……
        if( pSeg[Seg_Data] & 0x8000 ) R = 1;
        pSeg[Seg_Data] <<= 1;
         if( ++Disp_Data >=  SEG_MAX )   {Disp_Data -= SEG_MAX};
}

main()
{
WEIYI
Disp_On_LED();
……
}

上面的东西就是思路,显示不对的话就需要取字模软件的支持了。
LZ的单片机是8位的,请将上面的16位的指针pSeg改回8位的,每次位移+2。
或者在Disp_On_LED()中使用指针、位域强制类型转换成8位的用也行。

使用特权

评论回复
48
雷影少年|  楼主 | 2012-8-26 10:58 | 只看该作者
试试看
O(∩_∩)O谢谢LS

使用特权

评论回复
49
chenbb8| | 2012-8-26 11:20 | 只看该作者
没有用编译器检查,我上面的代码貌似有BUG~~
比如if( ++Disp_Data >=  SEG_MAX )   {Disp_Data -= SEG_MAX};这句~

使用特权

评论回复
50
雷影少年|  楼主 | 2012-8-26 16:51 | 只看该作者
本帖最后由 雷影少年 于 2012-8-26 16:52 编辑

仔细揣摩了下你的程序,若是按行显示的话感觉许多地方想不通
莫非你是按列显示的?数组里的数是按列存储的,话说我的东西已经焊好了,貌似只能按行显示吧~
若是按列显示的话只能改电路了~
按照当前电路的话,利用ls的思路可以写个上移或者下移程序。
不知是不是我的理解有误~
不过还是要O(∩_∩)O谢谢ls,现在有耐心看新手代码的DX不多了
20分全给你了哦~

使用特权

评论回复
51
chenbb8| | 2012-8-26 19:12 | 只看该作者
:loveliness:不是在做实验的吗~将字模改成列的形式发出去也就是图形扭转了90度而已
想要扭转回来的话可以牺牲Disp_On_LED(void)函数的效率,通过让显示程序变的臃肿来减少位移的时间,下面的程序同样没考虑8位机的优化
void Disp_On_LED(void)
{
    uint16_t Col_Tmp = 0x0001;   //用来和字模的列 相与的变量
……
    for( i = 16; i > 0; i--)             //外循环决定取字模中 列的那一个行
    {
        Seg_Data = Seg_Head;     //指向起始的位置


        for( j = 16; i > 0; i--)          //内循环遍历16个列
        {
            if( seg[Seg_Data] &  Col_Tmp ) R = 1;
            Seg_Data++;
        }

        Col_Tmp <= 1;                //更换另外一行,觉得方向颠倒了的话,Col_Tmp的左右移和Seg_Data的增减上要做调整
    }

}
由于在你的程序里显示部分是经常执行的,也就是说占用CPU时间的大头,因此以上的显示程序只能看下了~
不过倒是可以在不修改字模的情况下将做出显示的扭转效果。
另外使用指针并不能直接带来效率的提升,因为使用指针指向变量来操作变量的做法叫做间接访问,间接访问相对直接访问会在语法层次带来效率的降低。
但却可以使用更加先进灵活的技巧,从而带来几倍甚至几百倍的优化效果。

使用特权

评论回复
52
雷影少年|  楼主 | 2012-8-26 19:39 | 只看该作者
指针访问是间接访问什么的我是知道的,我接触过汇编,间接访问在51里是占3个周期的,指针是间接寻址,使用起来比较方便~
我记得貌似在哪本书说指针可以提高程序效率的,但是却不免白为什么?
寻址发现貌似指针不能提高程序速度,但是能使程序更加简洁,代码执行效率更高

使用特权

评论回复
53
chenbb8| | 2012-8-26 20:14 | 只看该作者
有时间可以看下《C和指针》,看评论这是一本C入门的书,但我觉得还是有一点点C的基础再看会比较合适,因为有些地方讲的不够详细。
这本书讨论了很多程序优化的方法

使用特权

评论回复
54
雷影少年|  楼主 | 2012-8-26 21:54 | 只看该作者
嗯~

使用特权

评论回复
55
sedatefire| | 2012-8-27 11:03 | 只看该作者
路过,小伙子不错,兢兢业业,孜孜不倦...
加油...

使用特权

评论回复
56
雷影少年|  楼主 | 2012-8-27 11:39 | 只看该作者
还要斑竹多多批评啊

使用特权

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

本版积分规则