Files
AC707N/SDK/cpu/periph_demo/gptimer_demo.c
T
2025-12-03 11:12:34 +08:00

341 lines
12 KiB
C

#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".timer_demo.data.bss")
#pragma data_seg(".timer_demo.data")
#pragma const_seg(".timer_demo.text.const")
#pragma code_seg(".timer_demo.text")
#endif
#include "gptimer.h"
#include "clock.h"
#include "debug.h"
#include "timer.h"
extern void wdt_clear();
static void timer_callback_func_0(u32 tid, void *private_data)
{
putchar('t');
//可以翻转IO口测量时间
gpio_set_mode(PORTA, BIT(0), PORT_OUTPUT_HIGH);
gpio_set_mode(PORTA, BIT(0), PORT_OUTPUT_LOW);
}
static void timer_callback_func_1(u32 tid, void *private_data)
{
putchar('T');
//可以翻转IO口测量时间
gpio_set_mode(PORTC, BIT(4), PORT_OUTPUT_HIGH);
gpio_set_mode(PORTC, BIT(4), PORT_OUTPUT_LOW);
}
static void timer_callback_func_2(u32 tid, void *private_data)
{
gpio_set_mode(PORTA, BIT(1), PORT_OUTPUT_HIGH);
gpio_set_mode(PORTA, BIT(1), PORT_OUTPUT_LOW);
}
static void timer_demo()
{
printf("timer_demo()\n");
const struct gptimer_config timer_config = {
.timer.period_us = 1 * 1000 * 1000, //定时周期, 1000000us
.irq_cb = timer_callback_func_0, //设置中断回调函数
.irq_priority = 1, //中断优先级
.mode = GPTIMER_MODE_TIMER, //设置工作模式
.private_data = NULL,
};
u32 id = gptimer_init(TIMERx, &timer_config); //初始化timer配置,成功会返回分配的timer_id, 失败返回-1
printf("timer_demo id:%d\n", id);
gptimer_start(id); //启动timer
gptimer_set_timer_period(id, 500 * 1000); //设置定时周期为500ms
u32 timer_us = gptimer_get_timer_period(id); //获取定时周期
printf("timer period_us = %dus\n", timer_us);
gptimer_set_irq_callback(id, timer_callback_func_1); //设置回调函数
}
#if 0
static void pwm_demo()
{
printf("pwm_demo()\n");
const struct gptimer_config pwm_config = {
.pwm.freq = 1 * 1000, //设置输出频率
.pwm.duty = 3456, //设置占空比为34.56%
.pwm.port = PORTA, //设置pwm输出IO_ PORTA_02
.pwm.pin = BIT(2), //设置pwm输出IO_PORTA_02
.mode = GPTIMER_MODE_PWM, //设置工作模式
};
u32 id = gptimer_init(TIMERx, &pwm_config);
printf("pwm_demo id:%d\n", id);
gpio_set_mode(PORTA, BIT(2), PORT_OUTPUT_LOW); //IO口设为输出
gptimer_start(id); //启动timer
gptimer_set_pwm_freq(id, 2000); //设置pwm频率
u32 freq = gptimer_get_pwm_freq(id);
printf("pwm freq = %dHz\n", freq);
gptimer_set_pwm_duty(id, 7500); //设置pwm占空比
u32 duty = gptimer_get_pwm_duty(id);
printf("pwm duty = %d/10000\n", duty);
gptimer_pwm_flip(id); //pwm翻转
}
#else
static void pwm_demo()
{
printf("pwm_demo()\n");
const struct gptimer_config pwm_config = {
.pwm.freq = 6 * 1000 * 1000, //设置输出频率
.pwm.duty = 5000, //设置占空比为34.56%
.pwm.port = PORTC, //设置pwm输出IO_ PORTA_02
.pwm.pin = BIT(3), //设置pwm输出IO_PORTA_02
.mode = GPTIMER_MODE_PWM, //设置工作模式
};
u32 id = gptimer_init(TIMERx, &pwm_config);
printf("pwm_demo id:%d\n", id);
gpio_set_mode(PORTC, BIT(3), PORT_OUTPUT_LOW); //IO口设为输出
gptimer_start(id); //启动timer
}
#endif
static void capture_demo()
{
printf("capture_demo()\n");
const struct gptimer_config capture_config = {
.capture.filter = 1000, //设置滤波频率, 1000Hz
.capture.max_period = 0,//110000, //最大计时周期, 单位us, 默认给0
.capture.port = PORTA, //设置捕获口IO_PORTA_04
.capture.pin = BIT(3), //设置捕获口IO_PORTA_04
.irq_cb = timer_callback_func_2, //设置回调函数
.irq_priority = 3, //设置捕获中断优先级
.mode = GPTIMER_MODE_CAPTURE_EDGE_ANYEDGE, //设置工作模式
};
u32 id = gptimer_init(TIMERx, &capture_config);
printf("capture_demo id:%d\n", id);
gpio_set_mode(PORTA, BIT(3), PORT_INPUT_FLOATING); //IO口设为浮空输入
gptimer_start(id); //启动timer
gptimer_set_capture_filter(id, 100000); //设置滤波参数为10000Hz
gptimer_set_capture_count(id, 0); //设置cnt寄存器
u32 cnt = gptimer_get_capture_count(id);
printf("capture cnt = %d\n", cnt);
u32 us = gptimer_get_capture_cnt2us(id); //获取捕获时间间隔, 单位:us
printf("capture_us = %dus \n", us);
}
static void measure_demo()
{
printf("measure_demo()\n");
u32 id = gptimer_measure_time_init(TIMER2, 0);
u32 time_us;
while (1) {
gptimer_measure_time_start(id);
gpio_set_mode(PORTC, BIT(3), PORT_OUTPUT_HIGH);
udelay(10000); //需配合示波器或逻辑分析仪测量IO间隔时间
gpio_set_mode(PORTC, BIT(3), PORT_OUTPUT_LOW);
time_us = gptimer_measure_time_end(id);
printf("time_us = %d\n", time_us);
udelay(500 * 1000);
wdt_clear();
}
}
static void other_api_demo()
{
printf("other_demo()\n");
u32 id = 0; // 这里仅演示接口用法, id 需 init 申请成功后才可使用
u32 cnt = 0;
gptimer_set_count(id, cnt); //设置cnt寄存器值
cnt = gptimer_get_count(id); //获取cnt寄存器值
printf("other_demo cnt:%d\n", cnt);
u32 prd = 0;
gptimer_set_prd(id, prd); //设置prd寄存器值
prd = gptimer_get_prd(id); //获取prd寄存器值
printf("other_demo prd:%d\n", prd);
u8 private_data[8];
gptimer_set_private_data(id, private_data); //设置私有参数
u8 *p = gptimer_get_private_data(id); //获取私有参数
put_buf(p, 8);
}
//直接造作寄存器,实现特殊需求定时功能
static void custom_timer_demo()
{
printf("custom_timer_demo()\n");
//以 TIMER0 输出 pwm 为例, 输出7.68KHz, 占空比50.00%的pwm
//根据芯片型号选择不同的demo
JL_TIMER_TypeDef *TIMER = JL_TIMER0;
printf("TIMER 0x%x\n", (u32)TIMER);
#if 0 //适用于br29
SFR(JL_PLL0->CON2, 21, 1, 1);
SFR(JL_PLL0->CON2, 14, 1, 1); //sys_pll_d2p5 时钟使能
SFR(JL_CLOCK->STD_CON1, 10, 4, 6); //clk_out2 选择时钟源为 sys_pll_d2p5
SFR(JL_CLOCK->STD_CON1, 14, 6, 9); //clk_out2 选择预分频系数为 (9+1)
//按如上配置,系统时钟为192 * 1000000 Hz时,clk_out2 = 192000000 / 2.5 / 10 = 7.68 * 1000000 Hz
SFR(TIMER->CON, 10, 4, 8); //timer 选择时钟源为 clk_out2
SFR(TIMER->CON, 4, 4, 0); //timer 选择预分频系数为 1
//按如上配置,timer_clk = 7.68 * 1000000 / 1 = 7.68 * 1000000 Hz
//注意:最终需要满足 timer_clk <= (lsb_clk / 2)
SFR(TIMER->CON, 8, 1, 1); //pwm功能使能
TIMER->PRD = 1000; //设置 PRD 寄存器为 1000, pwm输出频率为 7.68 * 1000000 / 1000 = 7.68 * 1000 Hz;
TIMER->PWM = 500; //设置 PWM 寄存器为 500, pwm输出占空比为 500 / 1000 * 100% = 50.00%
gpio_set_function(IO_PORT_SPILT(IO_PORTA_00), PORT_FUNC_TIMER0_PWM); //pwm配置输出IO
gpio_set_mode(IO_PORT_SPILT(IO_PORTA_00), PORT_OUTPUT_LOW);
SFR(TIMER->CON, 0, 2, 0b01); //timer启动
#endif
#if 0 //适用于bd47
SFR(JL_PLL0->CON1, 15, 1, 1); //sys_pll_d2p5 时钟使能
SFR(JL_CLOCK->STD_CON1, 10, 4, 6); //clk_out2 选择时钟源为 sys_pll_d2p5
SFR(JL_CLOCK->STD_CON1, 14, 6, 9); //clk_out2 选择预分频系数为 (9+1)
//按如上配置,系统时钟为192 * 1000000 Hz时,clk_out2 = 192000000 / 2.5 / 10 = 7.68 * 1000000 Hz
SFR(TIMER->CON, 10, 4, 8); //timer 选择时钟源为 clk_out2
SFR(TIMER->CON, 4, 4, 0); //timer 选择预分频系数为 1
//按如上配置,timer_clk = 7.68 * 1000000 / 1 = 7.68 * 1000000 Hz
//注意:最终需要满足 timer_clk <= (lsb_clk / 2)
SFR(TIMER->CON, 8, 1, 1); //pwm功能使能
TIMER->PRD = 1000; //设置 PRD 寄存器为 1000, pwm输出频率为 7.68 * 1000000 / 1000 = 7.68 * 1000 Hz;
TIMER->PWM = 500; //设置 PWM 寄存器为 500, pwm输出占空比为 500 / 1000 * 100% = 50.00%
gpio_set_function(IO_PORT_SPILT(IO_PORTA_00), PORT_FUNC_TIMER0_PWM); //pwm配置输出IO
gpio_set_mode(IO_PORT_SPILT(IO_PORTA_00), PORT_OUTPUT_LOW);
SFR(TIMER->CON, 0, 2, 0b01); //timer启动
#endif
#if 0 //clk_out2 输出到IO测试
/* SFR(JL_PLL0->CON2, 11, 5, 0b11111); //sys_pll_d2p5 时钟使能 */
/* SFR(JL_CLOCK->STD_CON1, 10, 4, 6); //clk_out2 选择时钟源为 sys_pll_d2p5 */
/* SFR(JL_CLOCK->STD_CON1, 14, 6, 9); //clk_out2 选择预分频系数为 (9+1) */
/* gpio_set_mode(IO_PORT_SPILT(IO_PORTA_00), PORT_OUTPUT_LOW); */
SFR(JL_PLL0->CON2, 21, 1, 1);
clk_out2(IO_PORTA_00, CLK_OUT_SRC1_SYS_PLL_D2P0, 0);
printf("JL_PLL0->CON0 0x%x\n", JL_PLL0->CON0);
printf("JL_PLL0->CON2 0x%x\n", JL_PLL0->CON2);
#endif
}
#if 0 //外部时钟输入demo
static void timer_callback_func_3(u32 tid, void *private_data)
{
putchar('t');
//可以翻转IO口测量时间
gpio_set_mode(PORTC, BIT(11), PORT_OUTPUT_HIGH);
gpio_set_mode(PORTC, BIT(11), PORT_OUTPUT_LOW);
}
static void timer_extern_clk_demo()
{
printf("timer_extern_clk_demo()\n");
const struct gptimer_config timer_config = {
.timer.period_us = 1 * 1000 * 1000,
.irq_cb = timer_callback_func_3,
.irq_priority = 1,
.mode = GPTIMER_MODE_TIMER,
.private_data = NULL,
};
u32 id = gptimer_init(TIMERx, &timer_config);
printf("func:%s(), timer_id:%d\n", __func__, id);
//设置IO_PORTC_11为外部时钟输入脚, 频率 1K
gptimer_set_extern_clk(id, 1000, PORTC, BIT(10), 1);
gpio_set_mode(PORTC, BIT(10), PORT_INPUT_FLOATING);
gptimer_start(id); //启动timer
}
#endif
#if 0//使用gptimer 作脉冲计数功能, 不同芯片的最大计数值不一样那个, br35最大为 (0xffff)
#include "asm/power_interface.h"
static u8 pluse_detect_idle;
static u8 pluse_detect_idle_query(void)
{
return pluse_detect_idle;
}
REGISTER_LP_TARGET(pluse_detect_lp_target) = {
.name = "pluse_detect",
.is_idle = pluse_detect_idle_query,
};
static u32 user_id;
static void user_pluse_detect_timer_func(void *priv)
{
gptimer_pause(user_id);
u32 cnt = gptimer_get_count(user_id);
gptimer_set_count(user_id, 0);
gptimer_resume(user_id);
if (pluse_detect_idle) {
printf("Invalid data user_pluse_cnt:%d\n", cnt); //无效数据,忽略
} else {
printf("Valid data user_pluse_cnt:%d\n", cnt); //有效数据,添加处理流程
}
pluse_detect_idle ^= 1;
}
static void user_pulse_detec_demo()
{
printf("user_pulse_detec_demo()\n");
const struct gptimer_config timer_config = {
.timer.period_us = 0,
.irq_cb = NULL,
.irq_priority = 0,
.mode = GPTIMER_MODE_TIMER,
.private_data = NULL,
};
user_id = gptimer_init(TIMERx, &timer_config); //初始化timer配置,成功会返回分配的timer_id, 失败返回-1
printf("func:%s(), timer_id:%d\n", __func__, user_id);
//设置IO_PORTC_11 为外部时钟输入脚, 频率 1K
u16 gpio = IO_PORTC_10;
u32 extern_clk = 1000;
gptimer_set_extern_clk(user_id, extern_clk, IO_PORT_SPILT(gpio), 1);
gpio_set_mode(IO_PORT_SPILT(gpio), PORT_INPUT_FLOATING);
sys_timer_add(NULL, user_pluse_detect_timer_func, 1000); //定时1s读取脉冲数
gptimer_set_prd(user_id, 0xffff);
gptimer_start(user_id); //启动timer
}
#endif
void gptimer_test_demo()
{
udelay(1 * 1000 * 1000);
/* timer_demo(); */
/* pwm_demo(); */
/* capture_demo(); */
/* measure_demo(); */
/* other_api_demo(); */
/* custom_timer_demo(); */
/* timer_extern_clk_demo(); */
/* user_pulse_detec_demo(); */
gptimer_dump();
while (1) {
wdt_clear();
}
}
#if 0 //直接操作寄存器的 timer_demo
#define USER_CUSTOM_TIMER JL_TIMER0
#define USER_CUSTOM_TIMER_IDX IRQ_TIME0_IDX
___interrupt
void user_custom_timer_irq_callback()
{
USER_CUSTOM_TIMER->CON |= BIT(14); //清PND
}
void user_custom_timer_init(u32 time_us)
{
USER_CUSTOM_TIMER->CON = ((0b1 << 14) | (0b0101 << 10) | (0b0000 << 4));
USER_CUSTOM_TIMER->CNT = 0;
USER_CUSTOM_TIMER->PRD = time_us * 12 - 1; //注意不能为0
request_irq(USER_CUSTOM_TIMER_IDX, 1, user_custom_timer_irq_callback, 0);
}
void user_custom_timer_start()
{
USER_CUSTOM_TIMER->CON |= BIT(0);
}
void user_custom_timer_pause()
{
USER_CUSTOM_TIMER->CON &= ~BIT(0);
}
void user_custom_timer_set_period(u32 time_us)
{
USER_CUSTOM_TIMER->PRD = time_us * 12 - 1; //注意不能为0
}
void user_custom_timer_set_cnt(u32 cnt)
{
USER_CUSTOM_TIMER->CNT = cnt;
}
#endif