diff --git a/examples/tim2_pwm/tim2_pwm.c b/examples/tim2_pwm/tim2_pwm.c index 2e0911e5f8aa7ad248ba63c6113011476cb15ba8..2661c137dd17c4cef70af657c2a01184837fa28d 100644 --- a/examples/tim2_pwm/tim2_pwm.c +++ b/examples/tim2_pwm/tim2_pwm.c @@ -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 */ /* @@ -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 */ @@ -40,6 +56,11 @@ 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); @@ -47,7 +68,23 @@ void t2pwm_init( void ) // 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; @@ -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; @@ -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 } @@ -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 );