9S08QG8 PWM for SINE GENERATION

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

9S08QG8 PWM for SINE GENERATION

14,297 Views
fuma
Contributor I
Hi, I have a problem for generate a 8 bit PWM  signal for create a sine wave at 50Hz with PWM work at 15 or 20kHz.
The read for the sine tab work correctly, the generation signal of PWM is ok but when I paste all for the generation of signal the processor not work correctly because not read the value for load the PWM register.
I do with a table of 16 data for test and the code is the follow:
 
 
    lda   #$0f             ; lunghezza tabella sinusoide
    sta   TABMAX          ; lunghezza tabella sinusoide
 
lb00    ldhx  #TabSin           ; LETTURA TAB SINUSOIDE      read sin tab
lb01
        lda   ,x   
        LDHX   ,x
        STHX  TPMC1V                                              
        MOV   #$28,TPMSC           
        aix   #1     
        LDA   TABMAX       
        deca                      
        sta   TABMAX             
        cmp   #$00
        beq   go2      
go1     brCLR 7,TPMSC,go1       
        jmp   lb01
go2            
        lda   #$0f             ; lunghezza tabella sinusoide   lengh sin tab
        sta   TABMAX                                                
go3     brCLR 7,TPMSC,go3        
        jmp   lb00
       
TabSin:   
       dc.b $A0,$A0,$da,$da,$A0,$A0,$da,$da,$A0,$A0,$da,$da,$A0,$A0,$da,$da     ; only for test
EndTabSin
 
Where is my error? 
Thanks for the help.
Regards
 
Fabio
Labels (1)
0 Kudos
11 Replies

695 Views
bigmac
Specialist III
Hello Fabio,
 
It seems that, after the occurrence of each timer overflow condition, you require to load a new PWM value, obtained from the table, and that this would take affect at the next overflow.  This would result in each PWM cycle having a different pulse width, as dictated by the table, with a complete output cycle consisting of 16 PWM cycles.  Is this the case?
 
Even though the PWM resolution may be reduced to 8-bit, a full 16-bit word must be written to TPMC1V, which you are doing with the code:
        LDHX   ,x      ; Fetch word value from table
        STHX  TPMC1V   ; Write word to TPM ch 1

This means that each entry of the table must be a word value, even though the upper byte may be zero.  It also means that the X-value, prior to the first instruction, must take into account that each table entry is a word value.  Also adding other simplifications, the intent of your code might be represented thus:

          mov    #$28,TPMSC    ; TPM: No int, ext source, prescale 1
          clr    PNTR          ; Initialise pointer value
LOOP1:    ldx    PNTR
          and    #$0F          ; Ensure range 0-15
          lslx                 ; Word index for table
          clrh
          ldhx   TabSin,x      ; Get word value from table
          sthx   TPMC1V        ; Set PWM value
          inc    PNTR          ; Increment for next table entry
          brclr  TOF,TPMSC,*   ; Wait for timer overflow
          mov    #$28,TPMSC    ; Clear overflow flag
          bra    LOOP1         ; Loop always
 
TabSin:   ; only for test
          dc.w   $00A0,$00A0,$00DA,$00DA
          dc.w   $00A0,$00A0,$00DA,$00DA
          dc.w   $00A0,$00A0,$00DA,$00DA
          dc.w   $00A0,$00A0,$00DA,$00DA

Alternatively, this process should operate more efficiently on the basis of using timer overflow interrupt.  This should allow other processing to occur within the main loop.

; TPM OVERFLOW ISR
TPM_ISR:  pshh
          bclr   TOF,TPMSC      ; Clear overflow flag
          inc    PNTR           ; Increment for next table entry
          ldx    PNTR
          and    #$0F           ; Ensure range 0-15
          lslx                  ; Word index for table
          clrh
          ldhx   TabSin,x       ; Fetch word value from table
          sthx   TPMC1V         ; Set next PWM value
          pulh
          rti

Regards,
Mac


Message Edited by bigmac on 2007-07-05 06:44 AM
0 Kudos

695 Views
bigmac
Specialist III
Oops!  Just found an error in the code of my previous post  . . .  and too late to edit.
 
Each piece of code should actually be as follows:
 
          mov    #$28,TPMSC    ; TPM: No int, ext source, prescale 1
          clr    PNTR          ; Initialise pointer value
LOOP1:    lda    PNTR

          and    #$0F          ; Ensure range 0-15
          tax
          lslx                 ; Word index for table
          clrh
          ldhx   TabSin,x      ; Get word value from table
          sthx   TPMC1V        ; Set PWM value
          inc    PNTR          ; Increment for next table entry
          brclr  TOF,TPMSC,*   ; Wait for timer overflow
          mov    #$28,TPMSC    ; Clear overflow flag
          bra    LOOP1         ; Loop always
 
and for the ISR code -
 
; TPM OVERFLOW ISR
TPM_ISR:  pshh
          bclr   TOF,TPMSC      ; Clear overflow flag
          inc    PNTR           ; Increment for next table entry
          lda    PNTR
          and    #$0F           ; Ensure range 0-15
          tax
          lslx                  ; Word index for table
          clrh
          ldhx   TabSin,x       ; Fetch word value from table
          sthx   TPMC1V         ; Set next PWM value
          pulh
          rti
Regards,
Mac
 
0 Kudos

695 Views
peg
Senior Contributor IV
Hi Mac,
 
It appears you may have been in two minds while doing this.
 
The CLRH is superfluous in front of a LDHX
 
BUT.....
 
If you leave it there, remove the LSLX and change the LDHX to LDX it works with the original, half the size table! Of course you really only need to clear it once!
 
It is unclear whether the OP intended to do 16-bit value loads and had a short table or wrongly did 8-bit loads.
 
0 Kudos

695 Views
CompilerGuru
NXP Employee
NXP Employee
The CLRH is needed by the index part of the "ldhx   TabSin,x"
but could well by that for the OP an 8 bit table would be enough.

Daniel
0 Kudos

695 Views
peg
Senior Contributor IV
Hi,
Yes! of course you are right. It could be done outside the loop as the table as shown does not affect H. The point about the half sized table remains valid though. Then H could definately be cleared once.
 
0 Kudos

695 Views
peg
Senior Contributor IV
Hi Fabio,
 
Just for more educational value...
 
You had:
 
    lda  TABMAX
    deca
    sta  TABMAX
    cmp  #$00
    beq  go2
 
Now Tony has actually made this part redundant but this part could be reduced to:
 
    dec  TABMAX
    beq  go2
 
i.e. you can decrement the memory loacation directly without bring it into the accumulator
the DEC code will set the Z flag in the CCR directly without having to do the CMP  #$00
So you can do the zero testing branch instruction directly after it.
 
The original does do what is intended it is just a bit long winded!
 
Also I believe your lda ,x at the top was just an error as the part I quote above trashes it before it is used anyway. This would mean it can be left out of Tony's code.
 
 
 


Message Edited by peg on 2007-07-04 09:21 PM
0 Kudos

695 Views
tonyp
Senior Contributor II
Without checking if your code actually does what you claim, there is at least one obvious bug in your code.  When doing:

        LDHX   ,x
        STHX  TPMC1V                                              

you're destroying your data pointer; do this instead:

        PSHHX
        LDHX   ,x
        STHX  TPMC1V
        PULHX

Your code can be optimized somewhat (getting rid of the TABMAX variable and re-arranging things a bit), like so:

lb00                ldhx      #TabSin
lb01                lda       ,x
                    pshhx
                    ldhx      ,x
                    sthx      TPMC1V
                    pulhx
                    mov       #$28,TPMSC
                    brclr     7,TPMSC,*
                    aix       #1
                    cphx      #EndTabSin
                    blo       lb01
                    bra       lb00

TabSin              dc.b      $A0,$A0,$da,$da,$A0,$A0,$da,$da
                    dc.b      $A0,$A0,$da,$da,$A0,$A0,$da,$da
EndTabSin

And, where exactly is the value loaded in register A used?


Message Edited by tonyp on 2007-07-04 12:45 PM
0 Kudos

695 Views
fuma
Contributor I
Hi Tonyp, the exact value of the A register is:
 
       dc.b $00,$03,$06,$09,$0b,$10,$13,$16,$19,$1c,$1f,$22,$26,$29,$2c,$2f
       dc.b $32,$35,$38,$3b,$3e,$41,$44,$47,$4a,$4d,$50,$53,$56,$59,$5c,$5f
       dc.b $62,$65,$68,$6b,$6d,$70,$73,$76,$79,$7b,$7e,$81,$84,$87,$8a,$8c
       dc.b $8e,$91,$93,$96,$98,$9b,$9d,$a0,$a2,$a5,$a7,$a9,$ac,$ae,$b0,$b3
       dc.b $b5,$b7,$b9,$bb,$be,$c0,$c2,$c4,$c6,$c8,$ca,$cb,$cd,$cf,$d1,$d3
       dc.b $d5,$d6,$d7,$d8,$d9,$db,$dc,$e0,$e1,$e3,$e4,$e6,$e7,$e8,$ea,$eb
       dc.b $ec,$ed,$ee,$ef,$f1,$f2,$f3,$f3,$f4,$f5,$f6,$f7,$f8,$f8,$f9,$fa
       dc.b $fa,$fb,$fb,$fc,$fc,$fd,$fd,$fe,$fe,$fe,$fe,$ff,$ff,$ff,$ff,$ff
       dc.b $ff,$ff,$ff,$ff,$ff,$fe,$fe,$fe,$fe,$fd,$fd,$fb,$fb,$fb,$fa,$fa
       dc.b $fa,$f9,$f8,$f8,$f7,$f6,$f5,$f4,$f3,$f3,$f2,$f1,$ef,$ee,$ec,$eb
       dc.b $eb,$ea,$e8,$e7,$e6,$e4,$e3,$e1,$e0,$de,$dd,$db,$da,$d8,$d6,$d5
       dc.b $d3,$d1,$cf,$cd,$cb,$ca,$c8,$c6,$c4,$c2,$c0,$be,$bb,$b9,$b7,$b5
       dc.b $b3,$b0,$ae,$ac,$a9,$a7,$a5,$a2,$a0,$9d,$9b,$98,$96,$93,$91,$8e
       dc.b $8c,$89,$86,$84,$81,$7e,$7b,$79,$76,$73,$70,$6d,$6b,$68,$65,$62
       dc.b $5f,$5c,$59,$56,$53,$50,$4d,$4a,$47,$44,$41,$3e,$3b,$38,$35,$32
       dc.b $2f,$2c,$29,$26,$22,$1f,$1c,$19,$16,$13,$10,$0d,$09,$06,$03,$00
 
 
Thanks for all for the big help & for the explication.
 
Regards
Fabio
0 Kudos

695 Views
peg
Senior Contributor IV
Hi Fabio,
 
So that is your actual sign table? 256 long and one byte per load?
 
So I adjusted bigmac's code to this for you:
 
          mov    #$28,TPMSC    ; TPM: No int, ext source, prescale 1
          clr    PNTR          ; Initialise pointer value
          clrh
LOOP1:    ldx    PNTR

          ldx    TabSin,x      ; Get byte value from table
          sthx   TPMC1V        ; Set PWM value
          inc    PNTR          ; Increment for next table entry
          brclr  TOF,TPMSC,*   ; Wait for timer overflow
          mov    #$28,TPMSC    ; Clear overflow flag
          bra    LOOP1         ; Loop always
 
Tony was referring to your LDA at label lb01 which Itouched on again later.
You do not use the value you load into A!
 
 
0 Kudos

695 Views
tonyp
Senior Contributor II
If dealing with single byte values, and considering all advice received so far, it simplifies to this:

lb00                ldhx      #TabSin
lb01                clr       TPMC1VH
                    mov       x+,TPMC1VL
                    mov       #$28,TPMSC
                    brclr     TOF.,TPMSC,*
                    cphx      #EndTabSin
                    blo       lb01
                    bra       lb00
0 Kudos

695 Views
david_miravete
Contributor I

Hello

I want a software to create a sine wave with PWM
I tried the pieces of code in this topic that nothing works.

Thank you for your help

0 Kudos