;---------------------------------------------------------------------------*
;工 程 名: IIC.mcp                                                          *
;硬件连接:                                                                  *
;         (1)MCU的串行口与PC机的串行口相连(参见"SCI.asm")                   *
;         (2)MCU的IIC接口与时钟芯片的IIC接口相连(参见"IIC.asm")             *
;程序描述: MCU与时钟芯片PCF8563通过IIC总线通信,MCU从PCF8563获得时间,并通过  *
;          串口发送给PC.亦可PC发送时间给PCF8563来校正其时间.                *
;目    的: 初步掌握IIC模块编程方法                                          *
;---------------------------------------------------------------------------*

 INCLUDE 'Includes.inc'

 XDEF _Startup, main            ;定义可以被外部调用的函数
 XDEF ReBuf,Flag                ;定义可以被外部调用的变量 
 XDEF ReadData
 XDEF WriteData
 XREF __SEG_END_SSTACK 

;变量段
MY_ZEROPAGE: SECTION  SHORT           
SendBuf:DS.B 17                 ;存放要发送的从秒到年的ASCII码(首字节:帧头)
ReBuf: DS.B 17                  ;存放从PC接收的从秒到年的ASCII码(首字节:帧头)
Flag: DS.B 1                    ;接收正确帧标志
ReadData: DS.B 7                
WriteData: DS.B 15
END SECTION
       
;代码段
MyCode:      SECTION  
main:
_Startup:
        LDHX  #RAMEndAddr+1     ;初始化堆栈指针               
        TXS 
        
        LDA #0
        LDX #0
        CLRH
        STA Flag,X              ;设定接收正确
       
        AIS #-5                 ;定义5个变量
        LDA #$FF                ;第1,2个放循环控制变量
        STA 3,SP                ;第3个记录秒值
        
        MOV #$0,WriteData+0     ;CSR1
        MOV #$0,WriteData+1     ;CSR2
        
        MOV #$0,WriteData+2     ;秒
        MOV #$0,WriteData+3     ;分钟
        MOV #$0,WriteData+13    ;CLKOUT频率
        MOV #$0,WriteData+14    ;定时器控制
        MOV #$14,WriteData+4    ;小时
        MOV #$1,WriteData+5     ;天
        MOV #$1,WriteData+6     ;星期
        MOV #$06,WriteData+7    ;月
        MOV #$07,WriteData+8    ;年
        MOV #$80,WriteData+9    ;分钟报警
        MOV #$80,WriteData+10   ;小时报警
        MOV #$80,WriteData+11   ;日期报警
        MOV #$80,WriteData+12   ;周报警         
        
        CLRA                    ;下面要用的循环变量
        STA 4,SP
         
        SEI               ;禁止总中断
        JSR MCUInit       ;芯片初始化  
        JSR SCIInit       ;串口初始化
        JSR IICInit       ;IIC通信初始化(IIC波特率 = 250KHz)

InitPCF8563:              ;初始化时钟芯片PCF8563                           
        LDHX #$A200       ;初始时间设置:2007.06.01 14:00 Mon
        LDA #15
        JSR IICwriteN     ;HX中为A200,数组WriteData,A中存放传入的数据数
        CMP #1            ;A寄存器来存放返回的结果
        BEQ InitPCF8563   ;返回的是1,要继续发送
        
        JSR EnableSCIReInt;开放串口接收中断
        CLI               ;开放总中断 
          
mainLoop:
        CLRX
        CLRH
        LDA Flag,X
        CMP #1
        BNE ReadTime      ;每次循环时,接收到上次循环中由串口发出的17个字节

FirstProcessTime: 
        LDX 4,SP          ;正确收到了一帧
        CPX #8
        BHS ProcessTimeMore
       
        LSLX              ;小于8,则处理从秒到年数据(2字节ASCII合为1字节的压缩BCD)
        INCX
        LDA ReBuf,X
        SUB #$30          ;此时得到的是数字0-9
        LSLA
        LSLA
        LSLA
        LSLA              ;左移4位得到高4位数,低位补0
        STA 5,SP          ;高4位加上4个0存入内存中
        
        INCX              ;第2个字节数据
        LDA ReBuf,X
        SUB #$30
        ORA 5,SP          ;所得的BCD码放入A中
     
        LDX 4,SP
        STA WriteData,X   ;所得结果放入WriteData数组中
                     
        INCX              ;X中放的是循环变量
        STX 4,SP          ;数组的下标在变
        BRA FirstProcessTime
        
ProcessTimeMore:          ;按照时间寄存器格式,进一步处理WriteData中
        CLRX
        CLRH              ;的时间数据
        LDA WriteData,X
        AND #%01111111    ;VL位清零
        STA WriteData,X
        
        LDX #7
        LDA WriteData,X   ;设置月寄存器的世纪位
        CMP #$19
        BNE istwentieth
        LDX #5
        LDA WriteData,X
        ORA #%10000000
        STA WriteData,X
        BRA SendTime
istwentieth:
        LDX #5
        LDA WriteData,X
        AND #%01111111
        STA WriteData,X
SendTime:                                         
        LDHX #$A202           
        LDA #7
        JSR IICwriteN     ;HX中为A202,数组WriteData,A中存放传入的数据数
        CMP #1            ;A寄存器来存放返回的结果
        BEQ SendTime      ;返回的是1,要继续发送
        
        CLRH
        CLRX
        CLRA
        STA Flag,X        ;置标志位为0,表明发送数据成功
                   
ReadTime:                 ;从PCF8563读出时间的BCD码,存入ReadData
        LDHX #$A302           
        LDA #7
        JSR IICreadN      ;HX中为A302,数组ReadData,A中存放传入的数据数
        CMP #1            ;A寄存器来存放返回的结果
        BEQ ReadTime      ;返回的是1,要继续发送 
       
        CLRH
        CLRX
        LDA ReadData,X
        AND #%01111111
        CMP 3,SP
        BNE SecChangeClra
        JMP  Read_End
SecChangeClra:
        CLRA              ;秒值发生变化就转换数据格式并发送
        STA 4,SP          ;存入每次循环的变量,首先为0       
SecChange:
        LDX 4,SP
        CPX #7
        BHS For_End
        CLRH
        CPX #0
        BNE isornot1
        BRA is0oris1              
isornot1:
        CPX #1
        BNE isornot2
is0oris1:                ;此时X中放的是本次循环次数
        LDA ReadData,X
        AND #%01111111   ;秒和分数据的最高位不用,清零
        STA ReadData,X
        BRA Switch_End
isornot2:
        CPX #2
        BNE isornot3
        BRA is2oris3
isornot3: 
        CPX #3
        BNE isornot4
is2oris3:       
        LDA ReadData,X
        AND #%00111111   ;时和天数据的高两位不用,清零
        STA ReadData,X
        BRA Switch_End
isornot4:
        CPX #4
        BNE isornot5      
        LDA ReadData,X
        AND #%00000111   ;星期数据的高五位不用,清零
        STA ReadData,X
        BRA Switch_End
isornot5:
        CPX #5
        BNE Switch_End      
        LDA ReadData,X
        AND #%10000000
        CMP #0
        BNE nineteenthcentury
        MOV #$32,SendBuf+15
        MOV #$30,SendBuf+16
        BRA ProcessMonthMore
nineteenthcentury:
        MOV #$31,SendBuf+15
        MOV #$39,SendBuf+16
        
ProcessMonthMore:
        LDA ReadData,X
        AND #%00011111
        STA ReadData,X
Switch_End:             ;BCD码转为ASCII码
        LDA ReadData,X  ;X中一直存放循环变量
        PSHA
        AND #%11110000
        LSRA
        LSRA
        LSRA
        LSRA
        ADD #$30
        LSLX
        INCX
        STA SendBuf,X
        
        INCX
        PULA
        AND #%00001111
        ADD #$30        ;调整相对应的C语言两句赋值语句顺序
        STA SendBuf,X 
        
        LDX 4,SP
        INCX
        STX 4,SP
        JMP SecChange
For_End:
        LDA #'#'
        CLRH
        CLRX
        STA SendBuf,X
        LDA ReadData,X
        STA 3,SP        ;重新设置秒值
        
        LDA #17         ;A中放入的是发送数据个数
        LDHX #SendBuf   ;此时HX中放入的是数组的首地址
        JSR SCISendN
Read_End:        
        AIS #2          ;BRA因为范围原因,不能够用.用JSR时SP会减2
        JSR mainLoop   ;为使SP不变,在返回之前要加2

