课设作业
代码写得不好,只是记录一下
基于AT89C51的电子时钟系统,通过配置定时器实现电子时钟,秒表计时,记录年月日等。
可以通过按键调整时间,年月日
State——修改对象
m:秒 f:分 s:时 t:天 y:月 n:年 j:计时模式
Clock——时间
CountT——秒表计时
以仿真界面看,除RST按键外,从上到下,分别为按键1,按键2,按键3
按键1:增加
按键2:减少
按键3:切换修改对象
电路仿真:
相关代码:
主函数
#include "REGX52.H"
#include "LCDLM041L.h"
#include "key.h"
#include "Delay.h"
#include "sounder.h"
sbit sounder=P2^0;
unsigned char KeyNum;
//-----------------
//中断初始化
//-----------------
void Timer0_Init(){
//TMOD=TMOD&0XF0;//高四位保持不变,第四位清零
//TMOD=TMOD|0X01;//设置定时器模式 M1=0 M0=1
//TF0=0;//标志位
//TR0=1;//是定时器T0的定时器启动位
//TL0=0X18;//TX0的高8位 除以256相当于256进制 对65535-1000求商 1000us = 1ms
//TH0=0XFC;//TX0的低8位 对65535-1000取余
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0xF0; //设置定时初值
TH0 = 0xD8; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
//中断部分设置
ET0=1;
EA=1;
PT0=0;
}
//修改时间
unsigned char State = 'm';//修改项 初始化为秒 m - 秒 f - 分 s - 时 t - 天 y - 月 n - 年 j - 计时功能
unsigned char Year=22,Mon=2,Day=6;
unsigned char Sec=30,Min=2,Hour=12;
unsigned char CouSec=0,CouMin=0,CouMs=0;
//时间判断函数
void Judge(){
if(Sec>=60){
Sec=0;
Min++;
}
if(Min>=60){
Min=0;
Hour++;
}
if(Hour>=24){
Hour=0;
Day++;
}
if(((Mon==1||Mon==3||Mon==5||Mon==7||Mon==8||Mon==10||Mon==12)&&Day>31)||(Mon==4||Mon==6||Mon==9||Mon==11)&&Day>30){
Day=1;
Mon++;
}
if(Mon>12){
Mon=1;
Year++;
}
}
//平润年判断
void JudgeYear(){
//闰年
if(Year%4==0&&Mon==2){
if(Day>29){
Day=0;
Mon++;
}
}
//平年
else if(Year%4!=0&&Mon==2){
if(Day>28){
Day=1;
Mon++;
}
}
}
void Motify(){
if(Day==0)Day=1;
}
unsigned char CountFlag=0;//计时器标志符 1是启动 2是暂停
unsigned char FlagHour=0;
void JudgeHour(){
if(Min==0&&Sec==0)
Sounder();
}
void main(){
Timer0_Init();
LCD_Init();
LCD_Init();
LCD_ShowString(1,1,"Clock:");
LCD_ShowString(2,1,"CountT:");
LCD_ShowString(3,1,"State:");
LCD_ShowChar(1,10,':');
LCD_ShowChar(1,13,':');
LCD_ShowChar(2,10,':');
LCD_ShowChar(2,13,':');
LCD_ShowChar(4,6,'-');
LCD_ShowChar(4,9,'-');
sounder =~sounder;
while(1){
LCD_ShowNum(4,4,Year,2);
LCD_ShowNum(4,7,Mon,2);
LCD_ShowNum(4,10,Day,2);
LCD_ShowNum(1,14,Sec,2);
LCD_ShowNum(1,11,Min,2);
LCD_ShowNum(1,8,Hour,2);
LCD_ShowNum(2,14,CouMs,2);
LCD_ShowNum(2,11,CouSec,2);
LCD_ShowNum(2,8,CouMin,2);
LCD_ShowChar(3,7,State);
JudgeHour();
JudgeYear();
Motify();
Judge();
KeyNum=Key();
if(KeyNum==3){
if(State=='m')
State='f';
else if(State=='f')
State='s';
else if(State=='s')
State='t';
else if(State=='t')
State='y';
else if(State=='y')
State='n';
else if(State=='n')
State='j';
else if(State=='j')
State='m';
}
if(KeyNum==1){
if(State=='m')
Sec++;
else if(State=='f')
Min++;
else if(State=='s')
Hour++;
else if(State=='t')
Day++;
else if(State=='y')
Mon++;
else if(State=='n')
Year++;
else if(State=='j')
CountFlag=~CountFlag;
}
if(KeyNum==2){
if(State=='m'&&Sec!=0){
Sec--;
}
else if(State=='m'&&Sec==0){
Sec=59;
}
else if(State=='f'&&Min!=0){
Min--;
}
else if(State=='f'&&Min==0){
Min=59;
}
else if(State=='s'&&Hour!=1){
Hour--;
}
else if(State=='s'&&Hour==1){
Hour=12;
}
else if(State=='t'){
Day--;
if(Day<1&&Mon!=2&&(Mon==1||Mon==3||Mon==5||Mon==7||Mon==8||Mon==10||Mon==12))Day=31;
else if(Day<1&&Mon!=2&&(Mon==4||Mon==6||Mon==9||Mon==11))Day=30;
else if(Day<1&&Mon==2&&Year%4==0)Day=29;
else if(Day<1&&Mon==2&&Year%4!=0)Day=28;
}
else if(State=='y')
Mon--;
else if(State=='n')
Year--;
else if(State=='j'){
CouMin=0;
CouSec=0;
CouMs=0;
}
}
//sounder=~sounder;
//DelayXms(5);
//Sounder();
}
}
unsigned int T0Count;
void Timer0_Routine() interrupt 1{ //若是500ms 则可以用50ms*10 产生10次50ms的计时
TL0 = 0xF0; //设置定时初值
TH0 = 0xD8; //设置定时初值 z 55536 =0xD8F0
T0Count++;
if(CountFlag!=0){
CouMs++;
if(CouMs>=100){
CouSec++;
CouMs=0;
if(CouSec>=60){
CouMin++;
CouSec=0;
}
}
}
if(T0Count>=100){ //100 * 10ms = 1s 如果发现比实际时间慢 可以特意调低累计次数T0Count
T0Count=0;
Sec++;
}
}
定时器计算部分在作业验收时已经修改,跟代码不相符,具体计算方法可以查找其他博主的文章。
LM041L显示部分
#include "REGX52.H"
#include "LCDLM041L.h"
sbit LCD_RS=P3^5 ;
sbit LCD_RW=P3^6 ;
sbit LCD_E=P3^7 ;
#define LCD_DataPort P0
//-----------------
//写延迟函数
//-----------------
void LCD_Delay(){ //12MHz 1ms
unsigned char i,j;
i = 2;
j = 239;
do
{
while (--j);
}while(--i);
}
//-----------------
//写命令
//-----------------
void LCD_WriteCommand(unsigned char Command){
LCD_RS = 0;
LCD_RW = 0;
LCD_DataPort = Command;
//因为传输时序 需要延时一段时间
LCD_E = 1;
LCD_Delay();
LCD_E = 0;
LCD_Delay();
}
//-----------------
//写数据?
//-----------------
void LCD_WriteData(unsigned char Data){
LCD_RS = 1;
LCD_RW = 0;
LCD_DataPort = Data;
//因为传输时序 需要延时一段时间
LCD_E = 1;
LCD_Delay();
LCD_E = 0;
LCD_Delay();
}
//-----------------
//LCD初始化
//-----------------
void LCD_Init(void){
LCD_WriteCommand(0x38); //00111000
LCD_WriteCommand(0x0c);
LCD_WriteCommand(0x06);
LCD_WriteCommand(0x01);
LCD_WriteCommand(0x38);
LCD_Delay();
}
//-----------------
//光标位置
//-----------------
void LCD_SetCursor(unsigned char Line ,unsigned char Column){
if (Line == 1){
LCD_WriteCommand(0x80|(Column-1));//第一行
}
else if(Line == 2){
LCD_WriteCommand(0x80|((Column-1)+0xc0));//第二行
}
else if(Line == 3){
LCD_WriteCommand(0x80|((Column-1)+0x90));//第三行
}
else{
LCD_WriteCommand(0x80|((Column-1)+0xd0));//第四行
}
}
//-----------
//显示字符
//-----------
void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char){
LCD_SetCursor(Line,Column);
LCD_WriteData(Char);
}
//-----------
//显示字符串
//-----------
void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char *String){
unsigned char i;
LCD_SetCursor(Line,Column);
for(i=0;String[i]!='\0';i++){
LCD_WriteData(String[i]);
}
}
//----------
//次方计算函数
//----------
int LCD_Pow(int x, int y){
unsigned char i;
int Result = 1;
for(i=0;i<y;i++){
Result *= x;
}
return Result;
}
//-----------
//显示数字
//-----------
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length){
unsigned char i;
LCD_SetCursor(Line,Column);
for (i=Length;i>0;i--){
LCD_WriteData('0'+Number/LCD_Pow(10,i-1)%10);
}
}
按键部分:
#include "REGX52.H"
#include "KEY.H"
#include "Delay.h"
unsigned char Key(){
unsigned char KeyNumber = 0;
if (P1_0==0){
Delay20us();
while(P1_0==0);
Delay20us();
KeyNumber = 1;
}
if (P1_1==0){
Delay20us();
while(P1_1==0);
Delay20us();
KeyNumber = 2;
}
if (P1_2==0){
Delay20us();
while(P1_2==0);
Delay20us();
KeyNumber = 3;
}
return KeyNumber;
}
如有建议或错误,欢迎各位大佬指正。