From 68166dc6a07c2b2502e3eef2e78dae642dfb29ff Mon Sep 17 00:00:00 2001 From: cnlohr Date: Sun, 17 Nov 2024 17:14:43 -0800 Subject: [PATCH] Add example for timer capture. --- examples/tim1_capture_dma/Makefile | 10 +++ examples/tim1_capture_dma/funconfig.h | 7 ++ examples/tim1_capture_dma/tim1_capture_dma.c | 88 ++++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 examples/tim1_capture_dma/Makefile create mode 100644 examples/tim1_capture_dma/funconfig.h create mode 100644 examples/tim1_capture_dma/tim1_capture_dma.c diff --git a/examples/tim1_capture_dma/Makefile b/examples/tim1_capture_dma/Makefile new file mode 100644 index 00000000..835910e5 --- /dev/null +++ b/examples/tim1_capture_dma/Makefile @@ -0,0 +1,10 @@ +all : flash + +TARGET:=tim1_capture_dma +CH32V003FUN:=../../ch32v003fun + +include ../../ch32v003fun/ch32v003fun.mk + +flash : cv_flash +clean : cv_clean + diff --git a/examples/tim1_capture_dma/funconfig.h b/examples/tim1_capture_dma/funconfig.h new file mode 100644 index 00000000..998cf76f --- /dev/null +++ b/examples/tim1_capture_dma/funconfig.h @@ -0,0 +1,7 @@ +#ifndef _FUNCONFIG_H +#define _FUNCONFIG_H + +#define CH32V003 1 + +#endif + diff --git a/examples/tim1_capture_dma/tim1_capture_dma.c b/examples/tim1_capture_dma/tim1_capture_dma.c new file mode 100644 index 00000000..8448f906 --- /dev/null +++ b/examples/tim1_capture_dma/tim1_capture_dma.c @@ -0,0 +1,88 @@ +// Example using Timer 1 capture to look for down-going events +// on PD2. Then using DMA to capture that event and write it +// to a circular queue that can be read out later. +// +// For it to produce interesting output, you can wire PD2 to PD3. + +#include "ch32v003fun.h" +#include + +uint32_t count; +uint16_t reply_buffer[256]; // For generating the mask/modulus, this must be a power of 2 size. + +int main() +{ + SystemInit(); + funGpioInitAll(); + + // Enable GPIOs + RCC->APB2PCENR |= RCC_APB2Periph_TIM1 | RCC_APB2Periph_AFIO; + RCC->AHBPCENR |= RCC_AHBPeriph_DMA1; + + // TIM2_CH1 -> PD2 -> DMA1_CH2 + #define DMA_IN DMA1_Channel2 + + // T1C1 -> What we are sampling. + funPinMode( PD2, GPIO_CFGLR_IN_PUPD ); + funDigitalWrite( PD2, 1 ); + + // PD3 output to send something back into PD2. + funPinMode( PD3, GPIO_CFGLR_OUT_2Mhz_PP ); + + TIM1->PSC = 0x0fff; // set TIM1 clock prescaler divider (Massive prescaler) + TIM1->ATRLR = 65535; // set PWM total cycle width + + // CH2 Mode is output, PWM1 (CC1S = 00, OC1M = 110) + TIM1->CHCTLR1 = TIM_CC1S_0; + + // Add here CC1P to switch from UP->GOING to DOWN->GOING log times. + TIM1->CCER = TIM_CC1E;// | TIM_CC1P; + + // initialize counter + TIM1->SWEVGR = TIM_UG; + + // Enable TIM2 + TIM1->CTLR1 = TIM_ARPE | TIM_CEN; + TIM1->DMAINTENR = TIM_CC1DE | TIM_UDE; // Enable DMA motion. + TIM1->CTLR1 |= TIM_URS; // Trigger DMA on overflow ONLY. + + // TIM1_TRIG/TIM1_COM/TIM1_CH4 + DMA_IN->MADDR = (uint32_t)reply_buffer; + DMA_IN->PADDR = (uint32_t)&TIM1->CH1CVR; // Input + DMA_IN->CFGR = + 0 | // PERIPHERAL to MEMORY + 0 | // Low priority. + DMA_CFGR1_MSIZE_0 | // 16-bit memory + DMA_CFGR1_PSIZE_0 | // 16-bit peripheral + DMA_CFGR1_MINC | // Increase memory. + DMA_CFGR1_CIRC | // Circular mode. + 0 | // NO Half-trigger + 0 | // NO Whole-trigger + DMA_CFGR1_EN; // Enable + + int samples_in_buffer = sizeof(reply_buffer) / sizeof(reply_buffer[0]); + DMA_IN->CNTR = samples_in_buffer; + + int tail = 0; + while(1) + { + // Must perform modulus here, in case DMA_IN->CNTR == 0. + int head = (samples_in_buffer - DMA_IN->CNTR) & (samples_in_buffer-1); + + while( head != tail ) + { + uint32_t time_of_event = reply_buffer[tail]; + printf( "%d/%d %d\n", tail, head, (int)time_of_event ); + + // Performs modulus to loop back. + tail = (tail+1)&(samples_in_buffer-1); + } + + Delay_Ms(100); + funDigitalWrite( PD3, 1 ); + Delay_Ms(10); + funDigitalWrite( PD3, 0 ); + printf( "." ); + } +} +