使用DMA的方式来捕获输入波形中一个周期内的高低电平的持续时间,从而计算出输入频率;
捕获分辨率在这里设置到了1us;
/*****************************************************************************
*
* File Name : main.c
*
* Description: main
*
* Copyright (c) 2014 Winner Micro Electronic Design Co., Ltd.
* All rights reserved.
*
* Author : dave
*
* Date : 2014-6-14
*****************************************************************************/
#include "wm_include.h"
#include "wm_type_def.h"
#include "FreeRTOS.h"
#include "task.h"
#include "wm_gpio.h"
#include "wm_pwm.h"
#include "wm_cpu.h"
#include "wm_dma.h"
#include "wm_gpio_afsel.h"
#include "wm_timer.h"
#define COUNTER_FREQ 1000000
#define ZERO_DETEC_IO WM_IO_PB_18
#define PWM_CAP_CHANNEL 0
typedef struct _frequency_info
{
volatile u32 pwmDmaCap;
volatile u32 period_ticks;
volatile u32 frequecy;
} frequency_info;
static frequency_info f_info;
static void pwm_dma_callback(void *arg)
{
//printf("pwmH:%d, pwmL:%d\n", (f_info.pwmDmaCap >> 16), (f_info.pwmDmaCap & 0x0000ffff));
f_info.period_ticks = (f_info.pwmDmaCap >> 16) + (f_info.pwmDmaCap & 0x0000ffff);
}
static int pwm_capture_mode_dma(u8 channel, u32 freq)
{
u8 dmaCh;
int frequecy = 0, high, low;
struct tls_dma_descriptor DmaDesc;
tls_sys_clk sysclk;
memset( &f_info, 0, sizeof(f_info) );
tls_sys_clk_get(&sysclk);
wm_pwm1_config(ZERO_DETEC_IO);
tls_pwm_stop(channel);
dmaCh = tls_dma_request(1, TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_PWM_CAP0) | TLS_DMA_FLAGS_HARD_MODE);
DmaDesc.src_addr = HR_PWM_CAPDAT;
DmaDesc.dest_addr = (unsigned int)&(f_info.pwmDmaCap);
DmaDesc.dma_ctrl = TLS_DMA_DESC_CTRL_DEST_ADD_INC | TLS_DMA_DESC_CTRL_BURST_SIZE1 | TLS_DMA_DESC_CTRL_DATA_SIZE_WORD | TLS_DMA_DESC_CTRL_TOTAL_BYTES(400);
DmaDesc.valid = TLS_DMA_DESC_VALID;
DmaDesc.next = NULL;
tls_dma_start(dmaCh, &DmaDesc, 0);
tls_dma_irq_register(dmaCh, pwm_dma_callback, NULL, TLS_DMA_IRQ_TRANSFER_DONE);
tls_pwm_cap_init(channel, sysclk.apbclk * UNIT_MHZ / freq, DISABLE, WM_PWM_CAP_DMA_INT);
tls_pwm_start(channel);
while(f_info.period_ticks == 0);
tls_pwm_stop(channel);
high = f_info.period_ticks>>16;
low = f_info.period_ticks&0xffff;
printf("LEVEL: H:%d, L:%d\n", high, low);
frequecy = COUNTER_FREQ/(high + low);
printf("input freq: %dHz\n", frequecy);
f_info.frequecy = frequecy;
return frequecy;
}
static int gpio_initial(void)
{
tls_gpio_cfg(ZERO_DETEC_IO, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_PULLHIGH);
return WM_SUCCESS;
}
void ctrl_task9(int *arg)
{
printf("application start.\n");
wm_pwm2_config(WM_IO_PB_17);
tls_pwm_init(1, 60, 99, 0);
tls_pwm_start(1);
gpio_initial();
pwm_capture_mode_dma(PWM_CAP_CHANNEL, COUNTER_FREQ);
while(1)
{
tls_os_time_delay(HZ);
}
}
int misc_task_start(void (*func)(void *), char *task_name,
u32 stack_size, void *arg, u8 uxTaskPriority)
{
return xTaskCreate(func, /* The function that implements the task. */
task_name, /* Just a text name for the task to aid debugging. */
stack_size, /* The stack size is defined in FreeRTOSIPConfig.h. */
arg, /* The task parameter, not used in this case. */
uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */
NULL); /* The task handle is not used. */
}
void UserMain(void)
{
misc_task_start(ctrl_task9, "ctr9", 256, NULL, 5);
}