用STC89C52 ,74hc138驱动列,74hc595驱动行,8x8点阵显示问题。

用STC89C52 ,74hc138驱动列,74hc595驱动行,8x8点阵显示问题。,第1张

没有看到你的原理图,只能从原理上告诉你如何检查故障,或称之为“授以渔”吧。

你的问题是:结果只显示了最后一行的两个点

说明你的sendbyte_L()行选择有问题,可能是软件问题,也可能是硬件问题

首先断开138输入A、B、C与cpu的连接,手动设置A、B、C的高低电平,看显示是否对应的8个行是否轮流都亮,不亮再看138输出8个引脚的电平是否相应变化,这样就可以排查硬件问题。

假如硬件没有问题,检查软件,你的关闭显示段去掉,再看看;或者直接在程序中固定某行亮,依次排查,相信很快就可以找到问题所在了。

在检查故障中可以学到很多东西,比一帆风顺的做好作品学到的东西要多得多。

祝你成功!

这要从74hc595锁存方式说起,它是串行输入转并行输出的8位数据锁存器,需要串行输入8位二进制,也就是说要求将8位二进制dat,一位一位地送入74hc595数据输入端SD,且每输入一位需要一个时间脉冲CLK,共需要8个时钟脉冲才能将dat的8位数全部输入到74hc595内,再转换成并行8位数据。所以,要从dat的高位取出一位,送入SD,SER=dat&0x80;就是取出高位,然后还是将dat向左移一位,即将下一位移向高位,准备下次再取出送放SER。程序中肯定有移位一行或两行的。

而SER是定义为端口的,即是单片机接到74hc595的SD的那个I/O脚,假设是接到P11,那程序的前面就应该有一行是:sbit SER=P11;

这样,SER是一个位,并不是8位二进制,而你理解成8位二进制数了,所以,就不理解SER=dat&0x80这行的意义了。

横着数是行,竖着数是列。LED是一个一个的小发光二极管,每一个发光二极管都有一个点亮或不亮的控制源,那个源就是某一个二极管的驱动。行驱动就是横着一行的驱动,列驱动就是竖着一列的驱动。

很简单/1616点阵屏的显示/

#include <reg51h>

#include <intrinsh>

#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 lhj[32];//32字节RAM做为1616点阵屏显示缓存

void display();//做为点阵扫描函数,将显示缓存的数据输出到点阵屏

void displayS(unsigned int timer);//指定时间扫描显示

void displaymove(unsigned char lp,unsigned char c,unsigned char timer);//显示汉字内容的移动效果,LP指向要显示第一个字的首地址,C表示显示字的个数,

//timer是移动的速度

void displaymovetb(unsigned char din,unsigned char lp,unsigned char timer);

//上下移动内容,din:1为向下,0为向上,lp指向要移入的内容,timer为移动速度

void delay(unsigned int a);//延时子函数

code unsigned char lin[32]={0x04,0x20,0x04,0x20,0xff,0xfe,0x04,0x20,//汉字"英"的点阵数据。汉字点阵数据,可用汉字库点阵生成软件获得

0x01,0x00,0x1f,0xf0,0x11,0x10,0x11,0x10,

0x11,0x10,0xff,0xfe,0x01,0x00,0x02,0x80,

0x04,0x40,0x08,0x30,0x10,0x1c,0x20,0x08};

code unsigned char yang[32]={//达

0x00,0x00,0x40,0x80,0x30,0x80,0x10,0x80,

0x0f,0xfc,0x00,0x80,0x00,0x80,0xe0,0x80,

0x21,0x40,0x21,0x20,0x22,0x18,0x24,0x0c,

0x28,0x08,0x50,0x02,0x8f,0xfc,0x00,0x00};

code unsigned char dian[32]={//通

0x40,0x00,0x27,0xf8,0x20,0x90,0x00,0x60,

0x07,0xf8,0x04,0x48,0xe7,0xf8,0x24,0x48,

0x24,0x48,0x27,0xf8,0x24,0x48,0x24,0x68,

0x24,0x50,0x50,0x00,0x8f,0xfe,0x00,0x00};

code unsigned char zi[32]={//讯

0x40,0x00,0x27,0xf8,0x31,0x08,0x21,0x08,

0x01,0x08,0xf1,0x08,0x17,0xe8,0x11,0x08,

0x11,0x08,0x11,0x08,0x11,0x08,0x11,0,

0x15,0,0x19,0,0x11,0x04,0x00,0x00};

code unsigned char LY[32]={//图案数据

0x00,0x00,0x30,0x00,0x30,0x20,0x30,0x30,

0x30,0x18,0x30,0x0C,0x30,0x06,0x3F,0x7F,

0x3F,0x7F,0x00,0x06,0x00,0x0C,0x00,0x18,

0x00,0x30,0x00,0x20,0x00,0x00,0x00,0x00};

void main(void) //主入口函数

{

unsigned char i=0,j=0;

for(i=0;i<32;i++)

lhj[i]=LY[i];//将图案数据复制到显示缓存

while(1){

displayS(2); //显示图案约2秒

displaymove(lin,4,7);//将从"英"开始的四个汉字从右向左移动

displayS(1); //等持约1秒

displaymovetb(1,0,10); //将点阵上显示的内容向下以10的速度移出,补上0,即清空显示屏

displayS(1); //等待1秒

displaymovetb(0,lin,10); //达"达"字以10的速度向上移动

displaymovetb(0,yang,10); //将"通"字以10的速度向上移动

displaymovetb(0,dian,10); //将"讯"字以10的速度向上移动

displaymovetb(0,zi,10); //将"子"字以10的速度向上移动

displaymovetb(0,0,10); //以10的速度向上清空

displayS(1); //等待1秒

displaymovetb(1,LY,10); //将"图案"以10的速度向下移动

}

}

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;){ //每行16个点,循环位移两个字节

ia--; //循环两次

tmp=~lhj[i2+ia]; //读取点阵数据做输出,这里用到ia目的是先读取点阵数据的第二位字节,因一行16个点由两个字节组成,

//电路中的移位寄存器最后一位对应最后一列,所以要先输出一行中的第二个字节数据

for(j=0;j<8;j++){ //循环两次,每次移一个字节,

SCLH=0; //为列移位做准备

DATA=tmp&0x01; //将数据低位做输出,由电路图可知,移位寄存器的最后一位对应最后一列,因此先移最后一位

tmp>>=1; //将数据缓冲右移一位,为下次输出做准备

SCLH=1; //将DATA上的数据移入寄存器

} //移入单字节结束

} //移入两个字节结束

DATAOUT|=0X24; //此句可以用以下两句来理解,如果不将两句合为一句,将出现拖影现像

//SCK=1; //SCK拉高,行数据移位,相应行拉低,三极管导通输出电量到相应行点阵管阳极(共阳)

//SCLT=1; //SCLT拉高,将数据锁存输出到相应列的点阵发光管显示,显示一行后将保持到下一行显示开始

AB=1; //行数据位只在第一行时为0,其它时候都为1,当将这个0移入寄存器后,从第一位开始一直移位最后一位,

//移位的过程,AB就必需是1,这是因为不能同时有两个及两个以上0的出现,否则显示出乱

}

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表示显示字的个数,

//timer是移动的速度

{

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[i]=lp[i2+tmp]; //取半个汉字点阵数据,16字节

}

if(tmp) //当tmp为1时,表时一个字数组处理完成,将地址转到下一个字

lp+=32;

}

//--------------

tmp=8; //变量再次利用

while(tmp){ //循环8次,是将下一个字的前半部份的字节数据移入显示缓冲

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[i]&0x80) //判断下一个要显示汉字的前半行字节的高位是否为1,是移入,否则不处理

lhj[ia]++;

ia++;

tmp2[i]<<=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]; //将上一行的内容复制到下一行,每两行内容相隔四个字节,复制15行

}

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++) //将下一行的内容复制到上一行,每两行内容相隔四个字节,复制15行

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--);

}

有字模软件修改你想要显示的字,程序要字模改动别告诉我你不懂

以下是16x16的点阵LED电子图文显示屏的源程序采用汇编语言编写(也可采用C语言编写,C程序KeiluVision2 V230环境下调试通过。

以下为用汇编语言编写的字符显示控制程序:

; 单个16x16的点阵电子屏字符显示器

; ATA89C52 12MHz晶振

; 2004211 LRM

;显示字用查表法,不占用内存,字符用16x16共阳LED点阵,

;效果:向上滚动显示5个字,再重复循环。

;R1:查表偏址寄存器,B:查表首址,R2:扫描地址(从00~0FH)。

;R3:滚动显示时控制移动速度,单字显示可控制静止显示的时间。

;;

;中断入口程序 ;

;;

ORG 0000H

LJMP START

ORG 0003H

RETI

ORG 000BH

LJMP INTTO

ORG 0013H

ERTI

ORG 001BH

ERTI

ORG 0023H

RETI

ORG 002BH

RETI

;;

;初始化程序;

;;

;;

; 主程序 ;

;;

START: MOV 20H,#00H ;清零标志,00H为第16行开始扫描标志,01为1帧

;扫描结束标志

MOV A,#0FFH ;端口初始化

MOV P1,A

MOV P1,A

MOV P3,A

MOV P0,A

CLR P16 ;串行寄存器输入打入输出控制位

MOV TMOD,#01H ;使用T0做16位定时器,行扫描用。

MOV TH0,#0FCH ;1ms初值(12MHz)

MOV TL0,#18H

MOV SCON,#00H ;串口0方式传送显示字节

MOV IE,#82H ;T0中断允许,总中断允许

MOV SP,#70H

MAIN: LCALL DISI ;显示准备,黑屏,15s

MOV DPTR,#TAB

LCALL MOVDISP ;向上滚动显示一页(8个字)

INC DPH

LCALL MOVDISP ;向上滚动显示一页(8个字)

INC DPH

LACLL MOVDISP ;向上滚动显示一页(8个字)

AJMP MAIN

;;

; 多字滚动显示程序 ;

;;

;每次8个字,入口时定义好DPTR值

MOVDISP: MOV B,#00H ;向上移动显示,查表偏值暂存(从00开始)

DISLOOP: MOV R3,#07H ;移动速度

DISMOV: MOV R2,00H ;第0行开始

MOV R1,B

SETB TR0 ;开扫描(每次一帧)

WAITMOV: JBC 01H,DISMOV1 ;标志为1扫描一帧结束(16ms为1帧,每行1ms)

AJMP WAITMOV

DISMOV1: DJNZ R3,DISMOV ;1帧重复显示(控制移动速度)

INC B ;显示字的下一行(每行2字节)

INC B

MOV A,R1 ;R1为0,8个字显示完

JZ MOVOUT

AJMP DISLOOP

MOVOUT: RET ;移动先是结束

;;

; 单字显示程序 ;

;;

;显示表中某个字;

;;

DIS1: MOV R3,#5AH ;静止显示时间控制(16ms#=16s)

DIS11: MOV R2,#00H ;一帧扫描初始值(行地址从00~0FH)

MOV DPTR,#TAB ;取表首址

MOV R1,#00H ;查表偏址(显示第一个字)

SETB TR0 ;开扫描(每次一帧)

WAIT11: JBC 01H,DIS111 ;为1,扫描一帧结束

AJMP WAIT11

DIS111: DJNZ R3,DIS11

RET

;;

; 扫描程序 ;

;;

;1ms刷新一次,每行显示1s

INTT0: PUSH ACC

MOV TH0,#0FCH ;1ms初值重装

MOV TL0,#18H

JBC 00H,GOEND ;16行扫描标志为1,结束

INC R1 ;取行右边字节偏址

MOV A,R1

MOVC A,@A+DPTR ;查表

MOV SBUF,A ;串口0方式发送

WAIT: JBC TI,GO ;等待发送完毕

AJMP WAIT1

GO: DEC R1 ;取行左边字节偏址

MOV A,R1

MOVC A,@A+DPTR

MOV SBUF,A

WAIT1: JBC T1,GO1

AJMP WAIT1

GO1: SETB P17 ;关行显示,准备刷新

NOP ;串口寄存器数据稳定

SETB P16 ;产生上升沿,行数据打入输出端

NOP

NOP

CLR P16 ;恢复低电平

MOV A,R2 ;修改显示行地址

ORL A,#0F0H ;修改显示行地址

MOV R2,A ;修改显示行地址

MOV A,P1 ;修改显示行地址

ORL A,#0FH ;修改显示行地址

ANL A,R2 ;修改显示行地址

MOV P1,A ;修改完成

CLR P17 ;开行显示

INC R2 ;下一行扫描地址值

INC R1

INC R1 ;下一行数据地址

MOV A,R2

ANL A,#0FH

JNZ GO2

SETB 00H ;R2为01H,现为末行扫描,置标志

GO2: POP ACC

RETI

GOEND: CLR TR0 ;一帧扫描完毕,关扫描

SETB 01H ;一帧扫描完毕,置结束标志

POP ACC

RETI ;退出

;;

; 扫描文字表 ;

;;

TAB:DB 0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,00FFH,0FFH,0FFH ;黑屏

DB

0F9H,0BFH,0C7H,0AFH,0F7H,0B7H,0F7H,0B7H,0F7H,0BFH,000H,001H,0F7H,0BFH,0F7H,0B7H ;我

DB

0F1H,0D7H,0C7H,0CFH,037H,0DFH,0F7H,0AFH,0F6H,06DH,0F7H,0F5H,0D7H,0F9H,0EFH,0FDH ;

DB

0FFH,007H,0C0H,06FH,0EDH,0EFH,0F6H,0DFH,0C0H,001H,0DDH,0FDH,0BDH,0FFH,0C0H,003H ;爱

DB

0FBH,0FFH,0F8H,00FH,0F3H,0DFH,0F4H,0BFH,0EFH,03FH,09CH,0CFH,073H,0F1H,0CFH,0FBH ;

DB

0F7H,0DFH,0F9H,0CFH,0FBH,0BFH,0C0H,007H,0DEH,0F7H,0C0H,007H,0DEH,0F7H,0DEH,0F7H ;单

DB

0C0H,007H,0DEH,0F7H,0FEH,0FFH,000H,001H,0FEH,0FFH,0FEH,0FFH,0FEH,0FFH,0FEH,0FFH

DB

0FFH,0BFH,0EFH,0BFH,0EFH,0BFH,0EFH,0BBH,0E0H,001H,0EFH,0FFH,0EFH,0FFH,0EFH,0FFH ;片

DB

0E0H,00FH,0EFH,0EFH,0EFH,0EFH,0EFH,0EFH,0DFH,0EFH,0DFH,0EFH,0BFH,0EFH,07FH,0FFH

DB

0EFH,0FFH,0EFH,007H,0EFH,077H,001H,077H,0EFH,077H,0EFH,077H,0C7H,077H,0CBH,077H ;机

DB

0ABH,077H,0AFH,077H,06EH,0F7H,0EEH,0F5H,0EDH,0F5H,0EDH,0F5H,0EBH,0F9H,0EFH,0FFH ;

DB

0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH ;黑屏

DB

0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH ;

END

用2个138级联控制列,2个595,每个595控制2个8x8的点阵 我感觉这个程序就是最简单的滚动显示的程序 了

#include <reg52h>

sbit STR=P3^2; //锁存

sbit SRCLK=P3^3; //时钟

sbit SDI= P3^5;

//16×16汉

unsigned char code hanzi1[][32]={

/-- 文字: 要 --/

/-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --/

0xFF,0xFF,0x80,0x03,0xFB,0xBF,0xFB,0xBF,0xC0,0x07,0xDB,0xB7,0xDB,0xB7,0xC0,0x07,

0xFD,0xFF,0x80,0x03,0xFB,0xDF,0xF7,0xBF,0xE3,0x7F,0xFC,0x7F,0xF9,0x8F,0xC7,0xF7,/-- 文字: 一 --/

/-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --/

0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x01,

0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,

/-- 文字: 定 --/

/-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --/

0xFD,0xFF,0xFE,0xFF,0x80,0x01,0xBF,0xFD,0x7F,0xFB,0xFF,0xFF,0xC0,0x07,0xFE,0xFF,

0xFE,0xFF,0xEE,0xFF,0xEE,0x07,0xEE,0xFF,0xEE,0xFF,0xD6,0xFF,0xB8,0x01,0x7F,0xFF,

/-- 文字: 好 --/

/-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --/

0xEF,0xFF,0xEF,0x03,0xEF,0xFB,0xEF,0xF7,0x03,0xEF,0xDB,0xDF,0xDB,0xDF,0xDA,0x01,

0xDB,0xDF,0xB7,0xDF,0xD7,0xDF,0xEF,0xDF,0xD7,0xDF,0xBB,0xDF,0x7B,0x5F,0xFF,0xBF,

/-- 文字: 好 --/

/-- 宋体12; 此字体下对应的点阵为:宽x高=16x16 --/

0xEF,0xFF,0xEF,0x03,0xEF,0xFB,0xEF,0xF7,0x03,0xEF,0xDB,0xDF,0xDB,0xDF,0xDA,0x01,

0xDB,0xDF,0xB7,0xDF,0xD7,0xDF,0xEF,0xDF,0xD7,0xDF,0xBB,0xDF,0x7B,0x5F,0xFF,0xBF,

}

void delay()

{

unsigned int a;

for(a=400;a>0;a--); /延时程序/

}

void SendByteR(char dat) //74HC595驱动程序,发送一个字节到移位寄存器

{

char i,ddat=~dat;

for (i=0;i<8;i++)

{

ddat<<=1;

SDI=CY;

SRCLK=1;

SRCLK=0;

}

}

void main(void)

{

unsigned int i,j,b;

while(1)

{

P1=0xff;

for(j=0;j<256;j++) //移动多少次

{

for(b=0;b<3;b++) //控制速度

{

for(i=0;i<16;i++)

{

SendByteR(hanzi1[0][(i+j)2]);

SendByteR(hanzi1[0][(i+j)2+1]);

P1=i;

STR=0;STR=1;

delay();

}

}

}

delay(); delay();

}

}

以上就是关于用STC89C52 ,74hc138驱动列,74hc595驱动行,8x8点阵显示问题。全部的内容,包括:用STC89C52 ,74hc138驱动列,74hc595驱动行,8x8点阵显示问题。、你好,关于那个单片机点阵屏中74hc595的驱动程序中SER=dat&0x80;这句的理解、请问,在led点阵显示屏中行驱动,列驱动是什么意思等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9403144.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-28
下一篇 2023-04-28

发表评论

登录后才能评论

评论列表(0条)

保存