Skip to content

Commit

Permalink
Add #ifdef support for CH3/CH4 in tim2_pwm example
Browse files Browse the repository at this point in the history
-Implement CH3 and CH4 optionally via #define
-By default only CH1 and CH2 are enabled.
-Channels 3 and 4 can be enabled by uncommenting the appropriate line
-Choose whether default of PWM pins is HIGH (0xff) or LOW (0x00)

NOTES:
-Channel 3 is on a different port (GPIOC) which will be enabled if
needed.

-Channel 4 is on the NRST pin so not usable unless you use `minichlink -d`
to disable the NRST function so the pin can be used as a GPIO

-If your board has a bypass capacitor on PD7 for a reset button the
waveforms observed on CH4 will not be nice square waves.
  • Loading branch information
fr0sty1 committed Aug 1, 2023
1 parent e28a05b commit 2ddc2fe
Showing 1 changed file with 67 additions and 9 deletions.
76 changes: 67 additions & 9 deletions examples/tim2_pwm/tim2_pwm.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/*
* Example for using Advanced Control Timer (TIM2) for PWM generation
* Example for using General Purpose Timer (TIM2) for PWM generation
* 03-28-2023 E. Brombaugh
* 05-29-2023 recallmenot adapted from Timer1 to Timer2
* 07-29-2023 frosty implemented CH3 and CH4
*/

/*
Expand Down Expand Up @@ -31,6 +32,21 @@ Timer 2 pin mappings by AFIO->PCFR1
#include "ch32v003fun.h"
#include <stdio.h>

//By default this example only enables CH1(PD4) and CH2(PD3)
//Uncomment this line to enable CH3 (PC0)
//#define TIM2_EN_CH3

//CH4 uses PD7 which is also the NRST pin
//To use CH4 you must disable the NRST feature
//by using `minichlink -d` and uncomment this line.
#define TIM2_EN_CH4

// mask for the CCxP bits
// when set PWM outputs are held HIGH by default and pulled LOW
// when zero PWM outputs are held LOW by default and pulled HIGH
#define TIM2_DEFAULT 0xff
//#define TIM2_DEFAULT 0x00

/*
* initialize TIM2 for PWM
*/
Expand All @@ -40,14 +56,35 @@ void t2pwm_init( void )
RCC->APB2PCENR |= RCC_APB2Periph_GPIOD;
RCC->APB1PCENR |= RCC_APB1Periph_TIM2;

#ifdef TIM2_EN_CH3
// If using T2CH3 must also enable GPIOC
RCC->APB2PCENR |= RCC_APB2Periph_GPIOC;
#endif

// PD4 is T2CH1, 10MHz Output alt func, push-pull
GPIOD->CFGLR &= ~(0xf<<(4*4));
GPIOD->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF)<<(4*4);

// PD3 is T2CH2, 10MHz Output alt func, push-pull
GPIOD->CFGLR &= ~(0xf<<(4*3));
GPIOD->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF)<<(4*3);


#ifdef TIM2_EN_CH3
// PC0 is T2CH3, 10MHz Output alt func, push-pull
GPIOC->CFGLR &= ~(0xf<<(4*0));
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF)<<(4*0);
#endif


#ifdef TIM2_EN_CH4
// PD7 is T2CH4, 10MHz Output alt func, push-pull
// PD7 is also the NRST (Reset) pin and you must use minichlink
// or the WCH utility to disable the NRST function so the pin
// can be used as a GPIO.
GPIOD->CFGLR &= ~(0xf<<(4*7));
GPIOD->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF)<<(4*7);
#endif

// Reset TIM2 to init all regs
RCC->APB1PRSTR |= RCC_APB1Periph_TIM2;
RCC->APB1PRSTR &= ~RCC_APB1Periph_TIM2;
Expand All @@ -62,15 +99,26 @@ void t2pwm_init( void )
// enabling preload causes the new pulse width in compare capture register only to come into effect when UG bit in SWEVGR is set (= initiate update) (auto-clears)
TIM2->CHCTLR1 |= TIM_OC1M_2 | TIM_OC1M_1 | TIM_OC1PE | TIM_OC2M_2 | TIM_OC2M_1 | TIM_OC2PE;

#ifdef TIM2_EN_CH3
TIM2->CHCTLR2 |= TIM_OC3M_2 | TIM_OC3M_1 | TIM_OC3PE;
#endif
#ifdef TIM2_EN_CH4
TIM2->CHCTLR2 |= TIM_OC4M_2 | TIM_OC4M_1 | TIM_OC4PE;
#endif
// CTLR1: default is up, events generated, edge align
// enable auto-reload of preload
TIM2->CTLR1 |= TIM_ARPE;

// Enable CH1 output, positive pol
TIM2->CCER |= TIM_CC1E | TIM_CC1P;
// Enable CH2 output, positive pol
TIM2->CCER |= TIM_CC2E | TIM_CC2P;
// Enable Channel outputs, set default state (based on TIM2_DEFAULT)
TIM2->CCER |= TIM_CC1E | (TIM_CC1P & TIM2_DEFAULT);
TIM2->CCER |= TIM_CC2E | (TIM_CC2P & TIM2_DEFAULT);

#ifdef TIM2_EN_CH3
TIM2->CCER |= TIM_CC3E | (TIM_CC3P & TIM2_DEFAULT);
#endif
#ifdef TIM2_EN_CH4
TIM2->CCER |= TIM_CC4E | (TIM_CC4P & TIM2_DEFAULT);
#endif
// initialize counter
TIM2->SWEVGR |= TIM_UG;

Expand All @@ -88,10 +136,14 @@ void t2pwm_setpw(uint8_t chl, uint16_t width)
{
case 0: TIM2->CH1CVR = width; break;
case 1: TIM2->CH2CVR = width; break;
#ifdef TIM2_EN_CH3
case 2: TIM2->CH3CVR = width; break;
#endif
#ifdef TIM2_EN_CH4
case 3: TIM2->CH4CVR = width; break;
#endif
}
TIM2->SWEVGR |= TIM_UG; // load new value in compare capture register
//TIM2->SWEVGR |= TIM_UG; // load new value in compare capture register
}


Expand All @@ -116,8 +168,14 @@ int main()
printf("looping...\n\r");
while(1)
{
t2pwm_setpw(0, count); // Chl 1
t2pwm_setpw(1, (count + 128)&255); // Chl 2 180° out-of-phase
t2pwm_setpw(0, count); // CH1
t2pwm_setpw(1, (count + 128)&255); // CH2 180° out-of-phase
#ifdef TIM2_EN_CH3
t2pwm_setpw(2, count); // CH3
#endif
#ifdef TIM2_EN_CH4
t2pwm_setpw(3, (count + 128)&255); // CH4 180° out-of-phase
#endif
count++;
count &= 255;
Delay_Ms( 5 );
Expand Down

0 comments on commit 2ddc2fe

Please sign in to comment.