农历转换程序模块,c51和a51文件均可调用,有c51调用示范,汇编程序
可以屏蔽闰月的“节日”,可以辨别腊月小月29日的除夕。
农历天干、地支纪年,有生肖。
新建工程,然后直接将两个文件(其中nongli.c是示范文件)加入源代码组即可。
单片机源程序如下:
- //此文件经2013.04.14 00:00调试正常,可以通过c程序调用,
- //输入: 变量 YEAR,MONTH,DATE(年、月、日,16进制码)
- //输出:位变量CHUXI(腊月29或30除夕标志),=0是小月,腊月29日是除夕。
- //输出:位变量FLAG_Y(闰月标志,判农历节日用)FLAG_Y=0,是后月,后月无节日
- //输出: TIANGAN,DIZHI(天干、地支、生肖)
- //输出: NO_YEAR,NO_MONTH,NO_DATE(农历年、月、日),(16进制码)
- // FLAG_Y,闰月标志,CHUXI,腊月小时,腊月29是除夕标志,
- // 以上变量和子程序名均为大写,c51引用时应注意。
- ;**************************************************************
- ;转换农历子程序
- ;把已计算出的当年已过天数,从元旦对应的农历日期开始,减去29
- ;天,再减去大小月标志,如够减,[判断现存的农历月和当年的闰月
- ;是否相等,如相等就减1(下面加1,保持不变)],月数加1,
- ;再一次循环,直到不够减,余数做日,退出子程序(本次转换结束)
- ;*******************************************************
- PUBLIC YEAR, MONTH,DATE //外部可以调用的变量(公共的)输入的
- PUBLIC NO_YEAR,NO_MONTH,NO_DATE,TIANGAN,DIZHI //外部可以调用的变量(公共的)输出的
- PUBLIC CHUXI,FLAG_Y //外部可以调用的位变量(公共的)输出的
- PUBLIC ZHUAN_H //外部可以调用的子程序(公共的)
- ZH_RAM SEGMENT DATA ;定义一个段名,ZH_RAM是段名,在data区间,这种格式是让编译器统一安排内存使用
- ;作为定义变量的空间段
- ZH_ROM SEGMENT CODE ;定义一个段名,KEYP是段名, 在CODE区间,作为本程序的存储空间
- //ZH_BIAO SEGMENT BDATA
- RSEG ZH_RAM ;定义ZH_RAM段的使用
- YEAR: DS 1 //在编译连接整个工程时,给以下各变量保留一个字节的DATA空间
- MONTH: DS 1
- DATE: DS 1
- NO_YEAR: DS 1
- NO_MONTH: DS 1
- NO_DATE: DS 1
- NO_MONTH_R: DS 1 ;闰月
- TIANGAN: DS 1
- DIZHI: DS 1
- BSEG AT 00H ;定义位地址,下面的位地址从 00H开始(指定绝对地址,也可以不指定)
- RUNYUEBIT: DBIT 1 ;农历闰月标志
- CHUXI: DBIT RUNYUEBIT+1 ;定义除夕标志,区分腊月大小月
- BZ_RUN_NIAN: DBIT RUNYUEBIT+2 ;定义闰年标志
- FLAG_Y: DBIT RUNYUEBIT+3 ;闰月标志,写农历节日用(闰月无节日)
- RSEG ZH_ROM //以下的代码使用ZH_ROM段
- ZHUAN_H:
- PUSH ACC
- PUSH DPH
- PUSH DPL
- PUSH 03H
- PUSH 04H
- PUSH 05H
- PUSH 06H
- PUSH 07H
- /* mov sbuf, year ;发送到电脑一个字节,供调试使用
- jnb ti, $
- clr ti */
- CLR RUNYUEBIT ;清除标记位,待处理闰月时用
- CALL TIANSHU ;调用计算天数子程序
- CALL ZUZHUANG ;调用读表子程序
- MOV A, #4 ;读第4字节,是元旦对应的农历月日
- CALL DU_NO_SHU ;读取的数据在A,元旦对应的农历月日
- MOV B, A ;先保护起来读取的数据
- ANL A, #00011111B ;屏蔽掉高3位,只取元旦对应的农历日
- MOV NO_DATE, A ;存入农历日暂存器
- MOV A, B ;取回数据
- ANL A, #10000000B ;只取元旦农历月份值,A=00H是11月,A=80H,是腊月,仅此可能
- JZ ZHUAN_H_0 ;A=00H是11月,A=80H,是腊月
- MOV NO_MONTH, #12 ;A=1,就是腊月12月
- CALL ZOYI ;是腊月,左移,表中第一个月是11月,变成腊月
- JMP ZHUAN_H_6
- ;以上是读出元旦对应的农历的月日,写入对应单元。调整对应农历月大小标志到最左边一位
- ZHUAN_H_0: MOV NO_MONTH, #11 ;否则就是11月(春节元旦间只能是11、12月)
- ZHUAN_H_6: MOV NO_YEAR, YEAR
- DEC NO_YEAR
- MOV A, R3 ;取出已过天数的低位
- MOV NO_MONTH_R,NO_MONTH ;另存,备农历纪念日用(闰月标记为0)
- ADD A, NO_DATE ;从元旦对应农历月的月初算起(以便后面计算)
- MOV R3, A ;低位送回R3
- MOV A, R4 ;加上低位,相加后可能的进位
- ADDC A, #0 ;加上可能有的进位
- MOV R4, A ;高位送回R4
- ZHUAN_H_3:
- MOV NO_DATE, R3 ;先暂存,如下面不够减的,这就是农历日期
- CALL RUNYUE ;判断下一个月是否是闰月,并作处理
- CALL JIAN ;减去一个月的天数(子程序)
- JNZ ZHUAN_H_4 ;刚好够减A=0,否则跳过下面一行
- MOV A, R4
- JNZ ZHUAN_H_4
- JMP ZHUAN_H_2 ;跳出
- ZHUAN_H_4:
- JC ZHUAN_H_2 ;不够减的,有借位C=1,跳转,退出
- ZHUAN_H_1:
- INC NO_MONTH ;月份加1,是否闰月都到这来,加1
- MOV A, NO_MONTH ;是不是到了腊月?是腊月再加1,就是1月
- CJNE A, #13, ZHUAN_H_5 ;12月再加1,就是13,转为1月
- MOV NO_MONTH, #1 ;农历月进位,变为1月,农历年加1
- INC NO_YEAR
- ZHUAN_H_5:
- MOV NO_MONTH_R,NO_MONTH ;调整以后拷贝到NO_MONTH_R
- JMP ZHUAN_H_3 ;转回,进行下一轮减法
- ZHUAN_H_2: ;如果天数没有够减,从这转出
- CALL GAN_ZHI
- POP 07H
- POP 06H
- POP 05H
- POP 04H
- POP 03H
- POP DPL
- POP DPH
- POP ACC
- RET ;
- ;**************************************************
- ;当前日距离元旦天数计算子程序(农历转换二级子程序)
- ;出口:高位在R4,低位在R3
- ;**************************************************
- TIANSHU:
- PUSH ACC
- PUSH DPH
- PUSH DPL
- MOV DPTR, #TAB_MONTH ;当前月止,累计整月天数表
- MOV A, MONTH ;当前公历月份
- CLR C
- RLC A ;表中,每月高、低位占2字节,所以乘2
- MOV B, A ;保存ACC中的值
- MOVC A, @A+DPTR ;查表,求日期的低位字节
- ADD A, DATE ;加上当前日期,可能会有进位
- DEC A ;因后面的程序要加上元旦所对应农历日前面的天数
- ;比如当日17,需要加16,先减1,在这里减比较方便
- MOV R3, A ;暂时保存到R3
- INC DPTR ;读高位字节
- MOV A, B ;取出ACC中的值,使用
- MOVC A, @A+DPTR ;查表,整月天数高位字节
- ADDC A, #0 ;加上低位字节可能的进位(如果有C=1,否C=0)
- MOV R4, A ;R4存放高位字节
- MOV A, MONTH ;再取当前月份
- CJNE A, #3,TIANSHU_0 ;月份是否大于3月份,如果是3月份以后需区别闰月
- TIANSHU_0: JC TIANSHU_1 ;若A<3,C=1,A>=3,C=0,若C=1则跳转,1、2月不加闰 ;
- MOV A, R3 ;取回当前已过天数 ;
- MOV C, BZ_RUN_NIAN ;大于3月加上闰年(等于1,或等于0)
- ADDC A, #0 ;加上C中闰年的天数,是闰年RUN=1,否RUN=0,另加1天?
- MOV R3, A ;
- MOV A, R4 ;加闰月以后,是否有进位?
- ADDC A, #0 ;加上进位
- MOV R4, A ;存回,已过天数的高位在R4,
- TIANSHU_1:; POP PSW ;当前日止,累计天数计算完成
- POP DPL
- POP DPH
- POP ACC
- RET ;
- ;************************************************************************
- ;闰月处理子程序。(农历转换二级子程序)农历数据表中第3字节是闰月信息,
- ; 最高位是闰月月份的大小,低4位是月份
- ;功能:1、判断当前月是不是闰月。
- ; 2、是闰月在R6、R5最左面一位塞入闰月的大小标志。以后的月份大小标志顺序后推
- ; 3、月份减1,因为后面程序按正常月加1,所以保持月份不加
- ; 4、闰月处理过后,做上标记,下一循环时,闰月已过去,按正常月
- ;************************************************************************
- RUNYUE:
- PUSH ACC
- PUSH B
- MOV C, RUNYUEBIT ;RUNYUEBIT是标记(20H.6),=1处理过
- JC RUNYUE_E ;闰月是否处理过了(C=1),处理过,退出
- MOV A, #3 ;判断是否是闰月,第3字节是闰月数据
- CALL DU_NO_SHU ;调读数子程序
- MOV B, A ;保存待用
- ANL A, #0FH ;将读到的数据屏蔽高4位(低4位是闰月月份)
- JZ RUNYUE_E
- INC A ;闰月月份加上1,如:闰四月,是第个五月
- CLR FLAG_Y ;清除闰月标志,根据下面一句重新设置
- CJNE A, NO_MONTH,RUNYUE_E;判断当前月和闰月等否? 不等,跳出
- SETB FLAG_Y
- MOV A, B ;送回第三字节的值
- RLC A ;闰月大小标志移到C
- MOV A, R6 ;前半年的大小月标志
- RRC A ;闰月大小标志插入R6最高位(即将处理月的位置)
- MOV R6, A ;
- MOV A, R5 ;
- RRC A ;每个月的标志全部往后退一位
- MOV R5, A
- DEC NO_MONTH ;月份数减1,和上一次的月份值一样
- MOV NO_MONTH_R,#0 ;把闰月标记为0,闰月的纪念日无效
- SETB RUNYUEBIT ;闰年已经处理过,做上标记
- RUNYUE_E:
- POP B
- POP ACC
- RET
- ;***************************************************************
- ;左转移子程序,(农历转换二级子程序)
- ;每次把当月的大小值左移到C,参与农历日期转换运算
- ;***************************************************************
- ZOYI:
- PUSH ACC
- MOV A, R5 ;R5是后半年的月份大小值
- RLC A ;
- MOV R5, A ;左转以后存回
- MOV A, R6 ;R6中存放的是前半年月份大小值
- RLC A ;R6转出到C的数据参与转移
- MOV R6, A ;存回。
- POP ACC
- RET
- ;****************************************************************
- ;已过天数,减农历一个月的天数子程序。(农历转换二级子程序)
- ;当年已过天数减29减大小月标志
- ;入口:低位数在R3,高位数在R4,
- ;出口:低位数在R3,高位数在R4
- ;****************************************************************
- JIAN:
- CALL ZOYI ;把当前月的大小标志左移到C
- MOV A, R3 ;取已过天数的低位
- SUBB A, #29 ;减去基本天数(小月29天,大月再减1)
- MOV R3, A ;送回
- MOV A, R4
- SUBB A, #0 ;减去C中可能有的借位
- MOV R4, A ;送回
- MOV A, R3 ;
- RET
- ;**********************************************************
- ;(农历转换二级子程序)
- ;读表子程序是把农历数据表第一个字节,放到R5中,7~2位表示7.8.9.10.11.12月
- ;第二字节,7~0位表示:上年11.12.当年1.2.3.4.5.6月,读出后,放入R6
- ;(本来该子程序是将分散在多个字节中的信息合并,后来改变,没有取消)
- ;**********************************************************
- ZUZHUANG:
- MOV A, #1 ;读第1字节11.12.1.2.3.4.5.6月,返回在A
- CALL DU_NO_SHU ;读数子程序
- MOV R6, A ;R6中存放11.12.1.2.3.4.5.6月大小值
- MOV C, ACC.6 ;这个字节在后面纪念日确定除夕是否30时候用,暂存
- MOV CHUXI, C ;CHUXI是腊月的大小标志,1为大月,除夕为30日
- MOV A, #2 ;读第2字节
- CALL DU_NO_SHU ;读数子程序
- MOV R5, A ;7.8.9.10.11.12月大小值存入R5
- RET
- ;*****************************************************
- ;读取农历数据表的子程序(农历转换二级子程序)
- ;入口:欲读取的字节序号(1~4)在A,当前年份仍然在YEAR
- ;出口:读取到的数据在A
- ;*****************************************************
- DU_NO_SHU:
- MOV R7, A ;保存A中的字节号
- MOV DPTR, #TAB_NO_SHU ;数据表首送DPTR
- MOV A, YEAR ;年送A
- //-------------------------------------------------------------
- CLR BZ_RUN_NIAN
- JB ACC.0, HHHHHH ;如果YEAR的低2位为0,是闰年
- JB ACC.1, HHHHHH ;
- SETB BZ_RUN_NIAN ;设置闰年标志
- //-------------------------------------------------------------
- HHHHHH:
- CLR C ;求出行数
- MOV B, #4 ;年份乘4(左转2次=乘4)
- MUL AB ;因为每年4个字节数据
- ADD A, DPL ;偏移字节数和DPTR低位相加
- MOV DPL, A ;送回
- MOV A, B ;如果仅仅是2010~2030,可以简化
- ADDC A, DPH ;低位可能有进位,所以加
- MOV DPH, A ;*****最后修正2009.12.22.22:58
- MOV A, R7 ;R7中是入口参数,字节号
- MOVC A, @A+DPTR
- RET
- ;***************************************************************
- ;计算农历纪年"干支"子程序(农历转换二级子程序)
- ;***************************************************************
- GAN_ZHI:
- PUSH ACC
- MOV A, NO_YEAR
- CLR C
- SUBB A, #4 ;2004年是甲申年,设"甲"为"0",4=2004年
- MOV B, #10 ;除以10,取余数
- DIV AB
- MOV TIANGAN, B ;送"天干""TIANGAN"寄存
-
- MOV A, NO_YEAR
- SUBB A, #8 ;2008年是戊子年,子为"0"
- MOV B, #12 ;除以12,取余数
- DIV AB
- MOV DIZHI, B ;送"地支""DIZHI"寄存
- POP ACC
- RET
- ;************************************************************
- TAB_MONTH:
- DB 0,0,0,0,31,0,59,0,90,0,120,0,151 ;每月初止天数,低位在前,高位在后
- DB 0,181,0,212,0,243,0,17,1,48,1,78,1
- ;******************************************************
- ;*******************************************************
- TAB_NO_SHU:
- DB 00 ;机器是从0开始,我们习惯从1开始
- DB 0B2H, 058H, 000H, 019H ;2000
- DB 0B6H, 054H, 004H, 087H ;2001
- DB 075H, 028H, 000H, 012H ;2002
- DB 0B6H, 094H, 000H, 01DH ;2003
- DB 05DH, 054H, 002H, 08AH ;2004
- DB 055H, 0A8H, 000H, 015H ;2005
- DB 0AAH, 0ECH, 007H, 082H ;2006
- DB 0C9H, 074H, 000H, 00DH ;2007
- DB 064H, 0B4H, 000H, 017H ;2008
- DB 072H, 0ACH, 005H, 086H ;2009
- DB 0EAH, 054H, 000H, 011H ;2010
- DB 06DH, 028H, 000H, 01BH ;2011
- DB 0AEH, 0A8H, 004H, 088H ;2012(原数据表第一字节是0BAH,错的)
- DB 0ABH, 054H, 000H, 014H ;2013
- DB 055H, 074H, 009H, 081H ;2014
- DB 052H, 0E8H, 000H, 00BH ;2015
- DB 0A9H, 06CH, 000H, 016H ;2016
- DB 0D4H, 05CH, 086H, 084H ;2017
- DB 0D4H, 0ACH, 000H, 00FH ;2018
- DB 0EAH, 04CH, 000H, 01AH ;2019
- DB 0DEH, 054H, 004H, 087H ;2020
- DB 05AH, 0A8H, 000H, 012H ;2021
- DB 0ABH, 054H, 000H, 01DH ;2022
- DB 056H, 0D4H, 002H, 08AH ;2023
- DB 052H, 0D8H, 000H, 014H ;2024
- DB 0A9H, 0B8H, 006H, 082H ;2025
- DB 0A9H, 038H, 000H, 00DH ;2026
- DB 0B4H, 098H, 000H, 018H ;2027
- DB 0BAH, 098H, 005H, 085H ;2028
- DB 0B5H, 04CH, 000H, 011H ;2029
- DB 0D6H, 0A8H, 000H, 01CH ;2030
- DB 09DH, 0A8H, 003H, 088H ;2031
- DB 0A5H, 0B4H, 000H, 013H ;2032
- DB 052H, 0F4H, 007H, 081H ;2033
- DB 052H, 0B4H, 000H, 00BH ;2034
- DB 069H, 034H, 000H, 016H ;2035
- DB 074H, 02CH, 086H, 084H ;2036
- DB 0F4H, 094H, 000H, 010H ;2037
- DB 075H, 048H, 000H, 01AH ;2038
- DB 0B7H, 050H, 005H, 087H ;2039
- DB 02DH, 068H, 000H, 011H ;2040
- DB 095H, 0B4H, 000H, 01DH ;2041
- DB 055H, 06CH, 002H, 08AH ;2042
- DB 0D2H, 06CH, 000H, 015H ;2043
- DB 0E9H, 05CH, 007H, 082H ;2044
- DB 0E9H, 02CH, 000H, 00EH ;2045
- DB 0EAH, 094H, 000H, 019H ;2046
- DB 06CH, 094H, 085H, 086H ;2047
- DB 05BH, 048H, 000H, 010H ;2048
- DB 0ABH, 068H, 000H, 01CH ;2049
- DB 092H, 0D8H, 083H, 088H ;2050
- DB 0A4H, 0DCH, 000H, 013H ;2051
- DB 0D2H, 07CH, 008H, 01EH ;2052
- DB 0D2H, 05CH, 000H, 00CH ;2053
- DB 0D9H, 02CH, 000H, 017H ;2054
- DB 0DAH, 028H, 086H, 084H ;2055
- DB 0BAH, 094H, 000H, 00FH ;2056
- DB 05AH, 0C8H, 000H, 01AH ;2057
- DB 0A9H, 0B0H, 084H, 087H ;2058
- DB 02AH, 0B8H, 000H, 011H ;2059
- DB 0A4H, 0B8H, 000H, 01CH ;2060
- DB 0B4H, 0B8H, 003H, 08AH ;2061
- DB 0B2H, 058H, 000H, 015H ;2062
- DB 0B5H, 054H, 007H, 082H ;2063
- DB 075H, 028H, 000H, 00DH ;2064
- DB 0B6H, 094H, 000H, 019H ;2065
- DB 057H, 054H, 005H, 086H ;2066
- DB 055H, 0A8H, 000H, 010H ;2067
- DB 0A9H, 0B4H, 000H, 01BH ;2068
- DB 055H, 074H, 004H, 089H ;2069
- DB 054H, 0B4H, 000H, 013H ;2070
- DB 06AH, 06CH, 008H, 081H ;2071
- DB 0EAH, 054H, 000H, 00CH ;2072
- DB 06DH, 028H, 000H, 017H ;2073
- DB 0ADH, 0A8H, 006H, 084H ;2074
- DB 0ABH, 054H, 000H, 00FH ;2075
- DB 055H, 068H, 000H, 019H ;2076
- DB 0AAH, 0E8H, 004H, 087H ;2077
- DB 0A9H, 06CH, 000H, 012H ;2078
- DB 0D4H, 0ACH, 000H, 01DH ;2079
- DB 0ECH, 09CH, 003H, 08AH ;2080
- DB 0DAH, 04CH, 000H, 016H ;2081
- DB 0DCH, 0CCH, 007H, 083H ;2082
- DB 0DAH, 0A8H, 000H, 00EH ;2083
- DB 0ABH, 054H, 000H, 018H ;2084
- DB 052H, 0D4H, 085H, 086H ;2085
- DB 052H, 0D8H, 000H, 010H ;2086
- DB 0A9H, 05CH, 000H, 01BH ;2087
- DB 0D5H, 038H, 004H, 088H ;2088
- DB 0B4H, 098H, 000H, 014H ;2089
- DB 0BAH, 058H, 008H, 081H ;2090
- DB 0B5H, 048H, 000H, 00CH ;2091
- DB 0B6H, 0A8H, 000H, 017H ;2092
- DB 09AH, 0A8H, 086H, 084H ;2093
- DB 095H, 0B4H, 000H, 00FH ;2094
- DB 052H, 0B8H, 000H, 019H ;2095
- DB 0AAH, 074H, 004H, 086H ;2096
- DB 069H, 034H, 000H, 012H ;2097
- DB 074H, 054H, 000H, 01DH ;2098
- DB 07CH, 094H, 002H, 08BH ;2099
- DB 075H, 04CH, 000H, 015H ;2100
- ;*********************************************************************
- END
- /*
- //以下是c51调用汇编语言"农历转换.asm"文件示范,需要另建立一个.c文件
- extern unsigned char data year,month,date;
- extern void zhuan_h(void);
- extern bit flag_y,chuxi; //农历闰月标志,FLAG_Y=1,是前月,FLAG_Y=0,是后月,就是闰月,闰月无节日
- //chuxi是腊月大小月的标志。=0是小月,腊月29日是除夕。
- extern NO_YEAR,NO_MONTH,NO_DATE,TIANGAN,DIZHI;
- void main(void)
- {
- unsigned char year_1,month_1,date_1;
- // year=0x0d; //年、月、日可以是时钟芯片读出的值,如果是压缩BCD码,需要先转换,此处为模拟
- // month=0x05; //如果是ds12887等,可以设定读出的位hex码,不需要转换。
- // date=0x09;
- //如果是ds1302读出的值,是压缩BCD码,如:year_1=0x13(2013年)month_1=0x05,daye_1=0x09,需要如下转换:
- year_1=0x13; //年、月、日若是ds1302时钟芯片读出的值,是压缩BCD码,需要先转换,此处为模拟
- month_1=0x05;
- date_1=0x09;
- year=year_1/16*10+year_1%16;
- month=month_1/16*10+month_1%16;
- date=date_1/16*10+date_1%16;
- zhuan_h();
- while(1); //无限循环,模拟主程序,
- }
- */
复制代码
以上程序51hei提供下载:
汇编程序.7z
(5.5 KB, 下载次数: 54)
|