S_SET BIT P3.4 秒增加1按钮位
M_SET BIT P3.5 分增加1按钮位
H_SET BIT P3.7 小时增加1按钮位
SECONDEQU 30H 秒计数值变量
MINUTEEQU 31H 分计数值变量
HOUR EQU 32H 小时计数值变量
TCNT EQU 34H 1秒定时计数器
ORG 00H 起始地址
JMP START
ORG 0BH Timer0中断向量地址
JMP INT_T0
START:
MOVDPTR,#TABLE 装七段数码管段码数据表TABLE
MOVHOUR,#0 计数值全部清0
MOVMINUTE,#0
MOVSECOND,#0
MOVTCNT,#0
MOVTMOD,#01H Timer 0作定时器,模式1
MOVTH0,#(65536-50000)/256定时50毫秒
MOVTL0,#(65536-50000)MOD 256
MOVIE,#82H中断使能
SETBTR0 启动Timer 0
以下是判断秒、分、小时增加1按钮是否被按下
A1:
CALL DISPLAY
JNB S_SET,S1 判断秒按钮
JNB M_SET,S2判断分按钮
JNB H_SET,S3 判断小时按钮
JMP A1循环检测
S1:
CALL DELAY去抖动
JBS_SET,A1
INC SECOND 秒位计数值加1
MOVA,SECOND A=SECOND
CJNEA,#60,J0 判断是否到60秒
MOVSECOND,#0 如果到了就清0秒位计数值
JMP K1跳到K1段
S2:
CALL DELAY
JBM_SET,A1
K1:
INC MINUTE 分位计数值加1
MOVA,MINUTE A=MINUTE
CJNEA,#60,J1 判断是否到60分
MOVMINUTE,#0 如果到了就清0分位计数值
JMP K2
S3:
CALL DELAY
JBH_SET,A1
K2:
INC HOUR 小时计数值加1
MOVA,HOUR A=HOUR
CJNEA,#24,J2 判断是否到24小时
MOVHOUR,#0 如果到了就清0秒、分、小时位计数值
MOVMINUTE,#0
MOVSECOND,#0
JMP A1
以下程序等待秒、分、小时按钮放开
J0:
JBS_SET,A1
CALL DISPLAY
JMP J0
J1:
JBM_SET,A1
CALL DISPLAY
JMP J1
J2:
JBH_SET,A1
CALL DISPLAY
JMP J2
Timer0中断服务子程序, 进行秒、分、小时的计时
INT_T0:
MOVTH0,#(65536-50000)/256装计数初始值
MOVTL0,#(65536-50000)MOD 256
INC TCNT 1秒计数器增加1
MOVA,TCNTA=TCNT
CJNEA,#20,RETUNE 计时1秒
INC SECOND 秒计数器增加1
MOVTCNT,#0 清零TCNT
MOVA,SECOND A=SECOND
CJNEA,#60,RETUNE 计时60秒
INC MINUTE 分计数器增加1
MOVSECOND,#0 清零秒
MOVA,MINUTE A=MINUTE
CJNEA,#60,RETUNE 计时60分
INC HOUR 小时计数器增加1
MOVMINUTE,#0 清零分
MOVA,HOUR A=HOUR
CJNEA,#24,RETUNE 计时24小时
MOVHOUR,#0 秒、分、小时计数值清0
MOVMINUTE,#0
MOVSECOND,#0
MOVTCNT,#0
RETUNE:
RETI中断服务子程序结束
以下为七段数码管显示的子程序
DISPLAY:
MOVA,SECOND A=SECOND,显示秒
MOVB,#10B=10
DIV AB A除以B
MOV P2,#00100000B 使能秒的十位
MOVC A,@A+DPTR七段数码管段码数据装入A
MOVP0,A 从P0口输出
CALL DELAY
ORL P2,#0FFH 熄灭七段数码管
MOVA,B A=B
MOV P2,#00000000B 使能秒的个位
MOVC A,@A+DPTR七段数码管段码数据装入A
MOVP0,A 从P0口输出
CALL DELAY
ORL P2,#0FFH 熄灭七段数码管
MOVA,MINUTE A=MINUTE,显示分
MOVB,#10B=10
DIV AB A除以B
MOV P2,#01100000B 使能分的十位
MOVC A,@A+DPTR七段数码管段码数据装入A
MOVP0,A 从P0口输出
CALL DELAY
ORL P2,#0FFH 熄灭七段数码管
MOVA,B A=B
MOV P2,#01000000B 使能分的个位
MOVC A,@A+DPTR七段数码管段码数据装入A
MOVP0,A 从P0口输出
CALL DELAY
ORL P2,#0FFH 熄灭七段数码管
MOVA,HOUR A=HOUR,显示小时
MOVB,#10B=10
DIV AB A除以B
MOV P2,#10100000B 使能小时的十位
MOVC A,@A+DPTR七段数码管段码数据装入A
MOVP0,A 从P0口输出
CALL DELAY
ORL P2,#0FFH 熄灭七段数码管
MOVA,B A=B
MOV P2,#10000000B 使能小时的个位
MOVC A,@A+DPTR七段数码管段码数据装入A
MOVP0,A 从P0口输出
CALL DELAY
ORL P2,#0FFH 熄灭七段数码管
RET
TABLE: 七段数码管显示码表
DB 40H,79H,24H,30H,19H
DB 12H,02H,78H,00H,10H
DELAY: 延时子程序
MOVR6,#2
D1:
MOVR7,#250
DJNZR7,$
DJNZR6,D1
RET
END
#include <reg51.h>#define uchar unsigned char //定义unsigned int为uint
#define uint unsigned int //定义unsigned uchar为uchar
sbit LCD_RS = P2^0
sbit LCD_RW = P2^1
sbit LCD_EN = P2^2
sbit D_SDA = P2^6 //定义74HC164数据线为P2.6端口
sbit D_SCL = P2^7 //定义74HC164数据线为P2.7端口
sbit CLK = P1^3 /*实时时钟时钟线引脚 */
sbit IO = P1^4 /*实时时钟数据线引脚 */
sbit RST = P1^5 /*实时时钟复位线引脚 */
sbit ACC0 = ACC^0
sbit ACC7 = ACC^7
uchar time[8] = {0x50,0x30,0x19,0x30,0x12,0x06,0x06}
//========= 延时函数 ============
//延时时间以1ms为单位
//s决定延时时间长短
void delay_ms(uint s)
{
uint x
for(ss>0s--)
{
x = 200
while(x--)
}
}
//========= 送出一个字节给74HC164(实现串并转换) ==========
void send_out(unsigned char out)//传送一个字节8位
{
uchar i
D_SCL = 0
for (i=8i>=1i--)
{
D_SDA = out&0x80 //送数据到数据口
D_SCL = 1 //时钟线置1
D_SCL = 0 //送一时钟
out<<=1 //左移
}
}
//========= 写命令函数 ==========
void lcd_wcmd(uchar cmd)
{
LCD_RS = 0
LCD_RW = 0
LCD_EN = 0
send_out(cmd)
LCD_EN = 1
LCD_EN = 0
}
//========= 写数据函数 ==========
void lcd_wdat(uchar dat)
{
LCD_RS = 1
LCD_RW = 0
LCD_EN = 0
send_out(dat)
LCD_EN = 1
LCD_EN = 0
}
//========= LCD初始化函数 ==========
void lcd_init()
{
lcd_wcmd(0x38)
delay_ms(1)
lcd_wcmd(0x0c) //显示开,关光标
delay_ms(1)
lcd_wcmd(0x06) //向右移动光标
delay_ms(1)
lcd_wcmd(0x01) //清除LCD显示屏
delay_ms(1)
}
//========== 往DS1302写入1Byte数据 (内部函数) =============
void w_byte(uchar dat)
{
uchar i
for(i=8i>0i--)
{
IO = dat &0x01
CLK = 1
CLK = 0
dat = dat >>1
}
}
//======== 从DS1302读取1Byte数据 (内部函数) ===================
uchar r_byte(void)
{
uchar i
for(i=8i>0i--)
{
ACC = ACC >>1
ACC7 = IO
CLK = 1
CLK = 0
}
return(ACC)
}
//========== 指定地址往DS1302写入1Byte数据 (内部函数) =============
void write_byte(uchar addr, uchar dat)
{
RST = 0
CLK = 0
RST = 1
w_byte(addr)
w_byte(dat)
CLK = 1
RST = 0
}
//========== 指定地址往DS1302读1Byte数据 (内部函数) =============
uchar read_byte(uchar addr)
{
uchar ucData
RST = 0
CLK = 0
RST = 1
w_byte(addr)
ucData = r_byte()
CLK = 1
RST = 0
return(ucData)
}
//============ 设置ds1302日期和时间 =============
void write_ds1302(uchar *p)
{
uchar i
uchar addr = 0x80
write_byte(0x8e,0x00)// 控制命令,WP=0,写 *** 作
for(i =7i>0i--)
{
write_byte(addr,*p) // 秒 分 时 日 月 星期 年
p++
addr +=2
}
write_byte(0x8e,0x80) // 控制命令,WP=1,写保护
}
//============ 读ds1302当前日期和时间 =============
void read_ds1302(uchar *p)
{
uchar i
uchar addr = 0x81
for (i=0i<7i++)
{
*p = read_byte(addr) //格式为: 秒 分 时 日 月 星期 年
addr += 2
p++
}
}
//============ 显示函数 ===================
void lcd_disp()
{
uchar addr = 4
lcd_wcmd(0x80 + addr)
lcd_wdat(((time[2]>>4)&0x0f)+0x30)//显示小时
addr++
lcd_wcmd(0x80 + addr)
lcd_wdat((time[2]&0x0f)+0x30)
addr++
lcd_wcmd(0x80 + addr)
lcd_wdat(':')//显示":"
addr++
lcd_wcmd(0x80 + addr)
lcd_wdat(((time[1]>>4)&0x0f)+0x30)//显示分
addr++
lcd_wcmd(0x80 + addr)
lcd_wdat((time[1]&0x0f)+0x30)
addr++
lcd_wcmd(0x80 + addr)
lcd_wdat(':')//显示":"
addr++
lcd_wcmd(0x80 + addr)
lcd_wdat(((time[0]>>4)&0x0f)+0x30)//显示秒
addr++
lcd_wcmd(0x80 + addr)
lcd_wdat((time[0]&0x0f)+0x30)
addr = 2
lcd_wcmd(0xc0 + addr) //在第二行显示年月日和星期
lcd_wdat('2')//显示2
addr++
lcd_wcmd(0xc0 + addr)
lcd_wdat('0')//显示0
addr++
lcd_wdat(((time[6]>>4)&0x0f)+0x30)//年
addr++
lcd_wcmd(0xc0 + addr)
lcd_wdat((time[6]&0x0f)+0x30)
addr++
lcd_wcmd(0xc0 + addr)
lcd_wdat(' ')
addr++
lcd_wcmd(0xc0 + addr)
lcd_wdat(((time[4]>>4)&0x0f)+0x30)//显示月
addr++
lcd_wcmd(0xc0 + addr)
lcd_wdat((time[4]&0x0f)+0x30)
addr++
lcd_wcmd(0xc0 + addr)
lcd_wdat(' ')
addr++
lcd_wcmd(0xc0 + addr)
lcd_wdat(((time[3]>>4)&0x0f)+0x30)//显示日
addr++
lcd_wcmd(0xc0 + addr)
lcd_wdat((time[3]&0x0f)+0x30)
addr++
lcd_wcmd(0xc0 + addr)
lcd_wdat(' ')
addr++
lcd_wcmd(0xc0 + addr)
lcd_wdat((time[5]&0x0f)+0x30)//显示星期
}
//=========== 主函数 ===============
void main()
{
lcd_init() // 初始化LCD
write_ds1302(time)
while(1)
{
read_ds1302(time) //读DS1302数据
lcd_disp()//LCD显示
delay_ms(500) //延时0.5秒
}
}
这是一个电子时钟,在LCD1602上显示,时钟芯片是DS1302
================================================================功能:本程序实现P0口的对数码管动态显示秒表的分、秒、1/100秒;
计时程序由中断服务程序实现,采用定时计数器T0工作方式1;
P2口实现对数码管的片选功能
================================================================
==========================初始化================================
SHUCHUEQUP2 定义P0口为输出口
PIANXUAN EQUP1定义P2口为片选口
MIAO EQU30H
FEN EQU31H
MIAO0 EQU32H
SHUZIEQU33H
C_0 BIT20H.0
======================系统程序开始==============================
ORG 00H
LJMP START
ORG 03H
LJMP ON_OFF
ORG 0BH
LJMP T0_1
ORG 13H
LJMP RESET
ORG 30H
START:
CALL INIT
SETB C_0
MOVMIAO,#00
MOVMIAO0,#00
MOVFEN,#00
MOVDPTR,#TAB
MOV R2,#5
MAIN:
JNBC_0,$
CLRC_0
LL: CALL DISPLAY
CALL SHIJIAN
JMPMAIN
========================时间子程序=============================
输入:"30H、31H、32H"
输出:无
实现的功能:分、秒、百分之秒的计算。
===============================================================
SHIJIAN:
DJNZR2,TIAOCHU
MOV R2,#5
INC MIAO0
MOV R3,MIAO0
CJNER3,#100,TIAOCHU
MOV MIAO0,#00
INC MIAO
MOV R3,MIAO
CJNER3,#60,TIAOCHU
MOV MIAO,#00
INC FEN
MOV R3,FEN
CJNER3,#60,TIAOCHU
MOV FEN,#00
TIAOCHU:RET
========================显示子程序=============================
输入:"A"
输出:"P2口"
实现的功能:显示秒、分、百分之妙
===============================================================
DISPLAY:MOV SHUZI,MIAO0
CALL JISUAN
MOVC A,@A+DPTR
MOV SHUCHU,A 显示十位
MOV PIANXUAN,#10H片选
CALL DELAY
MOV PIANXUAN,#00H
MOV A,B
MOVC A,@A+DPTR
MOV SHUCHU,A 显示个位
MOV PIANXUAN,#20H片选
CALL DELAY延时
MOV PIANXUAN,#00H
MOV SHUZI,MIAO
CALL JISUAN
MOVC A,@A+DPTR
MOV SHUCHU,A 显示十位
MOV PIANXUAN,#04H片选
CALL DELAY
MOV PIANXUAN,#00H
MOV A,B
MOVC A,@A+DPTR
MOV SHUCHU,A 显示个位
MOV PIANXUAN,#08H片选
CALL DELAY延时
MOV PIANXUAN,#00H
MOV SHUZI,FEN
CALL JISUAN
MOVC A,@A+DPTR
MOV SHUCHU,A 显示十位
MOV PIANXUAN,#01H片选
CALL DELAY
MOV PIANXUAN,#00H
MOV A,B
MOVC A,@A+DPTR
MOV SHUCHU,A 显示个位
MOV PIANXUAN,#02H片选
CALL DELAY延时
MOV PIANXUAN,#00H
RET
========================计算子程序=============================
输入:30H
输出:"A和B"
实现的功能:把33H中的数据十位和个位分离出来
===============================================================
JISUAN:MOV A,SHUZI 数据放在A中
MOV B,#10除数放在B中
DIV AB 商放在A中,余数放在B中
RET
====================复位中断服务程序============================
输入;无
输出: 无
实现的功能:把30H、31H、32H中的数据清零。
================================================================
RESET:PUSH ACC
MOV 30H,#00H
MOV 3H,#00H
MOV 32H,#00H
CALL DELAY
POP ACC
RETI
====================启停中断服务程序============================
输入;无
输出: 无
实现的功能:关闭定时器
================================================================
ON_OFF:CPLTR0
CALL DELAY
RETI
====================定时中断0服务子程序========================
输入:无
输出:无
实现的功能:实现定时20MS,影响标中断志位C_0
===============================================================
T0_1:MOVTL0,50H 设置定时初值
MOVTH0,51H
SETB C_0定时标志位清0
RETI
========================中断设置子程序=========================
输入:无
输出:无
实现的功能:初始化设置定时器,设置初值,开中断0、中断1,定时器0.
===============================================================
INIT:MOVTMOD,#01H 定时器0工作方式1
MOVDPTR,#65536-20000
MOV50H,DPL
MOV51H,DPH
MOVTL0,50H设置定时初值
MOVTH0,51H
MOVIE,#87H 开定时器中断0
MOVTCON,#15H
RET
======================延时程序==================================
输入;无
输出: 无
实现的功能:延时一段时间
================================================================
DELAY:MOV R6,#80
L7:MOV R5,#60
L8:DJNZ R5,$
DJNZ R6,L7
RET
======================共阳查表数据==============================
TAB:DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H
===========================结束=================================
END
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)