人趣体育网

您现在的位置是: 首页 > 体育赛事

文章内容

51单片机排球计分程序_单片机计分牌

tamoadmin 2024-05-25
1.51单片机C语言程序2.求51单片机运动秒表程序,精确度0.1秒!3.51单片机程序编写4.51单片机开发板和绝对式编码器连接测量角度的程序5.51单片机c

1.51单片机C语言程序

2.求51单片机运动秒表程序,精确度0.1秒!

3.51单片机程序编写

4.51单片机开发板和绝对式编码器连接测量角度的程序

5.51单片机c程序

6.求教一个51单片机程序。。(LCD电子时钟)

51单片机排球计分程序_单片机计分牌

sfr P0M1 = 0X93; //这些是预定义寄存器的地址的

sfr P0M0 = 0X94; // 在编译过程中会把 POM1之类的东西变成这些地址

sfr P1M1 = 0X91; //mcu在运行中也是对这些地址操作的

sfr P1M0 = 0X92;

sfr P2M1 = 0X95;

sfr P2M0 = 0X96;

uchar CONT_1; //定义一个常量 作为计数器 使用,类型无符号整形数

P0M1 = 0; //将io口设置为推挽输出

P1M1 = 0; // 下面这些事定义了这些寄存器的初始值

P2M1 = 0; //以免第一次使用这些寄存器时出错

P0M0 = 0XFF;

P1M0 = 0XFF;

P2M0 = 0XFF;

51单片机C语言程序

#include "reg51.h"

sbit start=P3^2; //外部中断0引脚 开始

sbit rst=P3^3; //外部中断1引脚 复位

sbit breakk=P3^4;

sbit led=P3^5;

sbit beep=P3^7;

sbit P30=P3^0;

sbit P31=P3^1;

unsigned char code duanma[]=

{

0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff

};

char time=24;//原来的30s改为24小时

char flag_t=0; // 1秒辅助计时

char now=0; // 0停止 1 计时 2报警 3复位

unsigned int temp=0;//添加此行// 定义一个16位临时变量

unsigned char g=0,s=3,i=0;

void delay(unsigned int n)

{

while(--n);

}

void t0_srv() interrupt 1 using 1

{

TH0=0X3C;

TL0=0XB0;

flag_t++;

if(flag_t>=20){ //20*50ms=1s

flag_t=0;

temp++; //添加此行

if(temp>=3600)//1小时=3600s //添加此行

{

temp=0;//添加此行

time--;

if(time<=0){

beep=0;

led=0;

TR0=0;

now=2;

time=0;

}

}

}

}

void button_start() interrupt 0 using 1 //外部中断0

{

delay(1500);

if(start==0) {

now=1;

TR0=1;

}

else return;

while(start==0);

delay(1500);

}

void button_rst() interrupt 2 using 1

{

delay(1500);

if(rst==0) {

TR0=0;

time=24;//原为time=30;

i=0;

led=1;

beep=1;

now=0;

}

else return;

while(rst==0);

delay(1500);

}

void disp()

{

g=time%10;

s=time/10;

g=duanma[g];

s=duanma[s];

P1=g;

P31=0;

delay(250);

P31=1;

P1=s;

P30=0;

delay(250);

P30=1;

//

}

void key()

{

if(breakk==0)delay(1500);

else return;

if(breakk==0) {

if(now==1){

i++;

if(i%2)TR0=0;

if(!(i%2))TR0=1;

}

}

else return;

while(breakk==0);

delay(1500);

}

main()

{

TMOD=0X01;//定时器0工作在方式1,

EA=1;

IT0=1;

ET0=1;

TH0=0X3C;//在12M 晶振下,定时时间为50ms

TL0=0XB0;

EX0=1;

EX1=1;

//TR0=1;

while(1){

disp();

key();

}

}

求51单片机运动秒表程序,精确度0.1秒!

//你原来的b2,b2都是死循环,这是不行的,只有主函数才可以死循环。

//你的主函数结构也有问题。

//为你增加了一个按键检测的函数。

//下列程序通过了实验测试。

//b1输出的周期大约0.9s。

//b2输出的周期大约0.6s。

//K为触动开关,reg为红灯,bice为绿灯,b1、b2 各为一个方波,

//按第一次触动开关时红灯亮、b1输出,

//按第二次绿灯亮、为b2输出,

//按第三次都关闭.

#include <reg51.h>

#define uint unsigned int

#define uchar unsigned char

uint a;

void b1();

void b2();

sbit t = P1^0;

sbit k = P3^5;

sbit reg = P3^3;

sbit bice = P3^2;

void delay(uchar z)

{

uint x,y;

for(x = z; x > 0; x--) for(y = 110; y > 0; y--);

}

bit key()

{

bit kkk;

kkk = k; //读入按键.

if(kkk == 1) return 0;//没有按下.

delay(5); //延时.

if(k == kkk) return 1;//两次相等.

return 0;

}

void main()

{

while(1) {

P3 = 0xff;

while(!key()); //静等按下第一次.

reg = 0;

bice = 1;

while(!key()) b1(); //没有按下第二次就循环等待.

reg = 1;

bice = 0;

while(!key()) b2(); //没有按下第三次就循环等待.

}

}

void b1()

{

P1 = 0xfe; a = 50000; while(a--);

P1 = 0xff; a = 50000; while(a--);

}

void b2()

{

P1 = 0xfe; a = 30000; while(a--);

P1 = 0xff; a = 30000; while(a--);

}

51单片机程序编写

Count EQU 40H

TimeCount EQU 3FH

;**********************************************************

ORG 0000H

JMP MAIN

ORG 000BH

JMP TIMER0

ORG 0030H

;**********************************************************

MAIN:

CLR P3.6

MOV SP,#60H

MOV TMOD,#01

SETB EA

SETB ET0

SETB TR0

MOV TH0,#4CH ;50ms定时

MOV TL0,#00H

MOV R0,#Count

MOV A,#00H

CLR_1:

MOV @R0,A ;清零

INC R0

CJNE R0,#49H,CLR_1

DISP:

MOV R0,#Count ;获得显示单元首地址

MOV R1,#07FH ;从第一个数码管开始

MOV R2,#08H ;共显示8位数码管

DISP1:

MOV A,@R0 ;获得当前位地址

MOV DPTR,#TABLE ;获得表头

MOVC A,@A+DPTR ;查表获得显示数据

MOV P0,A ;显示数据

MOV P2,R1 ;开始显示当前位

MOV A,R1 ;准备显示下一位

CJNE A,#0BFH,DISP2

CLR P0.7 ;加小数点

DISP2:

RR A

MOV R1,A ;下一位

INC R0 ;取下一个单元地址

LCALL DELAY2MS ;延时 2 MS

DJNZ R2,DISP1 ;重复显示下一个

MOV P2,#0FFH

JMP DISP

RET ;显示完成,返回

;---------------------------------------------------------

;延时子程序

;---------------------------------------------------------

DELAY2MS:

MOV R6,#10

DEL1:

MOV R7,#100

DJNZ R7,$

DJNZ R6,DEL1

RET

;**********************************************************

TIMER0:

PUSH ACC

MOV TH0,#4CH ;50ms定时

MOV TL0,#00H

INC TimeCount

MOV A,TimeCount

CJNE A,#2,T_END

MOV TimeCount,#00H

INC Count ;小数位

MOV A,Count

CJNE A,#10,T_END

MOV Count,#00H

INC Count+1 ;个位

MOV A,Count+1

CJNE A,#10,T_END

MOV Count+1,#00H

INC Count+2 ;十位

MOV A,Count+2

CJNE A,#10,T_END

MOV Count+2,#00H

INC Count+3 ;百位

MOV A,Count+3

CJNE A,#10,T_END

MOV Count+3,#00H

INC Count+4 ;千位

MOV A,Count+4

CJNE A,#10,T_END

MOV Count+4,#00H

INC Count+5 ;万位

MOV A,Count+5

CJNE A,#10,T_END

MOV Count+5,#00H

INC Count+6 ;十万位

MOV A,Count+6

CJNE A,#10,T_END

MOV Count+6,#00H

INC Count+7 ;百万位

MOV A,Count+7

CJNE A,#10,T_END

MOV Count+7,#00H

T_END:

POP ACC

RETI

;**********************************************************

TABLE:

DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H

DB 80H ,90H,0FFH

DB 88H,83H,0C6H,0A1H,86H,8EH

;**********************************************************

END

这是0-9999999.9的秒表程序,你要是4位的话改一下程序或在硬件上之选后四位也可以,

51单片机开发板和绝对式编码器连接测量角度的程序

/*这是用LCD显示所测温度的代码,你参考一下,如果没问题的话,其他的功能你再添加就好了,不难*/

#include<reg52.h>

#include<intrins.h>

#define uint unsigned int

#define uchar unsigned char

#define Nack_number 10

//**************端口定义**************************************************

uchar flag; //LCD控制线接口

sbit RS=P1^0; ? //RS端

sbit RW=P1^1; ? //读写端

sbit LCDE=P2^5; ? //使能端

//mlx90614端口定义

sbit SCK=P2^1; //时钟线

sbit SDA=P2^2; //数据线

//************数据定义****************************************************

bdata uchar flag1; //可位寻址数据

sbit bit_out=flag1^7;

sbit bit_in=flag1^0;

uchar tempH,tempL,err;

//************************** ?LCD1602 ?***********************************

//向LCD写入命令或数据*****************************************************

#define LCD_COMMAND 0 ? //命令

#define LCD_DATA 1 ? // 数据

#define LCD_CLEAR_SCREEN 0x01 ? // 清屏

#define LCD_HOMING ? 0x02 ? // 光标返回原点

//设置显示模式******* 0x08+ ? *********************************************

#define LCD_SHOW 0x04 //显示开

#define LCD_HIDE 0x00 //显示关

#define LCD_CURSOR 0x02 //显示光标

#define LCD_NO_CURSOR 0x00 //无光标

#define LCD_FLASH 0x01 //光标闪动

#define LCD_NO_FLASH 0x00 //光标不闪动

//设置输入模式********** 0x04+ ********************************************

#define LCD_AC_UP 0x02 //光标右移 AC+

#define LCD_AC_DOWN 0x00 ? //默认 光标左移 AC-

#define LCD_MOVE 0x01 ? //画面可平移

#define LCD_NO_MOVE 0x00 ? //默认 画面不移动

//************************** ?mlx90614 ?***********************************

//command mode ?命令模式

#define RamAccess 0x00 //对RAM操作

#define EepomAccess 0x20 //对EEPRAM操作

#define Mode 0x60 //进入命令模式

#define ExitMode 0x61 //退出命令模式

#define ReadFlag 0xf0 //读标志

#define EnterSleep 0xff //进入睡眠模式

//ram address read only RAM地址(只读)

#define AbmientTempAddr 0x03 //周围温度

#define IR1Addr 0x04

#define IR2Addr 0x05

#define LineAbmientTempAddr 0x06 ? //环境温度

/*0x0000 0x4074 16500 0.01/单元

?-40 ? 125*/

#define LineObj1TempAddr 0x07 //目标温度,红外温度

/*0x27ad-0x7fff 0x3559 22610 0.02/单元

-70.01-382.19 ?0.01 ? 452.2*/

#define LineObj2TempAddr 0x08

//eepom address ?EEPROM地址

#define TObjMaxAddr 0x00 //测量范围上限设定

#define TObjMinAddr 0x01 //测量范围下限设定

#define PWMCtrlAddr 0x02 //PWM设定

#define TaRangeAddr 0x03 //环境温度设定

#define KeAddr 0x04 //频率修正系数

#define ConfigAddr 0x05 //配置寄存器

#define SMbusAddr 0x0e //器件地址设定

#define Reserverd1Addr 0x0f //保留

#define Reserverd2Addr 0x19 //保留

#define ID1Addr 0x1c //ID地址1

#define ID2Addr 0x1d //ID地址2

#define ID3Addr 0x1e //ID地址3

#define ID4Addr 0x1f //ID地址4

//************函数声明*****************************************************

void start(); //MLX90614发起始位子程序

void stop(); //MLX90614发结束位子程序

uchar ReadByte(void); //MLX90614接收字节子程序

void send_bit(void); //MLX90614发送位子程序

void SendByte(uchar number); //MLX90614接收字节子程序

void read_bit(void); //MLX90614接收位子程序

void delay(uint N); //延时程序

uint readtemp(void); //读温度数据

void init1602(void); //LCD初始化子程序

void busy(void); //LCD判断忙子程序

void cmd_wrt(uchar cmd); //LCD写命令子程序

void dat_wrt(uchar dat); //LCD写数据子程序

void display(uint Tem); //显示子程序

void Print(uchar *str); //字符串显示程序

//*************主函数*******************************************

void main()

{

uint Tem; //温度变量

SCK=1;

SDA=1;

delay(4);

SCK=0;

delay(1000);

SCK=1;

init1602(); //初始化LCD

while(1)

{

Tem=readtemp(); //读取温度

cmd_wrt(0x01); //清屏

Print(" ?Temperature: "); //显示字符串 ?Temperature: 且换行

display(Tem); //显示温度

Print(" ^C"); //显示摄氏度

delay(10000); //延时再读取温度显示

}

}

void Print(uchar *str) //字符串显示程序

{

while(*str!='\0') //直到字符串结束

{

dat_wrt(*str); //转成ASCII码 ?

str++; //指向下一个字符

}

}

//*********输入转换并显示*********

void display(uint Tem)

{

uint T,a,b;

T=Tem*2;

if(T>=27315) //温度为正

{

T=T-27315; //

a=T/100; //温度整数

b=T-a*100; //温度小数

if(a>=100) //温度超过100度

{

dat_wrt(0x30+a/100); //显示温度百位

dat_wrt(0x30+a%100/10); //显示温度十位

dat_wrt(0x30+a%10); //显示温度个位

}

else if(a>=10) //温度超过10度

{

dat_wrt(0x30+a%100/10); //显示温度十位

dat_wrt(0x30+a%10); //显示温度个位

}

else //温度不超过10度

{

dat_wrt(0x30+a); //显示温度个位

}

dat_wrt(0x2e); //显示小数点

if(b>=10) //温度小数点后第1位数不等于0

{

dat_wrt(0x30+b/10); //显示温度小数点后第1位数

dat_wrt(0x30+b%10); //显示温度小数点后第2位数

}

else //温度小数点后第1位数等于0

{

dat_wrt(0x30); //显示温度小数点后第1位数0

dat_wrt(0x30+b); //显示温度小数点后第2位数

}

}

else //温度为负

{

T=27315-T;

a=T/100;

b=T-a*100;

dat_wrt(0x2d); //显示负号

if(a>=10) //温度低于负10度

{

dat_wrt(0x30+a/10); //显示温度十位

dat_wrt(0x30+a%10); //显示温度个位

}

else //温度高于负10度

{

dat_wrt(0x30+a); //显示温度个位

}

dat_wrt(0x2e); //显示小数点

if(b>=10) //温度小数点后第1位数不等于0

{

dat_wrt(0x30+b/10); //显示温度小数点后第1位数

dat_wrt(0x30+b%10); //显示温度小数点后第2位数

}

else //温度小数点后第1位数等于0

{

dat_wrt(0x30); //显示温度小数点后第1位数0

dat_wrt(0x30+b); //显示温度小数点后第2位数

}

}

}

//************************************

void start(void) //停止条件是 SCK=1时,SDA由1到0

{

SDA=1;

delay(4);

SCK=1;

delay(4);

SDA=0;

delay(4);

SCK=0;

delay(4);

}

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

void stop(void) //停止条件是 SCK=1时,SDA由0到1

{

SCK=0;

delay(4);

SDA=0;

delay(4);

SCK=1;

delay(4);

SDA=1;

}

//---------发送一个字节---------

void SendByte(uchar number)

{

uchar i,n,dat;

n=Nack_number; //可以重发次数

Send_again:

dat=number;

for(i=0;i<8;i++) //8位依次发送

{

if(dat&0x80) ? //取最高位

{

bit_out=1; //发1

}

else

{

bit_out=0; //发0

}

send_bit(); //发送一个位

dat=dat<<1; //左移一位

}

read_bit(); ? //接收1位 应答信号

if(bit_in==1) //无应答时重发

{

stop();

if(n!=0)

{

n--; //可以重发Nack_number=10次

goto Repeat; //重发

}

else

{

goto exit; //退出

}

}

else

{

goto exit;

}

Repeat:

start(); //重新开始

goto Send_again; //重发

exit: ; //退出

}

//-----------发送一个位---------

void send_bit(void)

{

if(bit_out==1)

{

SDA=1; ? //发1

}

else

{

SDA=0; ? //发0

}

_nop_();

SCK=1; ? //上升沿

delay(4);delay(4);

SCK=0;

delay(4);delay(4);

}

//----------接收一个字节--------

uchar ReadByte(void)

{

uchar i,dat;

dat=0; //初值为0

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

{

dat=dat<<1; //左移

read_bit(); //接收一位

if(bit_in==1)

{

dat=dat+1; //为1时对应位加1

}

}

SDA=0; //发送应答信号0

send_bit();

return dat; //带回接收数据

}

//----------接收一个位----------

void read_bit(void)

{

SDA=1; //数据端先置1

bit_in=1;

SCK=1; //上升沿

delay(4);delay(4);

bit_in=SDA; //读数据

_nop_();

SCK=0;

delay(4);delay(4);

}

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

uint readtemp(void)

{

SCK=0;

start(); //开始条件

SendByte(0x00); //发送从地址00

SendByte(0x07); //发送命令

start(); //开始条件

SendByte(0x01); //读从地址00

bit_out=0;

tempL=ReadByte(); //读数据低字节

bit_out=0;

tempH=ReadByte(); //读数据高字节

bit_out=1;

err=ReadByte(); //读错误信息码

stop(); //停止条件

return(tempH*256+tempL);

}

//******************LCD显示子函数***********************

void init1602(void) //初始化LCD

{

cmd_wrt(0x01); //清屏

cmd_wrt(0x0c); //开显示,不显示光标,不闪烁

cmd_wrt(0x06); //完成一个字符码传送后,光标左移,显示不发生移位

cmd_wrt(0x38); //16×2显示,5×7点阵,8位数据接口

}

void busy(void) //LCD忙标志判断

{

flag=0x80; //赋初值 高位为1 禁止

while(flag&0x80) //读写操作使能位禁止时等待 继续检测

{

P0=0xff;

RS=0; //指向地址计数器

RW=1; //读

LCDE=1; //信号下降沿有效

flag=P0; //读状态位 高位为状态

LCDE=0;

}

}

void cmd_wrt(uchar cmd) //写命令子函数

{

LCDE=0;

busy(); //检测 读写操作使能吗

P0=cmd; //命令

RS=0; //指向命令计数器

RW=0; //写

LCDE=1; //高电平有效

LCDE=0;

}

void dat_wrt(uchar dat) //写数据子函数

{

busy(); //检测 读写操作使能吗

LCDE=0;

if(flag==16)

{

RS=0; //指向指令寄存器

RW=0; //写

P0=0XC0; //指向第二行

LCDE=1; //高电平有效

LCDE=0;

}

RS=1; //指向数据寄存器

RW=0; //写

P0=dat; //写数据

LCDE=1; //高电平有效

LCDE=0;

}

//------------延时--------------

void delay(uint n)

{

uint j;

for(j=0;j<n;j++)

{

_nop_();

}

}

51单片机c程序

#include <reg52.h>

#include "inc/delay.h"

#include "inc/hc595.h"

#define uchar unsigned char

#define uint unsigned int

sbit PIN_ROTARY_A = P2^0; //引脚1接口

sbit PIN_ROTARY_B = P2^1; //引脚2接口

sbit PIN_ROTARY_C = P2^2; //按下的接口

sbit PIN_ROTARY_D = P2^3; //按下的接口

//uchar code table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};

/* 存储待发送的数据 */

/* 1->8的段码表 */

code unsigned char ucDis_Segmentcode[16] = {0x3f,0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

/* 位码表 */

code unsigned char ucDis_Bitcode[8] = {0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F};

uchar dis_XS[8] = {0x3f,0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d};

uchar count = 0;

uchar flag;

uchar Last_BMB_status;

uchar Current_BMB_status;

void display()

{

uchar i;

dis_XS[0] = ucDis_Segmentcode[count/100]; //百位

dis_XS[1] = ucDis_Segmentcode[count%100/10]; //十位

dis_XS[2] = ucDis_Segmentcode[count%10]; //个位

if(i < 2)

{

i++;

}

else

{

i = 0;

}

// for (i = 0; i < 3; i++ )

{

Send_Data(dis_XS[i], ucDis_Bitcode[i]);

//PIN_ROTARY_D = 0;

// Delay1ms(1);

}

}

//************************************************

void main()

{

TMOD=0x01; //定时器0,工作方式1

TH0=0xD8;

TL0=0xF0; //给定时器装上初值,10ms中断一次

ET0=1; //打开定时器中断

EA =1; //打开总中断

TR0=1; //启动定时器0

while(1)

{

//display();

Last_BMB_status=PIN_ROTARY_B;

while(!PIN_ROTARY_A) //BMA为低电平时

{

Current_BMB_status = PIN_ROTARY_B;

flag = 1; //标志位置为1说明编码开关被旋转了

}

if(flag == 1)

{

flag = 0; //时刻要注意这一点!给标志位清零

if((Last_BMB_status == 0)&&(Current_BMB_status == 1)) //BMB上升沿表示正转

{

count++;

if(count == 255)

{

count = 0;

}

}

if((Last_BMB_status == 1)&&(Current_BMB_status == 0)) //BMB下降沿表示反转

{

count--;

if(count == 0)

{

count = 255;

}

}

}

}

}

//***********************************************

void timer0() interrupt 1//定时器0的中断服务程序

{

TH0=0xF8; // TH0=0xD8;

TL0=0xF0; //再次装入初值

display(); //每隔10ms显示一次

if(!PIN_ROTARY_C) //按下旋转编码开关则计数清零

{

count = 0;

}

PIN_ROTARY_D = !PIN_ROTARY_D;

}

求教一个51单片机程序。。(LCD电子时钟)

中断函数中的第一个num=60;去掉,放在主程序中。或者声明时赋初值也可以。

void zhongduan1() interrupt 3 {

TH1=(65536-45872)/256;

TL1=(65536-45872)%256;

num2++;

if(num2==20){ num2=0;num--;if(num==0)num=60;shi=num/10;ge=num%10;}}

#include<reg52.h>

#define uint unsigned int

#define uchar unsigned char

uchar a,miao,shi,fen,ri,yue,nian,week,flag,key1n,temp;

#define yh 0x80

#define er 0x80+0x40//液晶屏的与 C51 之间的引脚连接定义

sbit rs=P2^5;

sbit en=P2^7;

sbit rw=P2^6;//如果硬件上 rw 接地,就不用写这句和后面的 rw=0

//DS1302 时钟芯片与 C51 之间的引脚连接定义

sbit IO=P3^6;

sbit SCLK=P3^5;

sbit RST=P3^7;

sbit ACC0=ACC^0;

sbit ACC7=ACC^7;//校时按键与 C51 的引脚连接定义

sbit key1=P3^2;//设置键

sbit key2=P3^3;//加键

sbit key3=P3^4;//减键

uchar code tab1[]={"20//////////"};//年显示的固定字符

uchar code tab2[]={"LOVE ::::::"};//时间显示的固定字符

//延时函数,后面经常调用

void delay(uint xms)//延时函数,有参函数

{

uint x,y;

for(x=xms;x>0;x--)

for(y=110;y>0;y--);

}

/********液晶写入指令函数与写入数据函数,以后可调用**************/

write_1602com(uchar com) //****液晶写入指令函数****

{

rs=0; //数据/指令选择置为指令

rw=0; //读写选择 置为写

P0=com; //送入数据

delay(1);

en=1; //拉高使能端,为制造有效的下降沿做准备

delay(1);

en=0;

//en 由高变低,产生下降沿,液晶执行命令

}

write_1602dat(uchar dat) //***液晶写入数据函数****

{

rs=1; //数据/指令选择置为数据

rw=0; //读写选择置为写

P0=dat; //送入数据

delay(1);

en=1; //en 置高电平,为制造下降沿做准备

delay(1);

en=0; //en 由高变低,产生下降沿,液晶执行命令

}

lcd_init() //***液晶初始化函数****//

{

write_1602com(0x38); //设置液晶工作模式,意思:16*2 行显示,5*7 点阵,8 位数据

write_1602com(0x0c); //开显示不显示光标

write_1602com(0x06); //整屏不移动,光标自动右移

write_1602com(0x01); //清显示

write_1602com(yh+1); //日历显示固定符号从第一行第 1 个位置之后开始显示

for(a=0;a<14;a++)

{

write_1602dat(tab1[a]); //向液晶屏写日历显示的固定符号部分

}

write_1602com(er+1);//时间显示固定符号写入位置,从第 2 个位置后开始显示

for(a=0;a<12;a++)

{

write_1602dat(tab2[a]);//写显示时间固定符号,两个冒号

}

}

/***************DS1302 有关子函数********************/

void write_byte(uchar dat)//写一个字节

{

ACC=dat;

RST=1;

for(a=8;a>0;a--)

{

IO=ACC0;//相当于汇编中的 RRC

SCLK=0;

SCLK=1;

ACC=ACC>>1;

}

}

uchar read_byte() //读一个字节

{

RST=1;

for(a=8;a>0;a--)

{

ACC7=IO;

SCLK=1;

SCLK=0;

ACC=ACC>>1;

}

return (ACC);

}

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

void write_1302(uchar add,uchar dat) //向 1302 芯片写函数,指定写入地址,数据

{

RST=0;

SCLK=0;

RST=1;

write_byte(add);

write_byte(dat);

SCLK=1;

RST=0;

}

uchar read_1302(uchar add) //从 1302 读数据函数,指定读取数据来源地址

{

uchar temp;

RST=0;

SCLK=0;

RST=1;

write_byte(add);

temp=read_byte();

SCLK=1;

RST=0;

return(temp);

}

uchar BCD_Decimal(uchar bcd)//BCD 码转十进制函数,输入 BCD,返回十进制

{

uchar Decimal;

Decimal=bcd>>4;

return(Decimal=Decimal*10+(bcd&=0x0F));

}

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

void ds1302_init()//1302 芯片初始化子函数(2010-01-07,12:00:00,week4)

{

RST=0;

SCLK=0;

write_1302(0x8e,0x00);//允许写,禁止写保护

write_1302(0x8e,0x80);//打开写保护

}

//时分秒显示子函数

void write_sfm(uchar add,uchar dat)//向 LCD 写时分秒,有显示位置加、现示数据,两个参数

{

uchar gw,sw;

gw=dat%10;//取得个位数字

sw=dat/10;//取得十位数字

write_1602com(er+add);//er 是头文件规定的值 0x80+0x40

write_1602dat(0x30+sw);//数字+30 得到该数字的 LCD1602 显示码

write_1602dat(0x30+gw);//数字+30 得到该数字的 LCD1602 显示码

}

//年月日显示子函数

void write_nyr(uchar add,uchar dat)//向 LCD 写年月日,有显示位置加数、显示数据,两个参数

{

uchar gw,sw;

gw=dat%10;//取得个位数字

sw=dat/10;//取得十位数字

write_1602com(yh+add);//设定显示位置为第一个位置+add

write_1602dat(0x30+sw);//数字+30 得到该数字的 LCD1602 显示码

write_1602dat(0x30+gw);//数字+30 得到该数字的 LCD1602 显示码

}

void write_week(uchar week)//写星期函数

{

write_1602com(yh+0x0c);//星期字符的显示位置

switch(week)

{

case 1:write_1602dat('M');//星期数为一时,显示

write_1602dat('o');

write_1602dat('n');break;

case 2:write_1602dat('T');//星期数据为二时显示

write_1602dat('u');

write_1602dat('e');break;

case 3:write_1602dat('W');//星期数据为三时显示

write_1602dat('e');

write_1602dat('d');break;

case 4:write_1602dat('T');//星期数据为四是显示

write_1602dat('h');

write_1602dat('u');break;

case 5:write_1602dat('F');//星期数据为五时显示

write_1602dat('r');

write_1602dat('i');break;

case 6:write_1602dat('S');//星期数据为六时显示

write_1602dat('t');

write_1602dat('a');break;

case 7:write_1602dat('S');//星期数据为日时显示

write_1602dat('u');

write_1602dat('n');break;

}

}

//****************键盘扫描有关函数**********************

void keyscan()

{

if(key1==0)//key1 为功能键(设置键)

{

delay(9);//延时,用于消抖动

if(key1==0)//延时后再次确认按键按下

{

delay(20);

while(!key1);

key1n++;

if(key1n==9)

key1n=1;//设置按键共有秒、分、时、星期、日、月、年、返回,8 个功能循环

switch(key1n)

{

case 1:TR0=0;//关闭定时器

write_1602com(er+0x0E);//设置按键按动一次,秒位置显示光标

write_1602com(0x0f);//设置光标为闪烁

temp=(miao)/10*16+(miao)%10;//秒数据写入 DS1302

write_1302(0x8e,0x00);

write_1302(0x80,0x80|temp);//miao

write_1302(0x8e,0x80);break;

case 2:write_1602com(er+11);//按 2 次 fen 位置显示光标

break;

case 3:write_1602com(er+8);//按动 3 次,shi

break;

case 4:write_1602com(yh+0x0e);//按动 4 次,week

break;

case 5:write_1602com(yh+0);//按动 5 次,ri

break;

case 6:write_1602com(yh+0x07);//按动 6 次,yue

break;

case 7:write_1602com(yh+0x04);//按动 7 次,nian

break;

case 8:write_1602com(0x0c);//按动到第 8 次,设置光标不闪烁

TR0=1;//打开定时器

TR0=1;

temp=(miao)/10*16+(miao)%10;

write_1302(0x8e,0x00);

write_1302(0x80,0x00|temp);//miao 数据写入 DS1302

write_1302(0x8e,0x80);break;

}

}

}

//------------------------------加键 key2----------------------------//

if(key1n!=0)//当 key1 按下以下。再按以下键才有效(按键次数不等于零)

{

if(key2==0)//上调键

{

delay(10);

if(key2==0)

{

delay(20);

while(!key2);

switch(key1n)

{

case 1:miao++;//设置键按动 1 次,调秒

if(miao==60)

miao=0;

write_sfm(0x0D,miao);

temp=(miao)/10*16+(miao)%10;

write_1302(0x8e,0x00);

write_1302(0x80,temp);

write_1302(0x8e,0x80);

write_1602com(er+0x0E);

break;

case 2:fen++;

if(fen==60)

fen=0;

write_sfm(0x0A,fen);

temp=(fen)/10*16+(fen)%10;

write_1302(0x8e,0x00);

write_1302(0x82,temp);

write_1302(0x8e,0x80);

write_1602com(er+11);

break;

case 3:shi++;

if(shi==24)

shi=0;

write_sfm(7,shi);

temp=(shi)/10*16+(shi)%10;

write_1302(0x8e,0x00);

write_1302(0x84,temp);

write_1302(0x8e,0x80);

write_1602com(er+8);

break;

case 4:week++;

if(week==8)

week=1;

write_1602com(yh+0x0C) ;

write_week(week);

temp=(week)/10*16+(week)%10;

write_1302(0x8e,0x00);

write_1302(0x8a,temp);

write_1302(0x8e,0x80);

write_1602com(yh+0x0e);

break;

case 5:ri++;

if(ri==32)

ri=1;

write_nyr(9,ri);

temp=(ri)/10*16+(ri)%10;

write_1302(0x8e,0x00);

write_1302(0x86,temp);

write_1302(0x8e,0x80);

write_1602com(yh+10);

break;

case 6:yue++;

if(yue==13)

yue=1;

write_nyr(6,yue);

temp=(yue)/10*16+(yue)%10;

write_1302(0x8e,0x00);

write_1302(0x88,temp);

write_1302(0x8e,0x80);

write_1602com(yh+7);

break;

case 7:nian++;

if(nian==100)

nian=0;

write_nyr(3,nian);

temp=(nian)/10*16+(nian)%10;

write_1302(0x8e,0x00);

write_1302(0x8c,temp);

write_1302(0x8e,0x80);

write_1602com(yh+4);

break;

}

}

}

//------------------减键 key3,各句功能参照'加键'注释---------------

if(key3==0)

{

delay(10);

//调延时,消抖动

if(key3==0)

{

delay(20);

while(!key3);

switch(key1n)

{

case 1:miao--;

if(miao==-1)

miao=59;

write_sfm(0x0D,miao);

temp=(miao)/10*16+(miao)%10;

write_1302(0x8e,0x00);

write_1302(0x80,temp);

write_1302(0x8e,0x80);

write_1602com(er+0x0E);

break;

case 2:fen--;

if(fen==-1)

fen=59;

write_sfm(10,fen);

temp=(fen)/10*16+(fen)%10;

write_1302(0x8e,0x00);

write_1302(0x82,temp);

write_1302(0x8e,0x80);

write_1602com(er+11);

break;

case 3:shi--;

if(shi==-1)

shi=23;

write_sfm(7,shi);

temp=(shi)/10*16+(shi)%10;

write_1302(0x8e,0x00);

write_1302(0x84,temp);

write_1302(0x8e,0x80);

write_1602com(er+8);

break;

case 4:week--;

if(week==0)

week=7;

write_1602com(yh+0x0C);

write_week(week);

temp=(week)/10*16+(week)%10;

write_1302(0x8e,0x00);

write_1302(0x8a,temp);

write_1302(0x8e,0x80);

write_1602com(yh+0x0e);

break;

case 5:ri--;

if(ri==0)

ri=31;

write_nyr(9,ri);

temp=(ri)/10*16+(ri)%10;//十进制转换成 DS1302 要求的 DCB 码

write_1302(0x8e,0x00);//允许写,禁止写保护

write_1302(0x86,temp);//向 DS1302 内写日期寄存器 86H 写入调整后的日期数据 BCD 码

write_1302(0x8e,0x80);//打开写保护

write_1602com(yh+10);//因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位

break;

case 6:yue--;

if(yue==0)

yue=12;

write_nyr(6,yue);

temp=(yue)/10*16+(yue)%10; //十进制转换成 DS1302 要求的 DCB 码

write_1302(0x8e,0x00); //允许写,禁止写保护

write_1302(0x88,temp); //向 DS1302 内写月份寄存器 88H 写入调整后的月份数据 BCD 码

write_1302(0x8e,0x80); //打开写保护

write_1602com(yh+7); //因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位

break;

case 7:nian--;

if(nian==-1)

nian=99;

write_nyr(3,nian);

temp=(nian)/10*16+(nian)%10; //十进制转换成 DS1302 要求的 DCB 码

write_1302(0x8e,0x00); //允许写,禁止写保护

write_1302(0x8c,temp); //向 DS1302 内写年份寄存器 8cH 写入调整后的年份数据 BCD 码

write_1302(0x8e,0x80); //打开写保护

write_1602com(yh+4); //因为设置液晶的模式是写入数据后,指针自动加一,所以需要光标回位

break;

}

}

}

}

}

void init()

//定时器、计数器设置函数

{

TMOD=0x11;

//指定定时/计数器的工作方式为 3

TH0=0;

//定时器 T0 的高四位=0

TL0=0;

//定时器 T0 的低四位=0

EA=1;

//系统允许有开放的中断

ET0=1;

//允许 T0 中断

TR0=1;

//开启中断,启动定时器

}

//*******************主函数**************************

void main()

{

lcd_init(); //调用液晶屏初始化子函数

ds1302_init(); //调用 DS1302 时钟的初始化子函数

init(); //调用定时计数器的设置子函数

delay(80);

while(1)

//无限循环下面的语句:

{

keyscan();

//调用键盘扫描子函数

}

}

void timer0() interrupt 1 //取得并显示日历和时间

{ //读取秒时分周日月年七个数据(DS1302 的读寄存器与写寄存器不一样)

miao = BCD_Decimal(read_1302(0x81));

fen = BCD_Decimal(read_1302(0x83));

shi = BCD_Decimal(read_1302(0x85));

ri = BCD_Decimal(read_1302(0x87));

yue = BCD_Decimal(read_1302(0x89));

nian=BCD_Decimal(read_1302(0x8d));

week=BCD_Decimal(read_1302(0x8b));

//显示秒、时、分数据:

write_sfm(13,miao); //秒,从第二行第 8 个字后开始显示(调用时分秒显示子函数)

write_sfm(10,fen); //分,从第二行第 5 个字符后开始显示

write_sfm(7,shi); //小时,从第二行第 2 个字符后开始显示

//显示日、月、年数据:

write_nyr(9,ri); //日期,从第二行第 9 个字符后开始显示

write_nyr(6,yue); //月份,从第二行第 6 个字符后开始显示

write_nyr(3,nian); //年,从第二行第 3 个字符后开始显示

write_week(week);

}