Always on the Pulse

As was noted at the very beginning pin 41 (PD0) which drives our LED has as its alternate function "Channel 2 of Timer 3". Timer channels can be used in input or output mode so we can drive the LED directly from a timer without using GPIO's and interrupts.
So a timer can be set up to send pulses to the LED with configurable duty cycle in PWM mode or simply toggle as we have been doing in toggle mode.

As well as the auto reload AAR registers timers 1,2 and 3 have capture/compare registers that can be set on any of there channels, Timer 3 has two channels and our LED is connected the second, but all together there are 9 channels on the combined timers that can be used as variable frequency generators and pulse width modulation sources when the timers are used in compare mode.

Lets look at timer 3 and we see that it has two Channel Compare Registers TIM3_CCR1 and TIM3_CCR2 which are 16 bit in size, As the timer is counting up to the value in the Auto Reload register it is also looking at the channel compare registers to see if the current counter value is less than or greater than the compare register, when the values are equal then an action can be performed and also if needed an interrupt request sent.

One of these actions can be to toggle the output pin so zero becomes one and visa versa. Here we set the AAR register to update at a count of 1024, and we set the Channel Compare register to be somewhere between 0 and ARR so the compare will be performed.

We also set-up the Channel 2 Compare Mode Register (TIM3_CCMR2) to be in toggle mode by setting its value to 0x30 so the output pin will change when the compare register value is reached. Further more we also have to enable channel two using the Channel 2 enable register (TIM3_CCER1) which will put the Pin into its alternate function and finally enable the timer as before. 

That's it , no interrupts needed just set up the hardware and go

    #include ""   

    segment 'rom'
CLK_CKDIVR        EQU $50C6        ; Clock divider register
TIM3_CR1          EQU $5320        ; TIM3 Control register 1
TIM3_CCMR2        EQU $5326        ; TIM3 Capture/Compare mode register 2
TIM3_CCER1        EQU $5327        ; TIM3 Capture/Compare enable register 1
TIM3_PSCR         EQU $532A        ; TIM3 Prescaler register
TIM3_ARRH         EQU $532B        ; Auto reload register High
TIM3_ARRL         EQU $532C        ; Auto reload register Low
TIM3_CCR2H        EQU $532F        ; Chan2 compare register High
TIM3_CCR2L        EQU $5330        ; Chan2 compare register Low


    mov CLK_CKDIVR,#$0     ; set max internal clock
    ; PDO pin (41) alternate  mode is timer 3 chanel 2
    mov TIM3_PSCR,#$0F     ; timer 3 prescaler div by 32768
    mov TIM3_ARRH,#$04     ; count to 256 note high byte must be loaded individually and first
    mov TIM3_ARRL,#$00     ;
    mov TIM3_CCR2H,#$03    ; compare register set above mid point for uneven duty cycle
    mov TIM3_CCR2L,#$F0 ; 
    ; Set CC2 channel as output (compare mode)
    ; 0x30 = OC2Ref toggles when TIM3_CNT=TIM3_CCR1
    ; 0x60 = PWM mode 1
    ; 0x70 = PWM mode 2
    ; 0x50 = Force active level OC2Ref forced low
    ; 0x40 = Force active level OC2Ref forced low
    ; 0x20 = Chan 2 inactive on level match
    ; 0x10 = Chan 2 active on level match
    ; 0x00 = Frozen
    mov TIM3_CCMR2,#$30 ; set to toggle on compare
    bset TIM3_CCER1,#4     ; enable chan 2 as output
    bset TIM3_CR1,#0      ; set CEN bit to enable the timer

;    main program loop
    jra loop_forever


Below is from the reference manual but simplified some what (oh yeh) by your's truly, they are for output mode only.

Capture/compare mode register 2 TIM3_CCMR2

 Bit No
 7  6  5  4  3  2  1  0
 Function  reserved OC2M2
below *
 OC2PE  reserved  CC2S1 CC2S0
 Name         Output compare 2 preload enable   Capture/compare 2 selection
 R/W  rw rw rw rw  rw rw
 Default  0  0  0  0  0  0  0  0
 Notes         0: Preload on CCR2 disabled
1: Preload on CCR2 enabled
  00: CC2 channel is configured as output *default*
01: CC2 channel is configured as input, IC2 is mapped on TI2FP2
10: CC2 channel is configured as input, IC2 is mapped on TI1FP2
11: N/A in stm8s105

* Note: OC2M Output compare 2 mode

These bits defines the behaviour of the output reference signal OC2REF from which OC2 is derived. OC2REF is active high whereas OC2 active level depends on the CC2P bit (see below).

000: Frozen - The comparison between the output compare register TIM3_CCR2 and the counter TIM3_CNT has no effect on the outputs

001: Set channel 1 to active level on match. OC2REF signal is forced high when the counter TIM3_CNT matches the capture/compare register 2 (TIM3_CCR2).

010: Set channel 1 to inactive level on match. OC2REF signal is forced low when the counter TIM3_CNT matches the capture/compare register 2 (TIM3_CCR2).

011: Toggle - OC2REF toggles when TIM3_CNT=TIM3_CCR2

100: Force inactive level - OC2REF is forced low

101: Force active level - OC2REF is forced high

110: PWM mode 1
- In up-counting, channel 2 is active as long as TIM3_CNT< TIM3_CCR2.Otherwise, channel 2 is inactive.

111: PWM mode 2 - In up-counting, channel 2 is inactive as long as TIM3_CNT< TIM3_CCR2. Otherwise, channel 2 is active.

Note: In PWM mode 1 or 2, the OC2REF level changes only when the result of the comparison changes or when the output compare mode switches from “frozen” mode to “PWM” mode.

Capture/Compare enable register 1 (TIM3_CCER1)

 Bit No
 7 6  5  4  3 2  1  0
 Function  reserved  reserved  CC2P  CC2E  reserved  reserved  CC1P  CC1E
 Name     Capture Compare 2 output polarity
Capture Compare 2 output Enable
    Capture Compare 1 output polarity Capture Compare 1 output enable
 Default  0  0  0  0  0  0  0  0
 Notes     0: OC2 active high
1: OC2 active low
when configured for output
must be set to enable the channel as output

0: OC2 active high
1: OC2 active low
when configured for output
must be set to enable the channel as output

So 001 and 010 appear to be one shot modes , once the output has changed it stays there
011 we know about , it simply toggles the output
110 and 111 are the pulse width modulation modes where the compare value in TIM3_CCR2 will determine the pulse width.
000,001 and 010 appear to keep the output in a static state , either freeze it or force it high or low.

Lets look PWM mode 1 (0x60), Now what should happen is that pin 41 is active (high) until the compare value is reached 0x03F0 then it is inactive (low) until the AAR refresh value 0x0400 is reached and then it is reset and goes back to active (high).
So the pulse will be longest at the beginning and blip to (low) just before we get to the refresh value. As High means off for the LED it should blip every second or so.

Try it  .. Set TIM3_CCER1 to 0x60, OK seems to work, now change to PWM mode 2 (0x70) the reverse should happen , also behaves as expected

Another thing to try is to set bit 5 of TIM_CCER1 the output polarity flag CC2P,  this will reverse the behaviour.

Atom Age,
5 Sept 2010, 13:11