#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