Skip to content
Snippets Groups Projects
Commit 2ddc2fea authored by Mark Frost's avatar Mark Frost
Browse files

Add #ifdef support for CH3/CH4 in tim2_pwm example

-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.
parent e28a05b1
No related branches found
No related tags found
No related merge requests found
/*
* 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 );
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment