点阵屏,32*32输出显示,稍微上那么点技术的东西,希望对大家有所帮助。
基于单片机型号stc15w4k32s4,分别运用的是74LS138和74HC595两款译码器
下面是Proteus仿真
下面是代码部分
#include<stc15.h>
#include<intrins.h>
#define uchar unsigned char
sbit DS=P1^5;//DS
sbit SH=P1^6;//SH
sbit ST=P1^7;//ST
sbit D_port=P1^0;
sbit C_port=P1^1;
sbit B_port=P1^2;
sbit A_port=P1^3;
sbit G_port=P1^4;
sbit key1=P3^3;sbit key2=P3^2;
uchar run=4;
unsigned int second;
void Timer0Init(void) //20毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xE0; //设置定时初始值
TH0 = 0xB1; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void SendData (unsigned char m, unsigned char n)
{
unsigned char i;
ST=0;
for (i=0;i<16;i++)
{
SH=0;
if(i<8)
{
DS=0X80& (m<<i);
}
else
DS=0x80& (n<<(i-8));
SH=1;
}
ST=1;
}
/*void HC595SendData(unsigned char n)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(n&0x80)DS=1;
else DS=0;
n<<=1;
SH=0;
SH=1;
}
ST=0;
ST=1;
}*/
/*-------------------------------------------------------
点阵LED第几行显示数据
其中daH为数据高8位,daL为数据低8位,han为第几行显示
--------------------------------------------------------*/
void HC595_Data_Send(uchar daH,daL,han)
{
SendData (daH, daL);
//HC595SendData(daH);
//HC595SendData(daL);
G_port = 1; /*关屏显示,原理为使HC138输出全为1,从而三极管截止,点阵不显示*/
switch (han){
case 0:
A_port = 0; B_port = 0; C_port = 0; D_port = 0;
break;
case 1:
A_port = 1; B_port = 0; C_port = 0; D_port = 0;
break;
case 2:
A_port = 0; B_port = 1; C_port = 0; D_port = 0;
break;
case 3:
A_port = 1; B_port = 1; C_port = 0; D_port = 0;
break;
case 4:
A_port = 0; B_port = 0; C_port = 1; D_port = 0;
break;
case 5:
A_port = 1; B_port = 0; C_port = 1; D_port = 0;
break;
case 6:
A_port = 0; B_port = 1; C_port = 1; D_port = 0;
break;
case 7:
A_port = 1; B_port = 1; C_port = 1; D_port = 0;
break;
case 8:
A_port = 0; B_port = 0; C_port = 0; D_port = 1;
break;
case 9:
A_port = 1; B_port = 0; C_port = 0; D_port = 1;
break;
case 10:
A_port = 0; B_port = 1; C_port = 0; D_port = 1;
break;
case 11:
A_port = 1; B_port = 1; C_port = 0; D_port = 1;
break;
case 12:
A_port = 0; B_port = 0; C_port = 1; D_port = 1;
break;
case 13:
A_port = 1; B_port = 0; C_port = 1; D_port = 1;
break;
case 14:
A_port = 0; B_port = 1; C_port = 1; D_port = 1;
break;
case 15:
A_port = 1; B_port = 1; C_port = 1; D_port = 1;
break;
}
ST = 1; /*允许HC595数据输出到Q1-Q8端口*/
G_port = 0; /*HC138输出有效,打开显示*/
ST = 0; /*锁定HC595数据输出*/
}
///实物阳码,仿真阴码
uchar code string[]={
0xFF,0xFF,0xFF,0xFF,0x00,0x80,0xDF,0xFF,0xDF,0xFF,0xDF,0xFF,0x1F,0xF0,0xDF,0xF7,
0xDF,0xF7,0xEF,0xF7,0xEF,0xF7,0xF7,0xF7,0xF7,0xF7,0xFB,0xF7,0xFD,0xFA,0xFE,0xFD,/*"万",0*/
0x7F,0xFF,0x7F,0xFF,0x00,0x80,0x7F,0xFF,0x03,0xE0,0x7B,0xEF,0x03,0xE0,0x7F,0xFF,
0x03,0xE0,0x7F,0xEF,0x00,0x80,0x7F,0xEF,0x03,0xE0,0x7F,0xFF,0x5F,0xFF,0xBF,0xFF,/*"事",1*/
0xF7,0xFF,0xF7,0xFF,0xF7,0xFF,0xF7,0xC1,0x80,0xDD,0xBB,0xDD,0xBB,0xDD,0xBB,0xDD,
0xBD,0xDD,0xDB,0xDD,0xD7,0xDD,0xEF,0xDD,0xD7,0xDD,0xBB,0xC1,0xBD,0xDD,0xFE,0xFF,/*"如",2*/
0x7F,0xFF,0x03,0xE0,0xEF,0xFB,0xDF,0xFD,0x00,0x80,0xFF,0xFF,0x07,0xF0,0xF7,0xF7,
0x07,0xF0,0xF7,0xF7,0x07,0xF0,0xBF,0xFF,0x75,0xDF,0x75,0xB7,0xF6,0xB7,0x0F,0xF0/*"意",3*/
};
//姓名杨鹏
uchar code string2[]={
0xFF,0xFF,0xBF,0xFF,0xBD,0xFF,0x3B,0x00,0xBB,0xFF,0xBB,0xFF,0x03,0xE0,0xFF,0x9F,
0xBB,0x6D,0xAB,0xF5,0x9B,0xFD,0x39,0x80,0x9A,0x7D,0xAB,0xB5,0xBB,0xED,0xBF,0xDF,/*"新",7*/
0xFF,0xFF,0xFF,0xFB,0xFB,0xFB,0xBB,0xFB,0xBB,0xFB,0xBB,0xFB,0xBB,0xFB,0x03,0x00,
0xBB,0xFB,0xBB,0xFB,0xBB,0xFB,0xBB,0xFB,0x38,0xF8,0xE7,0xFB,0xDF,0xFB,0xFF,0xFB,/*"年",8*/
0xFF,0xFF,0xFF,0x7E,0xFF,0x7E,0x07,0xBE,0xF7,0xCE,0xF7,0xF2,0x00,0xFC,0xF7,0xF2,
0xF7,0xCE,0xF7,0xBE,0xDF,0x7E,0xEF,0xFF,0x00,0x00,0xFF,0xFF,0x1F,0xFF,0xFF,0xFE,/*"快",9*/
0xFF,0xFF,0xFF,0xFF,0x7F,0xCF,0x7F,0xF7,0x7D,0xFB,0x7C,0xFD,0x7D,0xFF,0x7D,0xFF,
0x0B,0x80,0x7B,0x7F,0x7B,0xBF,0x7B,0xF9,0x63,0xF7,0x1F,0xEF,0xFF,0xDF,0xFF,0xFF/*"乐",10*/
};
uchar code string_downtoup[]={
0x00,0x00,
0x0B,0x80,0x7B,0x7F,0x7B,0xBF,0x7B,0xF9,0x63,0xF7,0x1F,0xEF,0xFF,0xDF,0xFF,0xFF,/*"乐",10*/
0xFF,0xFF,0xFF,0x7E,0xFF,0x7E,0x07,0xBE,0xF7,0xCE,0xF7,0xF2,0x00,0xFC,0xF7,0xF2,
0xF7,0xCE,0xF7,0xBE,0xDF,0x7E,0xEF,0xFF,0x00,0x00,0xFF,0xFF,0x1F,0xFF,0xFF,0xFE,/*"快",9*/
0xFF,0xFF,0xFF,0xFB,0xFB,0xFB,0xBB,0xFB,0xBB,0xFB,0xBB,0xFB,0xBB,0xFB,0x03,0x00,
0xBB,0xFB,0xBB,0xFB,0xBB,0xFB,0xBB,0xFB,0x38,0xF8,0xE7,0xFB,0xDF,0xFB,0xFF,0xFB,/*"年",8*/
0xFF,0xFF,0xBF,0xFF,0xBD,0xFF,0x3B,0x00,0xBB,0xFF,0xBB,0xFF,0x03,0xE0,0xFF,0x9F,
0xBB,0x6D,0xAB,0xF5,0x9B,0xFD,0x39,0x80,0x9A,0x7D,0xAB,0xB5,0xBB,0xED,0xBF,0xDF,/*"新",7*/
0xFF,0xFF,0xF3,0xDF,0xCB,0xDF,0x5B,0xEF,0xDB,0xEE,0xDB,0xF5,0xDB,0xFB,0xDB,0x80,
};
//(从下到上)
delay(uchar a){
uchar m;
for(m=a;m>0;m--);
}
void Delay10ms() //@12.000MHz
{
unsigned char i, j;
i = 117;
j = 184;
do
{
while (--j);
} while (--i);
}
void main(){
HC595_Data_Send(0xff,0xff,0);ST=0;ST=1;
EA=1;ET0=1;EX0=1;IT0=1;EX1=1;IT1=1;//开T0,INT0,INT1中断 且INT0,INT1下降沿有效
PT0=1;//设置T0优先级高于INT0,INT1
Timer0Init() ;//定时器初始化
while(1){
uchar i,j,n,k=0;
HC595_Data_Send(0xff,0xff,0);
if(run==4)HC595_Data_Send(0xff,0xff,0);
for(j=0;j<4;j++){
for(n=0;n<100;n++){ //循环时间
for(i=0;i<16;i++){ //内层循环
if(run==0){
HC595_Data_Send(string[i*2+1+j*32],string[i*2+j*32],k);
delay(270);
HC595_Data_Send(0xff,0xff,0);//消影
k++;
if(k==16) k=0;}
}}}//多屏显示
for(j=0;j<48;j++){//滚动32行,共32屏
for(n=0;n<50;n++){
for(i=0;i<16;i++){
if(run==1){
HC595_Data_Send(string[(i+j)*2+1],string[(i+j)*2],k);
delay(270);
HC595_Data_Send(0xff,0xff,0);
k++;
if(k==16) k=0;}
} } }//滚动显示(从上到下)
for(j=0;j<4;j++){
for(n=0;n<100;n++){ //循环时间
for(i=0;i<16;i++){ //内层循环
if(run==2){
HC595_Data_Send(string2[i*2+1+j*32],string2[i*2+j*32],k);
delay(270);
HC595_Data_Send(0xff,0xff,0);
k++;
if(k==16) k=0;}
}}}//多屏显示
for(j=48;j>0;j--){//滚动48行,共48屏
for(n=0;n<50;n++){
for(i=0;i<16;i++){
if(run==3){
HC595_Data_Send(string_downtoup[(i+j)*2+1],string_downtoup[(i+j)*2],k);
delay(270);
HC595_Data_Send(0xff,0xff,0);
k++;
if(k==16) k=0;}
}}}//滚动显示(从下到上)
}}
void INT0(void) interrupt 0
{
Delay10ms(); //延时 消抖
if(key2==0) //key2按下
{
HC595_Data_Send(0xff,0xff,0);
second=0;
TR0 = 1;
}
while(key2==0);//等待按键释放
TR0 = 0; //定时器0暂停计时
if (second>100)run=4;
else if(second>50)run=3;
else run=2;
}
void INT1(void) interrupt 2
{
Delay10ms(); //延时 消抖
if(key1==0) //key1按下
{
HC595_Data_Send(0xff,0xff,0);
second=0;
TR0 = 1;
}
while(key1==0);//等待按键释放
TR0 = 0; //定时器0暂停计时
if (second>50)run=1;
else run=0;
}
void Timer0(void) interrupt 1//20ms计时
{
second++;
}
提一嘴,按键的切换功能采用中断来实现,这边结果展示就不上传了,有需要的同学,关注加私信我就行了,希望对同学们有所帮助,88。