搜档网
当前位置:搜档网 › 实验一STC15系列单片机数码管扫描显示和液晶显示

实验一STC15系列单片机数码管扫描显示和液晶显示

/*内部IRC时钟,11.0592MHz;SW1~SW8连BFFFH输入端口,ON为0,OFF为1,SW3SW2SW1为
000=5ms;001=22ms;010=23ms;011=24ms;100=25ms;101=26ms;110=27ms;111=100ms*/
#include<15f2k.h>
#include
#define u8c unsigned char code//存放于代码中的无符号8位字符型缩写定义
#define writecmd XBYTE[0xECFF]//1602写指令端口地址,E正脉冲有下降沿(A12=0),R/W=A9=0写,RS=A8=0写指令
#define readstate XBYTE[0xEEFF]//1602读状态端口地址,E正脉冲有高电平(A12=0),R/W=A9=1读,RS=A8=0读状态
#define writedata XBYTE[0xEDFF]//1602写数据端口地址,E正脉冲有下降沿(A12=0),R/W=A9=0写,RS=A8=1读数据
#define Displayseg XBYTE[0x7FFF]//数码管段码锁存器写端口地址(A15=0)
#define Displaybit XBYTE[0xBFFF]//数码管位码锁存器写端口地址(A14=0)
#define SW XBYTE[0xBFFF]//8位拨码开关输入缓冲读端口地址(A14=0)
#define LCD_CLR 0x01 //清屏,清DDRAM内容为空,AC=00H
#define LCD_MODE 0x38 //模式设置,001DLNF**,DL=1是8位数据接口,N=1两行显示,F=0是5*7点阵字符
#define LCD_ON 0x0c //显示开关控制,00001DCB,D=1开显示,C=0关光标,B=0关闪烁
#define LCD_A_MODE 0x06 //输入方式设置,000001I/DS,I/D=1数据读写后AC自动增1,S=0数据读写后画面不动
char dispbuf[10]; //10个数码管显示段码缓存区数组定义
char Ax_r1=-127,Ax_m1=127,Ax; //加法秒、减法秒及显示用中间变量定义
char Ax_r0=0,Ax_m0=10,i; //加法亚秒、减法亚秒及计算用中间变量定义
char M=0,ms_counter=0; //扫描显示位计数、毫秒计数变量定义
bit new_cycle_flag=0; //扫描显示一周标志
sbit LSIGN=P1^6; //左边的符号位数码管公共端连接引脚,=0可能亮
sbit RSIGN=P1^7; //右边的符号位数码管公共端连接引脚,=0可能亮
sbit LED_FLASH=P3^6; //秒闪烁发光二极管连接引脚,=0亮
sbit BEEP=P3^5; //秒发声蜂鸣器连接引脚,=0响
u8c SG[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0-9段码表
u8c BT[10]={0xfe,0xfd,0xfb,0xf7,0xff,0xef,0xdf,0xbf,0x7f,0xff};//位码表
u8c disp1[16]={'I','n','c','r','e','a','s','e',':',' ',' ',' ',' ','.',' ','s'};//????
u8c disp2[16]={'D','e','c','r','e','a','s','e',':',' ',' ',' ',' ','.',' ','s'};//????
u8c tHtab[8]={0xfe,0xf8,0xf7,0xf7,0xf6,0xf6,0xf6,0xdc};//定时初值高字节表
u8c tLtab[8]={0x33,0x14,0xb8,0x5c,0xff,0xa3,0x47,0x00};//定时初值低字节表
u8c MStab[8]={5,22,23,24,25,26,27,100};//扫描显示周期表(单位:ms)
/***********LCD写指令************/
void LCD_write_cmd(char cmd) //要传递指令
{ while((readstate&0x80)!=0); //查询LCD忙否?BF=1表示忙,循环,直到BF=0退出循环
writecmd=cmd; //写指令,即把指令送[0xE3FF]端口
}
/***********LCD写数据************/
void LCD_write_data(cha

r dat) //要传递数据
{ while((readstate&0x80)!=0); //查询LCD忙否?BF=1表示忙,循环,直到BF=0退出循环
writedata=dat; //写数据,即把数据送[0xE7FF]端口
}
/***********LCD初始化************/
void LCD_init(void) //清屏/8位数据接口/1行/5*7点阵字符/关显示/AC自动增1
{ LCD_write_cmd(LCD_MODE); //写模式设置指令
LCD_write_cmd(LCD_ON); //写显示开关控制指令
LCD_write_cmd(LCD_A_MODE); //写输入方式设置指令
LCD_write_cmd(LCD_CLR); //写清屏指令
}
/***********T0T1初始化***********/
void T0T1_init(void) //10个数码管扫描1周5ms,每个数码管显示0.5ms
{ TMOD=0x21; //T0为方式1,16位定时,T1为方式2,8位自动重装
SCON=0x40; //8位UART波特率可变(2^1*T1溢出率/32)
PCON|=0x80; //第8位SMOD=1
AUXR &= 0x3E; //T0和T1时钟为Fosc/12,即12T,串口1选T1波特率
TH0=tHtab[SW&0x07]; //频率(11059200/12)/(65536-0xfe33)=1999Hz
TL0=tLtab[SW&0x07]; //定时周期1/1999=0.0005002s=0.5ms
TH1=0xfd; //T1溢出率(11059200/12)/(256-253)=307200Hz
TL1=0xfd; //波特率=2*307200/32=19200bps
EA=1; //允许中断
ES=0; //禁止串行通信中断
ET0=1; //允许T0申请中断
TR0=1; //启动T0定时器工作
TR1=1; //启动T1定时器工作
}
/*******1602液晶屏幕初始化*******/
void Display_init(void) //1602显示初始化
{ LCD_write_cmd(0x80); //写指令,设置DDRAM指针AC=0x00
for(i=0;i<16;i++) LCD_write_data(disp1[i]);//往第1行写数据:"Increase: . s"
LCD_write_cmd(0xc0); //写指令,设置DDRAM指针AC=0x40
for(i=0;i<16;i++) LCD_write_data(disp2[i]);//往第2行写数据:"Decrease: . s"
}
/*****加数秒显示缓存区的更新******/
void disp_g(void) //加数秒显示缓存区的更新
{ LCD_write_cmd(0x89); //写指令,设置DDRAM指针AC=0x09
Ax=Ax_r1; //取要显示的物理量
if(Ax<0) //如果加数秒是负数
{ Ax=-Ax; //取绝对值
dispbuf[9]=0x40; //数码管符号位送负号段码
LCD_write_data('-'); //1602符号位送负号的ASCII码
}
else
{ dispbuf[9]=0x00; //数码管符号位送正号段码
LCD_write_data(' '); //1602符号位送正号对应的空的ASCII码
}
i=Ax/100; //计算百位
dispbuf[8]=SG[i]; //数码管对应加数秒的百位更新
LCD_write_data(i+0x30); //往1602写百位的ASCII码
i=Ax/10%10; //计算十位
dispbuf[7]=SG[i]; //数码管对应加数秒的十位更新
LCD_write_data(i+0x3

0); //往1602写十位的ASCII码
i=Ax%10; //计算个位
dispbuf[6]=SG[i]|0x80; //数码管对应加数秒的个位更新
LCD_write_data(i+0x30); //往1602写个位的ASCII码
LCD_write_data('.'); //往1602写小数点的ASCII码
dispbuf[5]=SG[Ax_r0]; //数码管对应加数秒的小数位更新
LCD_write_data(Ax_r0+0x30); //往1602写小数位的ASCII码
}
/*****减数秒显示缓存区的更新******/
void disp_f(void) //减数秒显示缓存区的更新
{ LCD_write_cmd(0xc9); //写指令,设置DDRAM指针AC=0x49
Ax=Ax_m1; //取要显示的物理量
if(Ax<0) //如果减数秒是负数
{ Ax=-Ax; //取绝对值
dispbuf[4]=0x40; //数码管符号位送负号段码
LCD_write_data('-'); //1602符号位送负号的ASCII码
}
else
{ dispbuf[4]=0x00; //数码管符号位送正号段码
LCD_write_data(' '); //1602符号位送正号对应的空的ASCII码
}
i=Ax/100; //计算百位
dispbuf[3]=SG[i]; //数码管对应减数秒的百位更新
LCD_write_data(i+0x30); //往1602写百位的ASCII码
i=Ax/10%10; //计算十位
dispbuf[2]=SG[i]; //数码管对应减数秒的十位更新
LCD_write_data(i+0x30); //往1602写十位的ASCII码
i=Ax%10; //计算个位
dispbuf[1]=SG[i]|0x80; //数码管对应减数秒的个位更新
LCD_write_data(i+0x30); //往1602写个位的ASCII码
LCD_write_data('.'); //往1602写小数点的ASCII码
dispbuf[0]=SG[Ax_m0]; //数码管对应减数秒的小数位更新
LCD_write_data(Ax_m0+0x30); //往1602写小数位的ASCII码
}
/*************主程序*************/
void main(void)
{ LCD_init(); //1602液晶显示模块初始化
Display_init(); //1602液晶屏显示内容初始化
T0T1_init(); //T0、T1初始化程序(11.0592MHz)
do
{ if(new_cycle_flag==1) //扫描显示1周标志存在的话
{ ms_counter+=MStab[SW&0x07];//毫秒计数累加1个扫描周期的时间
if(ms_counter>99) //如果毫秒计数达到了100ms
{ ms_counter-=100; //毫秒计数扣除100ms
Ax_r0+=1; //加法亚秒加1
if(Ax_r0>9) //加法亚秒达到1秒
{ Ax_r0-=10; //加法亚秒有秒进位,加法亚秒扣除1s
Ax_r1+=1; //加法秒加1
if(Ax_r1==127) Ax_r1=-127;//加法秒达到127秒,重置-127
}
Ax_m0-=1; //减法亚秒减1
if(Ax_m0<0) //减法亚秒达到1秒
{ Ax_m0+=10; //减法亚秒有借位,减法亚秒增加1s
Ax_m1-=1; //减法秒减1
if(Ax_m1=

=-127) Ax_m1=127;//减法秒达到-127秒,重置127
LED_FLASH^=1; //秒闪烁,1秒亮,1秒暗
BEEP^=1; //秒发声,1秒响,1秒不响
TI=0; //1s要通信1组数据,清除发送结束状态标志
ES=1; //允许串行中断
SBUF =Ax_r1; //先发送加法秒
}
disp_g(); //每100ms加法秒显示缓存区更新显示信息
disp_f(); //每100ms减法秒显示缓存区更新显示信息
}
new_cycle_flag=0; //扫描显示1周标志清0
}
}while(1); //死循环
}
/*********T0中断服务程序*********/
void t0() interrupt 1 using 1 //每次中断均要进行扫描显示处理
{ TH0=tHtab[SW&0x07]; //T0时间常数高字节重装
TL0=tLtab[SW&0x07]; //T0时间常数低字节重装
if(M==10) //扫描1周到了吗?
{ new_cycle_flag=1; //到了,置扫描显示1周标志
M=0; //M清0
}
LSIGN=1; //关闭左边符号位显示
RSIGN=1; //关闭右边符号位显示
Displaybit=0xff; //关闭8个数码管的显示
Displayseg=dispbuf[M]; //查显示缓存表送数显的段端口
Displaybit=BT[M]; //查位码表送数显的位端口
if(M==4)RSIGN=0; //扫描到右边符号位则该位显示
if(M==9)LSIGN=0; //扫描到左边符号位则该位显示
M++; //修改下一次的显示位
}
/******串行通信中断服务程序*******/
void txd() interrupt 4 using 2 //每100ms发2字节,第2字节靠发送结束中断完成
{ TI=0; //清除发送结束状态标志
ES=0; //发送到最后1个字节,禁止发送结束中断
SBUF =Ax_m1; //发送报文第2字节,即减法秒
}

相关主题