;-------------------------------------------------------------------------*
;文件名: PWM.asm (PWM波输出文件)                                          *
;本文件包含:                                                              *  
;        PWM:PWM波输出函数                                                *
;硬件连接:                                                                *
;        PTE.2即定时器1通道0接小灯                                        *
;-------------------------------------------------------------------------*

    INCLUDE 'MC9S08AW60.inc'

;相关宏定义
CH0FBit:  equ  7    ;时器1通道0标志位
    
;声明外部函数    
    XDEF  PWM       ;PWM波输出子程序
    XDEF  CH0FBit   ;时器1通道0标志宏定义s
    
;PWM:PWM波输出子程序-----------------------------------*
;功能:根据所需的PWM波的周期和占空比,并设置相关寄存器,输*
;     出PWM波                                          *
;入口:                                                 *
;    (1)PWM波的周期:  HX($0~$FFFF个计数周期)           *
;    (2)PWM波的占空比:A(0~100)                         *
;出口:无                                               *
;堆栈深度:2 + 3 + 6 = 11                               *
;内部调用:DIV16U,MUL16U                                *
;------------------------------------------------------* 
PWM:
   
    
    CLR TPM1SC        ;清定时器1状态和控制寄存器
    CLR TPM1CNTH      ;清计数寄存器
    CLR TPM1CNTL
    
    AIS #-1     
    STA 1,SP    ;暂存占空比
    ;设置PWM波的周期
    PSHH
    PULA
    STA TPM1MODH
    STX TPM1MODL      
    ;根据占空比,设置相应通道寄存器
    ;周期(HX)除100,商在HX中
    LDA #100
    JSR DIV16U
    ;上一步结果乘A
    LDA 1,SP
    JSR MUL16U
    ;写相应通道寄存器                                                                                                                                      
    PSHH
    PULA
    STA TPM1C0VH
    STX TPM1C0VL

    ;设置相应通道控制和状态寄存器
    LDA #%00010110              
    ;     ||||||||
    ;     |||||||+-PS1 \
    ;     ||||||+--PS2 -   -- 分频因子：64
    ;     |||||+---PS3 /
    ;     ||||+----CLKSA \
    ;     |||+-----CLKSB / -- 设置为系统时钟(XCLK = 2MHz)
    ;     ||+------CPWMS   -- IC/OC/EPWM
    ;     |+-------TOIE    -- 禁止溢出中断
    ;     +--------TOF     -- 清溢出标志
    STA  TPM1SC
    ;设置通道控制和状态寄存器
    LDA  #%00101000       
    ;      ||||||xx
    ;      ||||||
    ;      ||||||
    ;      |||||+---ELSnA \
    ;      ||||+----ELSnB / -- 输出高电平
    ;      |||+-----MSnA \
    ;      ||+------MSnB /  -- EPWM
    ;      |+-------CHnIE   -- 禁止 通道0 中断
    ;      +--------CHnF    -- 清 通道0 标志 
    STA  TPM1C0SC
    AIS  #1
   RTS
   
;DIV16U:商为16位无符号数的除法-------------------------*
;功能:无符号数的除法,被除数和商为16位,除数为8位        *
;入口:                                                 *
;    (1)HX:被除数($0-$FFFF的无符号数)                  *
;    (2)A :除数($0-$FF的无符号数)                      *
;出口:                                                 *
;    (1)HX:商($0-$FFFF的无符号数)                      *
;堆栈深度:2 + 3 + 1 = 6                                *
;------------------------------------------------------*
DIV16U:
    AIS #-3    
    ;除数存入[SP+3]
    STA 3,SP
    ;被除数HX存入[SP+2]:[SP+1]
    STX 1,SP
    PSHH
    PULA
    STA 2,SP
    LDHX #0     ;商初始化为0
DIV16U_0:    
    ;比较被除数高8位是否为0
    LDA 2,SP
    CMP #0
    BEQ DIV16U_1    ;被除数高8位为0
    ;被除数高8位不为0(执行2字节减1字节程序段)
    LDA 1,SP        ;取被除数低8位
    SUB 3,SP        ;减除数
    BCC DIV16U_2    ;低8位够减 
    DEC 2,SP        ;被除数高8位-1
    ADD #$FF
    INCA
DIV16U_2:
    STA 1,SP   
    AIX #1    ;商加1
    BRA DIV16U_0
;被除数高8位为0(仅在低8位减)
DIV16U_1:
    ;被除数低8位是否小于除数
    LDA 1,SP     
    CMP 3,SP        
    BLO DIV16U_Exit    ;小于退出
    AIX #1             ;商加1
    SUB 3,SP           ;被除数低8位减余数
    STA 1,SP
    BRA DIV16U_1    
DIV16U_Exit:    
    AIS #3  
   RTS

;MUL16U:被乘数为16位无符号数的乘法---------------------*
;功能:无符号数的乘法,被乘数和积为16位,乘数数为8位      *
;入口:                                                 *
;    (1)HX:被乘数($0-$FFFF的无符号数)                  *
;    (2)A :乘数($0-$FF的无符号数)                      *
;出口:                                                 *
;    (1)HX:积($0-$FFFF的无符号数)                      *
;堆栈深度:2 + 3 + 1 = 6                                *
;------------------------------------------------------*
MUL16U:
    AIS #-3     ;在堆栈区开辟3个临时变量
    STA 1,SP    ;暂存乘数
    ;积([SP+2][SP+3])清零
    LDA #$00
    STA 2,SP
    STA 3,SP
MUL16U_1:    
    LDA 1,SP
    CMP #0
    BEQ MUL16U_EXIT    ;乘数为0,乘法做完
    ;乘数减1
    DECA    
    STA 1,SP
    ;被乘数的低8位和积的低8位相加
    TXA
    ADD 2,SP
    STA 2,SP
    ;被乘数的高8位和积的高8位带低位进位相加
    PSHH
    PULA
    ADC 3,SP
    STA 3,SP
    BRA MUL16U_1
MUL16U_EXIT:
    ;积存入HX
    LDX 2,SP    
    LDA 3,SP
    PSHA
    PULH
    AIS #3    ;释放堆栈区的3个临时变量
   RTS