基于单片机的大屏幕显示程序编译无错误,为什们仿真不了

2019-07-15 19:41发布

本帖最后由 菜鸟与大神 于 2014-5-18 20:07 编辑

求大神们帮我看看这程序能工作吗
源程序
/*16*16点阵屏的显示*/
#include <reg51.h>
#include <intrins.h>        

#define DATAOUT P2        //指定P2口作为输出
sbit DATA=DATAOUT^0;        //列数据输出位        
sbit SCLH=DATAOUT^1;        //列扫描时钟位
sbit SCLT=DATAOUT^2;        //列数据锁存位
sbit AB=DATAOUT^4;                //行数据输出位
sbit SCK=DATAOUT^5;        //行扫描时钟位

unsigned char Temp;    //定义变量
unsigned char lhj[32];//32字节RAM作为16*16点阵屏显示缓存
void display();      //做为点阵扫描函数,将显示缓存的数据输出到点阵屏
void displayS(unsigned int timer);//指定时间扫描显示
void displaymove(unsigned char *lp,unsigned char c,unsigned char timer);
void displaymovetb(unsigned char din,unsigned char *lp,unsigned char timer);
void delay(unsigned int a);//延时子函数
void right_display();//右移子程序
void up_display();//上移子程序        

void main(void)  //主入口函数
{
        unsigned char i=0,j=0;
        SCON = 0x50;     /* SCON: 模式 1, 8-bit UART, 使能接收 */
        TMOD |= 0x20;     /* TMOD: timer 1, mode 2, 8-bit reload */
        TH1 = 0xFD;      /* TH1: reload value for 9600 baud @ 11.0592MHz */
        TR1 = 1;         /* TR1: timer 1 run */
        EA = 1;          /*打开总中断*/  
        ES = 1;          /*打开串口中断*/
        for(i=0;i<32;i++)
                lhj=GUANG;//将"广"字数据复制到显示缓存
        while(1)
        {
                displayS(1);                    //显示"广"字约1秒
                displaymove(DONG,5,7);       //将从"东"开始的5个汉字从右向左移动                        
                displayS(1);                    //等持约1秒
displaymovetb(1,0,10); //将点阵上显示的内容向下以10的速度移出,
displayS(1);                    //等待1秒
                displaymovetb(0,GUANG,10);            //将"广"字以10的速度向上移动
                displaymovetb(0,DONG,10);        //将"东"字以10的速度向上移动
                displaymovetb(0,JI,10);        //将"技"字以10的速度向上移动
                displaymovetb(0,SU,10);        //将"术"字以10的速度向上移动
                displaymovetb(0,SHI,10);            //将"师"字以10的速度向上移动
                displaymovetb(0,FAN,10);        //将"范"字以10的速度向上移动
                displaymovetb(0,0,10);            //以10的速度向上清空
                displayS(1);                    //等待1秒
                displaymovetb(1,GUANG,10);          //将"广"以10的速度向下移动
                right_display();//右移子程序
                up_display();//上移子程序
        }
}
void display()//显示
{        
        unsigned char i,ia,j,tmp;                //定义变量
        DATAOUT=0XFF;                                        //置位高电平做准备
        AB=0;                                                        //将行数据位清0,准备移位
        for(i=0;i<16;i++)
        {        //循环输出16行数据
                SCK=0;                                //为行移位做准备
                SCLT=0;                                //为列锁存做准备
                for(ia=2;ia>0;ia--)
                {        //每行16个点,循环位移两个字节
                                //循环两次
                        tmp=~lhj[i*2+ia];        //读取点阵数据做输出,                                                                                
           for(j=0;j<8;j++)
                        {        //循环两次,每次移一个字节,
                                SCLH=0;                        //为列移位做准备
                                DATA=tmp&0x01;           //将数据低位做输出,
                                tmp>>=1;                  //将数据缓冲右移一位,为下次输出做准备
                                SCLH=1;                        //将DATA上的数据移入寄存器
                        }                                        //移入单字节结束
                }                                        //移入两个字节结束
                SCK=1;                //SCK拉高,行数据移位,相应行拉低
                SCLT=1;                //SCLT拉高
                AB=1;                //行数据位只在第一行时为0,其它时候都为1,
                }
        j=64;
        while(j--);                //每一行的显示,保持了两字节的移位时间,        
        SCK=0;                        //
        SCK=1;                        //将最后一行数据移出
}
void displayS(unsigned int timer)//指定时间扫描显示
{
        unsigned char i;        
        while(timer--)
        { //当timer=1时,大约1秒时间
                i=130;               
                while(i--);
                        display();
        }
}
void displaymove(unsigned char *lp,unsigned char c,unsigned char timer)
//显示汉字内容的移动效果,LP指向要显示第一个字的首地址,C表示显示字的个数,
{
        unsigned char i=0,j=0,ia=0;
        unsigned int tmp=0,timerc=0;
        unsigned char tmp2[16];
        c*=2;                //因一个汉字32字节组成,要分开半个汉字16字节处理,因此这里乘以2
        for(i=0;i<16;i++)
        tmp2[1]=0;        //将缓冲区清0,
        while(c)
        {                //循环处理
                if(lp!=0)
                {        //当lp指向的地址为0时,直接用组缓冲0补上,效果是将当前显示的内容移出
                        tmp=c%2;        //取余,目的是为了判断处理汉字的前半部份还是后半部份
                        for(i=0;i<16;i++)
                        {               
                                tmp2=lp[i*2+tmp];        //取半个汉字点阵数据,16字节
                        }
                        if(tmp)                //当tmp为1时,表时一个字数组处理完成,将地址转到下一个字
                                lp+=32;
                }
                //--------------
                tmp=8;                //变量再次利用
                while(tmp)
                {               
                        ia=0;                //做为点阵数组的元素
                        for(i=0;i<16;i++)
                        {//移动是16行同时移,因此要处理16个字节
                                lhj[ia]<<=1;        //移当前显示缓冲的前半行字节
                        if(lhj[ia+1]&0x80)        //判断后半行字节的高位是否为1,                                               lhj[ia]++;
                                ia++;                        
                                lhj[ia]<<=1;        //移当前显示缓冲的后半行字节
                                if(tmp2&0x80)        //判断下一个要显示汉字的前半行字节的高位是否为1,
                                   lhj[ia]++;
                                ia++;
                                tmp2<<=1;        //下一个要显示汉字的半行字节向高位移一位准备下一次取位
                        }
                        tmp--;
                        timerc=timer;        //处理完16行,调用显示函数更新点阵
                        while(timerc--)        //循环做为处理的速度,即移动的速度
                        display();
                }
                c--;        //移完一半,进入下一半或下一个汉字,直到结束
        }
}
void displaymovetb(unsigned char din,unsigned char *lp,unsigned char timer)
//上下移动内容,din:1为向下,0为向上,lp指向要移入的内容,timer为移动速度
{
        unsigned char i=0,j=0,ia=0;
        unsigned int tmp=0,timerc=0;
        if(din)
        {        //判断移动方向,向下
                ia=32;                //要移入第一个汉字的数组元素
                i=16;                //行索引
                while(i--)
                {                //逐行处理
                        j=30;
                        while(j)
                        {
                                j--;
                                lhj[j+2]=lhj[j];        //将上一行的内容复制到下一行,
                        }
                        if(lp==0)
                        {                                //最后一行的处理,判断移入的内容是否为空,是用0移入
                                lhj[0]=0;
                                lhj[1]=0;
                        }
                        else
                        {                                        //否则,取字数组处理
                                ia--;               
                                lhj[1]=lp[ia];
                                ia--;
                                lhj[0]=lp[ia];               
                        }
                        timerc=timer;        //处理完16行,调用显示函数更新点阵
                        while(timerc--)        //循环做为处理的速度,即移动的速度
                        display();
                }
        }
        else
        {                        //移动方向,向上
                ia=0;        //向上移动,移入汉字从低位开始
                for(i=0;i<16;i++)
                {        //处理16行
                        for(j=0;j<30;j++)        //将下一行的内容复制到上一行,
                        lhj[j]=lhj[j+2];
                        if(lp==0)
                        {                        //最后一行的处理,判断移入的内容是否为空,是用0移入
                                lhj[30]=0;
                                lhj[31]=0;
                        }
                        else
                        {                        //否则,取字数组处理
                                lhj[30]=lp[ia];
                                lhj[31]=lp[ia+1];
                                ia+=2;                           
                        }
                        timerc=timer;        //处理完16行,调用显示函数更新点阵
                        while(timerc--)        //循环做为处理的速度,即移动的速度
                        display();
                }
        }                        
}
void delay(unsigned int a)                                                                //延时
{
        while(a--);
}

void right_display()//右移子程序
{
        int i;
        while(0xF2==Temp)//输入r,右移
        {
                for(i=0;i<32;i++)
                        lhj=GUANG;//将"广"字数据复制到显示缓存
                displayS(2);                    //显示"广"字约1秒
                displaymove(DONG,5,7);       //将从"东"开始的5个汉字从右向左移动
                for(i=0;i<32;i++)
                        lhj=GUANG;//将"广"字数据复制到显示缓存
        }
}
void up_display()//上移子程序        
{
        int i;
        while(0xF5==Temp)//输入u,上移
        {
                displaymovetb(0,GUANG,10);            //将"广"字以10的速度向上移动
                displaymovetb(0,DONG,10);          //将"东"字以10的速度向上移动
                displaymovetb(0,JI,10);          //将"技"字以10的速度向上移动
                displaymovetb(0,SU,10);          //将"术"字以10的速度向上移动
                displaymovetb(0,SHI,10);           //将"师"字以10的速度向上移动
                displaymovetb(0,FAN,10);           //将"范"字以10的速度向上移动
                displaymovetb(0,0,10);            //以10的速度向上清空
                for(i=0;i<32;i++)
                        lhj=GUANG;//将"广"字数据复制到显示缓存        
        }
}
void UART_SER (void) interrupt 4   //串行中断服务程序
{  
        if(RI==1) //判断是接收中断产生        
        {
                RI=0;   //标志位清零
                Temp=SBUF; //读入缓冲区的值
                SBUF=Temp;  //把接收到的值再发回电脑端
        }
        if(TI==1)//如果是发送标志位,清零
        TI=0;
}


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
9条回答
菜鸟与大神
1楼-- · 2019-07-15 22:50
求求各位大神了,要是仿真不出,毕设完成不了了,跪求。
依然落叶飘零
2楼-- · 2019-07-16 00:19
你这电路看着真是恐怖,这么多三极管,用来干嘛?你仿真有什么问题?一点都不显示还是显示不对?一点都不显示应该是电路的问题。
菜鸟与大神
3楼-- · 2019-07-16 01:22
依然落叶飘零 发表于 2014-5-17 18:09
你这电路看着真是恐怖,这么多三极管,用来干嘛?你仿真有什么问题?一点都不显示还是显示不对?一点都不显 ...

三极管用来放大呀,从74hc164出来的电流驱动不了16个二极管,所以加个放大,仿真是显示不出字,胡乱显示一些,基本上都是一列一列的亮。关键是我想知道这程序能不能实现动态显示。我是机械电子专业的,不太懂c语言编程的单片机程序。
依然落叶飘零
4楼-- · 2019-07-16 06:20
菜鸟与大神 发表于 2014-5-17 18:16
三极管用来放大呀,从74hc164出来的电流驱动不了16个二极管,所以加个放大,仿真是显示不出字,胡乱显示 ...

看你是广技师的,把keil和proteus工程文件发给我看看,不敢保能弄出来的。
菜鸟与大神
5楼-- · 2019-07-16 12:19
 精彩回答 2  元偷偷看……
依然落叶飘零
6楼-- · 2019-07-16 14:32
菜鸟与大神 发表于 2014-5-17 18:41
不管能不能调出,先谢谢你能帮我

我找到问题的所在了,具体怎么弄还得你自己去弄。
还是三极管的问题。74HC164输出是没有问题的,但是进过三极管后输出都是高电平,因此都是整列整列的显示。
仿真的时候管脚是红 {MOD}就是高电平,蓝 {MOD}就是低电平,灰 {MOD}就是电平不确定。
不要用三极管,用反相器增大输出电流。74HC164输出经过74HC04反相输入到点阵。
至于程序有没有问题我就不知道了。有问题再上来问。

一周热门 更多>