農歷轉換程序模塊,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)
2020-4-9 02:32 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|