📄 led点阵显示屏源程序.c
字号:
/*******************************************************
**
** 毕业设计:LED点阵显示屏源程序
** 山东理工大学 电气与电子工程学院 自动化专业
** 作者:胡成通
** 完成时间:2007-06-10
**
*********************************************************/
#include <reg51.h>
#include <stdio.h>
#include <absacc.h>
#define uint unsigned int
#define uchar unsigned char
#define CS165_2 XBYTE[0xbff8]; //74HC165地址
#define CS165_3 XBYTE[0xbff8]; //
sbit cs_6116_138=P1^4; //控制板上6116和138的片选,=0选中6116,=1选中74LS138
sbit cs_138=P2^7;
bit bdata fun_com; //单片机单机运行标志位
//当此标志位有效时=1,则循环调用动态显示子程序(暂时为7种显示//模式)
bit bdata fun_pc;//单片机显示PC通信的数据,
//标志位有效=1时,跳转到相应的子程序,处理PC通信数据,进行约定//的显示
uchar xdata show_buffer1[16][8];//显示缓冲区1,列为8字节数据(代表64点),
//一共有16行
uchar xdata show_buffer2[16][8]; //两显示缓冲区存放在片外数据存储器(6116)
bit bdata showbuf_sign; //显示缓冲区标志位,=0时使用show_buffer1,
//=1时使用show_buffer2
uchar xdata show_pc[16][42]; //用于存储PC通信的数据,最多可以20个汉字
//(或40个ASCII字符)加上相关的处理信息
uchar idata *show_pcpoint; //用于在串行中断处理中,指向show_pc,
//将所有的通信数据信息放入此数组中
uchar idata **show_pcdata; //指向PC通信有效显示数组的数据的首地址
uint show_pccount; //对通信数据个数计数
bit bdata show_pccom; //PC正在通信标志位,=1有效
bit bdata show_pcend; //PC通信结束标志位
uint PC_COM(void); //函数声明
void uart_int(void);
void show_static(uchar **);
void show_left(uchar **,uint);
void show_right(uchar **);
void show_up(uchar **);
void show_down(uchar **);
void show_upspread(uchar **);
void show_downspread(uchar **);
void show_down(uchar **);
void show_middle(uchar **);
void show_pcprocess(uint);
uchar xdata data_com[16][12]={
0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, //"山"
0x41, 0x04, 0x41, 0x04, 0x41, 0x04, 0x41, 0x04,
0x41, 0x04, 0x41, 0x04, 0x41, 0x04, 0x41, 0x04,
0x41, 0x04, 0x7F, 0xFC, 0x40, 0x04, 0x00, 0x00,
0x02, 0x00, 0x02, 0x00, 0x02, 0x04, 0xFF, 0xFE, //"东"
0x04, 0x00, 0x09, 0x00, 0x09, 0x00, 0x11, 0x10,
0x3F, 0xF8, 0x01, 0x00, 0x09, 0x40, 0x09, 0x20,
0x11, 0x10, 0x21, 0x18, 0x45, 0x08, 0x02, 0x00,
0x00, 0x08, 0x13, 0xFC, 0xFA, 0x48, 0x22, 0x48,
0x23, 0xF8, 0x22, 0x48, 0xFA, 0x48, 0x23, 0xF8,
0x20, 0x40, 0x20, 0x50, 0x23, 0xF8, 0x3C, 0x40,
0xE0, 0x40, 0x40, 0x44, 0x0F, 0xFE, 0x00, 0x00, //"理"
0x00, 0x00, 0x00, 0x08, 0x7F, 0xFC, 0x01, 0x00,
0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
0x01, 0x04, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, //"工"
0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
0x01, 0x04, 0xFF, 0xFE, 0x01, 0x00, 0x02, 0x80,
0x02, 0x80, 0x02, 0x40, 0x04, 0x40, 0x04, 0x20,
0x08, 0x10, 0x10, 0x0E, 0x60, 0x04, 0x00, 0x00, //"大"
0x22, 0x08, 0x11, 0x08, 0x11, 0x10, 0x00, 0x20,
0x7F, 0xFE, 0x40, 0x02, 0x80, 0x04, 0x1F, 0xE0,
0x00, 0x40, 0x01, 0x84, 0xFF, 0xFE, 0x01, 0x00,
0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x02, 0x00 //"学"
};
/*=======================================================*/
/*====================主程序=============================*/
/*======================================================*/
void main(void)
{
uint all_pcdata; //PC通信的有效显示数据字节个数
uart_int(); //初始化串口,设置波特率\开中断\串口工作模式
show_pcpoint=show_pc[0][0]; //指针指向数据存储数组
// show_pccount=0; //通信数据个数计数清零
show_pccom=0; //通信标志位清零
fun_pc=0;
fun_com=1;
while(1)
{
if(fun_com==1)
{
if(fun_com==1&&fun_pc==0)
{show_left(data_com,12); }
if(fun_com==1&&fun_pc==0)
{show_right(data_com); }
if(fun_com==1&&fun_pc==0)
{show_up(data_com); }
if(fun_com==1&&fun_pc==0)
{show_down(data_com); }
if(fun_com==1&&fun_pc==0)
{show_upspread(data_com); }
if(fun_com==1&&fun_pc==0)
{show_downspread(data_com); }
if(fun_com==1&&fun_pc==0)
{show_middle(data_com); }
// show_static(data_com);
}
if(fun_pc==1)
{
all_pcdata=pc_com(); //检测PC通信进程,
//结束则置PC通信结束标志位show_pcend=1
//同时返回数据通信数据中有效的数据个数
}
if(show_pcend==1&&fun_pc==1) //如果PC正在执行通信,且通信已完成,//则执行此段程序
{
show_pcprocess(all_pcdata); //显示PC通信的数据
}
}
// show_static(show_buffer1); //测试用,临时语句
}
/*=====================PC通信数据处理子程序=====================*/
/*
**************************************************************
**子程序入口参数:无
** 子程序功能:读取PC通信信息,截取其中的数据信息和控制信息
**************************************************************
*/
uint PC_COM(void)
{
uint i,endcount,allcount;
uchar idata *p1;
bit bdata sign;
endcount=0;
p1=show_pc[0][12]; //指向数据区,起始位10字节,空位2字节
for(i=0;i<10;i++)
{
allcount++;
if(*p1==0x0a)
{
endcount++;
if(endcount==10)
{
i=10;
show_pcend=1; //计数标志位0x0a已计满10个,已到数据结尾,//PC通信结束
return(p1-&show_pc[0][12]); // 返回有效显示数据的个数
}
}
else
{
endcount=0;
i=0;
}
if(allcount==652) //已经检测到数组的结尾,仍没有检测到完全的结束//标志位,则退出程序
{i=10; // 数组总容量为662,若倒数第10个仍不是
//结束标志位0x0a,则可断定数据传输有误
fun_pc=0;}
}
}
/*
**********************************************************
**子程序入口:无
**子程序功能:初始化串口,设置波特率\开中断\串口工作模式
**********************************************************
*/
void uart_int(void)
{
TMOD = 0x20; // 定时器1工作于8位自动重载模式, 用于产生波特率
TH1 = 0xfc; // 波特率9600,TH1=252 公式:波特率=(1/n)*(振荡器
//频率/12*[256-TH1])
TL1 = 0xfc;
SCON = 0x50; // 设定串行口工作1方式
PCON&= 0xef; // 波特率不倍增
ES = 1; //开串口中断描方式进行
ET1=0; //禁止定时器1中断
PS=1; //设置串口通信服务程序为高优先级
EA = 1; //开总中断
}
/*
**********************************************************
**子程序入口:无
**子程序功能:串口中断处理函数
**********************************************************
*/
uart_interrupt() interrupt 4 using 2 //串口中断处理程序
{
if(RI) //接引起的中断处理程序
{
show_pcpoint=SBUF; //将数据送入PC通信数据数组show_pc
RI=0;
show_pccount++;
show_pccom=1; //通信标志位
show_pcend=0; //通信结束标志位清零
}
}
/*===============================================================*/
/*=======================显示子程序========================= ====*/
/*===============================================================*/
/*----------------------静态显示子程序--------------------------*/
/*
*****************************************************************
**子程序入口:显示数据的首地址,数据必须是二位数组的格式
**子程序功能:静态显示显示缓冲区show_buffer1中的内容,只能显示一次
******************************************************************
*/
#define DECODE_AD XBYTE[0xbfff] //显示电路行扫描译码电路的地址
void shift_165(uchar *value); //函数声明
void show_static(storep1)
uchar **storep1;
{
uint i,j,k=0;
uchar numcode1=0; //显示电路上面的138译码器
uchar numcode2=0x10; //显示电路下面的138译码器
// storep1=show_buffer1; //子程序不需要形参时,可以默认显示
//显示缓冲区show_buffer1中的内容
for(i=0;i<8;i++) //上下两译码器各运行一次
{
shift_165(storep1[k]); //子程序通过74HC165实现8字节数据信息//并行输入串行输出
//子程序入口:8字节数据的首地址
k++;
DECODE_AD=numcode1;
numcode1++;
}
for(i=0;i<8;i++)
{
shift_165(storep1[k]);
k++;
DECODE_AD=numcode2;
numcode2=numcode2+0x10;
}
}
/*---------------------------显示左移子程序-------------------------*/
/*
**********************************************************************
**子程序入口:需要左移显示的数据的首地址,不可以是显示缓冲区的地址,
** 数据必须是二维数组,字节数暂时定为16*8字节
** num应为二位数组的列数
**子程序功能:显示内容左移,开始部分和结束部分以空白填充;
** 程序只能滚动显示一次
*************************************************************************
*/
void show_left(storep2,num)
uchar xdata **storep2;
uint num;
{
uint i,j,m;
num=num+8; //此时num等于显示缓冲区需要更新的次数,8为屏的宽度
for(i=0;i<16;i++) //对两个显示缓冲区清零
{
for(j=0;j<8;j++)
{
show_buffer1[i][j]=0x00;
show_buffer2[i][j]=0x00;
}
}
TMOD=TMOD&&0xf0; //计数器0工作在方式1,
TMOD=TMOD||0x01; //声明:计数器0只有各个显示子程序可以使用,
//其他子程序只能使用计数器0或计数器2
TH0=(65536-25000)/256; //晶振12MHZ,计数25000次,1S中断40次
TL0=(65536-25000)%256;
EA=1 ; //CPU开中断,定时器0开中断
ET0=1;
PT0=0; //定时器0为中断低优先级
TR0=1; //启动定时器0
showbuf_sign=0; //程序开始时使用show_buffer1显示缓冲区
for(m=0;m<num;m++)
{
if(showbuf_sign==0) //正在显示显示缓冲区show_buffer1中的内容,
//则更新show_buffer2中的内容
{
for(i=0;i<=m;i++) //滚动左移显示移动的第m次,需要移动m列数据
//需要移位的个数,如第一次仅需更新显示缓冲区的最后一位
{
for(j=0;j<16;j++)
{
if(m>num-8)
show_buffer2[j][7-(num-m)]=0x00;
else
show_buffer2[j][7-i]=storep2[j][i];
}
}
}
else
{
for(i=0;i<=m;i++) //滚动左移显示移动的第m次,需要移动m列数据
//需要移位的个数,如第一次仅需更新
//显示缓冲区的最后一位
{
for(j=0;j<16;j++)
{
if(m>num-8)
show_buffer1[j][7-(num-m)]=0x00;
else
show_buffer1[j][7-i]=storep2[j][i];
}
}
//数据完成一次移动
showbuf_sign=~showbuf_sign; //显示区标志位取反,
//显示另外一个显示缓冲区中的内容
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -