单片机电子表程序

单片机电子表程序,第1张

汇编如下:

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


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7692663.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-08
下一篇 2023-04-08

发表评论

登录后才能评论

评论列表(0条)

保存