diff --git a/examples/tim1_pwm/Makefile b/examples/tim1_pwm/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..67357efb1079dd4c61badc7c50c0be664fae9b06 --- /dev/null +++ b/examples/tim1_pwm/Makefile @@ -0,0 +1,41 @@ +TARGET:=tim1_pwm + +all : flash + +PREFIX:=riscv64-unknown-elf + +GPIO_Toggle:=EXAM/GPIO/GPIO_Toggle/User + +CH32V003FUN:=../../ch32v003fun +MINICHLINK:=../../minichlink + +CFLAGS:= \ + -g -Os -flto -ffunction-sections \ + -static-libgcc -lgcc \ + -march=rv32ec \ + -mabi=ilp32e \ + -I/usr/include/newlib \ + -I$(CH32V003FUN) \ + -nostdlib \ + -I. -DSTDOUT_UART -Wall + +LDFLAGS:=-T $(CH32V003FUN)/ch32v003fun.ld -Wl,--gc-sections + +SYSTEM_C:=$(CH32V003FUN)/ch32v003fun.c + +$(TARGET).elf : $(SYSTEM_C) $(TARGET).c + $(PREFIX)-gcc -o $@ $^ $(CFLAGS) $(LDFLAGS) + +$(TARGET).bin : $(TARGET).elf + $(PREFIX)-size $^ + $(PREFIX)-objdump -S $^ > $(TARGET).lst + $(PREFIX)-objdump -t $^ > $(TARGET).map + $(PREFIX)-objcopy -O binary $< $(TARGET).bin + $(PREFIX)-objcopy -O ihex $< $(TARGET).hex + +flash : $(TARGET).bin + $(MINICHLINK)/minichlink -w $< flash -b + +clean : + rm -rf $(TARGET).elf $(TARGET).bin $(TARGET).hex $(TARGET).lst $(TARGET).map $(TARGET).hex + diff --git a/examples/tim1_pwm/t1pwm.h b/examples/tim1_pwm/t1pwm.h new file mode 100644 index 0000000000000000000000000000000000000000..261659d35a2cf5c3d40e2619bb3a9ab762f952d8 --- /dev/null +++ b/examples/tim1_pwm/t1pwm.h @@ -0,0 +1,107 @@ +/* + * Single-File-Header for using Advanced Control Timer (TIM1) for PWM generation + * 03-28-2023 E. Brombaugh + */ + +#ifndef _T1PWM_H +#define _T1PWM_H + +#include <stdint.h> + +/* + * initialize act + */ +void t1pwm_init( void ) +{ + // Enable GPIOC, GPIOD and TIM1 + RCC->APB2PCENR |= RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOC | + RCC_APB2Periph_TIM1; + + // PD0 is T1CH1N, 50MHz Output PP CNF = 10: Mux PP, MODE = 11: Out 50MHz + GPIOD->CFGLR &= ~(GPIO_CFGLR_MODE0 | GPIO_CFGLR_CNF0); + GPIOD->CFGLR |= GPIO_CFGLR_CNF0_1 | GPIO_CFGLR_MODE0_0 | GPIO_CFGLR_MODE0_1; + + // PC4 is T1CH4, 50MHz Output PP CNF = 10: Mux PP, MODE = 11: Out 50MHz + GPIOC->CFGLR &= ~(GPIO_CFGLR_MODE4 | GPIO_CFGLR_CNF4); + GPIOC->CFGLR |= GPIO_CFGLR_CNF4_1 | GPIO_CFGLR_MODE4_0 | GPIO_CFGLR_MODE4_1; + + // Reset TIM1 to init all regs + RCC->APB2PRSTR |= RCC_APB2Periph_TIM1; + RCC->APB2PRSTR &= ~RCC_APB2Periph_TIM1; + + // CTLR1: default is up, events generated, edge align + // SMCFGR: default clk input is CK_INT + + // Prescaler + TIM1->PSC = 0x0000; + + // Auto Reload - sets period + TIM1->ATRLR = 255; + + // Reload immediately + TIM1->SWEVGR |= TIM_UG; + + // Enable CH1N output, positive pol + TIM1->CCER |= TIM_CC1NE | TIM_CC1NP; + + // Enable CH4 output, positive pol + TIM1->CCER |= TIM_CC4E | TIM_CC4P; + + // CH1 Mode is output, PWM1 (CC1S = 00, OC1M = 110) + TIM1->CHCTLR1 |= TIM_OC1M_2 | TIM_OC1M_1; + + // CH2 Mode is output, PWM1 (CC1S = 00, OC1M = 110) + TIM1->CHCTLR2 |= TIM_OC4M_2 | TIM_OC4M_1; + + // Set the Capture Compare Register value to 50% initially + TIM1->CH1CVR = 128; + TIM1->CH4CVR = 128; + + // Enable TIM1 outputs + TIM1->BDTR |= TIM_MOE; + + // Enable TIM1 + TIM1->CTLR1 |= TIM_CEN; +} + +/* + * set timer channel PW + */ +void t1pwm_setpw(uint8_t chl, uint16_t width) +{ + switch(chl&3) + { + case 0: TIM1->CH1CVR = width; break; + case 1: TIM1->CH2CVR = width; break; + case 2: TIM1->CH3CVR = width; break; + case 3: TIM1->CH4CVR = width; break; + } +} + +/* + * force output + */ +void t1pwm_force(uint8_t chl, uint8_t val) +{ + uint16_t temp; + + chl &= 3; + + if(chl < 2) + { + temp = TIM1->CHCTLR1; + temp &= ~(TIM_OC1M<<(8*chl)); + temp |= (TIM_OC1M_2 | (val?TIM_OC1M_0:0))<<(8*chl); + TIM1->CHCTLR1 = temp; + } + else + { + chl &= 1; + temp = TIM1->CHCTLR2; + temp &= ~(TIM_OC1M<<(8*chl)); + temp |= (TIM_OC1M_2 | (val?TIM_OC1M_0:0))<<(8*chl); + TIM1->CHCTLR2 = temp; + } +} + +#endif diff --git a/examples/tim1_pwm/tim1_pwm.c b/examples/tim1_pwm/tim1_pwm.c new file mode 100644 index 0000000000000000000000000000000000000000..84d77bdd9cb0a9446874f8ecd68b1b0febcf2628 --- /dev/null +++ b/examples/tim1_pwm/tim1_pwm.c @@ -0,0 +1,39 @@ +/* + * Example for using Advanced Control Timer (TIM1) for PWM generation + * 03-28-2023 E. Brombaugh + */ + +// Could be defined here, or in the processor defines. +#define SYSTEM_CORE_CLOCK 48000000 +#define APB_CLOCK SYSTEM_CORE_CLOCK + +#include "ch32v003fun.h" +#include <stdio.h> +#include "t1pwm.h" + +int main() +{ + uint32_t count = 0; + + SystemInit48HSI(); + + // start serial @ default 115200bps + SetupUART( UART_BRR ); + Delay_Ms( 100 ); + printf("\r\r\n\ntim1_pwm example\n\r"); + + // init TIM1 for PWM + printf("initializing tim1..."); + t1pwm_init(); + printf("done.\n\r"); + + printf("looping...\n\r"); + while(1) + { + t1pwm_setpw(0, count); // Chl 1 + t1pwm_setpw(3, (count + 128)&255); // Chl 4 + count++; + count &= 255; + Delay_Ms( 5 ); + } +}