/** ************************************************************************** * @file main.c * @brief main program ************************************************************************** * Copyright notice & Disclaimer * * The software Board Support Package (BSP) that is made available to * download from Artery official website is the copyrighted work of Artery. * Artery authorizes customers to use, copy, and distribute the BSP * software and its related documentation for the purpose of design and * development in conjunction with Artery microcontrollers. Use of the * software is governed by this copyright notice and the following disclaimer. * * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES, * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS, * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS, * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. * ************************************************************************** */ #include "at32f421_board.h" #include "at32f421_clock.h" #include "FreeRTOS.h" #include "task.h" #include "cmcng.h" #include "TaskLoop.h" /** @addtogroup UTILITIES_examples * @{ */ /** @addtogroup FreeRTOS_demo * @{ */ crm_clocks_freq_type g_crm_clocks_freq_struct = {0}; tmr_input_config_type g_tmr_input_config_struct; __IO uint32_t sys_counter = 0; //uint8_t g_input_div = 1; TaskHandle_t loop_task_handler; tmr_output_config_type tmr_oc_init_structure; /* pb1 output pwm waveform, use Tmr14. tmr3 channel1 duty cycle = (tmr3_c1dt/ tmr3_pr)* 100 = 50% tmr3 channel2 duty cycle = (tmr3_c2dt/ tmr3_pr)* 100 = 37.5% tmr3 channel3 duty cycle = (tmr3_c3dt/ tmr3_pr)* 100 = 25% tmr3 channel4 duty cycle = (tmr3_c4dt/ tmr3_pr)* 100 = 12.5% */ uint16_t c1dt_val = 333; //uint16_t c2dt_val = 249; //uint16_t c3dt_val = 166; //uint16_t c4dt_val = 83; uint16_t prescaler_value = 0; __IO uint16_t pulse=0;//55; //脉冲宽度 uint8_t g_pulse_counter = 0; uint8_t g_flag_pulse = 1; /* Basic timr6 */ void Timr6_Init(void) { crm_periph_clock_enable(CRM_TMR6_PERIPH_CLOCK, TRUE); //TODO: 定时的计算方法 // tmr_base_init(TMR6, 9999, (g_crm_clocks_freq_struct.ahb_freq / 10000) - 1); // 1s tmr_base_init(TMR6, 999, (g_crm_clocks_freq_struct.ahb_freq / 1000000) - 1); // 1ms tmr_cnt_dir_set(TMR6, TMR_COUNT_UP); tmr_interrupt_enable(TMR6, TMR_OVF_INT, TRUE); nvic_irq_enable(TMR6_GLOBAL_IRQn, 0, 0); tmr_counter_enable(TMR6, TRUE); // crm_periph_clock_enable(CRM_TMR14_PERIPH_CLOCK, TRUE); // // //TODO: 定时的计算方法 //// tmr_base_init(TMR6, 9999, (g_crm_clocks_freq_struct.ahb_freq / 10000) - 1); // 1s // tmr_base_init(TMR14, (5000-1), (g_crm_clocks_freq_struct.ahb_freq / 1000000) - 1); // 5ms //// tmr_base_init(TMR14, 9999, (g_crm_clocks_freq_struct.ahb_freq / 1000000) - 1); // 10ms // // // tmr_cnt_dir_set(TMR14, TMR_COUNT_UP); // // tmr_interrupt_enable(TMR14, TMR_OVF_INT, TRUE); // // nvic_irq_enable(TMR14_GLOBAL_IRQn, 0, 0); // // tmr_counter_enable(TMR14, TRUE); crm_periph_clock_enable(CRM_TMR15_PERIPH_CLOCK, TRUE); //TODO: 定时的计算方法 // tmr_base_init(TMR6, 9999, (g_crm_clocks_freq_struct.ahb_freq / 10000) - 1); // 1s tmr_base_init(TMR15, (5000-1), (g_crm_clocks_freq_struct.ahb_freq / 1000000) - 1); // 5ms // tmr_base_init(TMR14, 9999, (g_crm_clocks_freq_struct.ahb_freq / 1000000) - 1); // 10ms tmr_cnt_dir_set(TMR15, TMR_COUNT_UP); tmr_interrupt_enable(TMR15, TMR_OVF_INT, TRUE); nvic_irq_enable(TMR15_GLOBAL_IRQn, 0, 0); tmr_counter_enable(TMR15, TRUE); gpio_init_type gpio_init_struct; gpio_default_para_init(&gpio_init_struct); gpio_init_struct.gpio_pins = GPIO_PINS_1; gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; gpio_init_struct.gpio_mode = GPIO_MODE_MUX; gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_init(GPIOB, &gpio_init_struct); gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE1, GPIO_MUX_0); crm_periph_clock_enable(CRM_TMR14_PERIPH_CLOCK, TRUE); /* compute the prescaler value */ prescaler_value = (uint16_t)(system_core_clock / 24000000) - 1; tmr_base_init(TMR14, 665, prescaler_value); tmr_cnt_dir_set(TMR14, TMR_COUNT_UP); tmr_clock_source_div_set(TMR14, TMR_CLOCK_DIV1); tmr_output_default_para_init(&tmr_oc_init_structure); tmr_oc_init_structure.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A; tmr_oc_init_structure.oc_idle_state = FALSE; tmr_oc_init_structure.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH; tmr_oc_init_structure.oc_output_state = TRUE; c1dt_val = 670; tmr_output_channel_config(TMR14, TMR_SELECT_CHANNEL_1, &tmr_oc_init_structure); tmr_channel_value_set(TMR14, TMR_SELECT_CHANNEL_1, c1dt_val); tmr_output_channel_buffer_enable(TMR14, TMR_SELECT_CHANNEL_1, TRUE); tmr_period_buffer_enable(TMR14, TRUE); /* tmr enable counter */ tmr_counter_enable(TMR14, TRUE); } /*=========================================================================== * 红灯呼吸 (PB1 / TMR14 PWM) — V4.23: 呼吸节奏对齐 vd960Loop (LED_PWR) * * vd960Loop 参考 (周期≈2.6s, 60ms/步): 满量程 6800 * 升: <6000 大步 +400(≈5.9%), ≥6000 小步 +100(≈1.5%) * 峰值保持 3 步后回落; 降: -400(≈5.9%) * V4B PWM 满量程 = TMR14 ARR 665, 参数按 665/6800 ≈ 0.0978 缩放取整: * 大歩 39(≈5.9%) / 小步 10(≈1.5%) / 分界 585(≈88%) / 峰值保持 660(≈99%) * 全周期 ≈ 2.6s, 与 vd960Loop 观感一致 *===========================================================================*/ #define RED_BREATH_ARR 665 /* 必须与 tmr_base_init(TMR14,665,...) 一致 */ #define RED_STEP_BIG 39 /* 低段升/全程降步长 ≈ 400×665/6800 */ #define RED_STEP_SMALL 10 /* 近顶小步 ≈ 100×665/6800 */ #define RED_SPLIT 585 /* 大步/小步分界 ≈ 6000×665/6800 (88%) */ #define RED_HOLD_LEVEL 660 /* 峰值保持占空比 (≈99%) */ #define RED_HOLD_TICKS 3 /* 峰值保持 3 步 × 60ms = 180ms */ uint8_t g_cnt_pwm_red_low_timeout = 0; void poll_red_pwm(void) { g_pulse_counter++; if (g_pulse_counter >= 12) { /* 12 × 5ms = 60ms/步 (同 vd960Loop) */ g_pulse_counter = 0; if (g_flag_pulse) { /* 渐亮: 低段大步, 近顶小步 */ if (pulse < RED_SPLIT) pulse += RED_STEP_BIG; else pulse += RED_STEP_SMALL; /* 到最亮: 保持 RED_HOLD_TICKS 步再回落 */ if (pulse >= RED_BREATH_ARR) { g_cnt_pwm_red_low_timeout++; if (g_cnt_pwm_red_low_timeout >= RED_HOLD_TICKS) { g_flag_pulse = 0; g_cnt_pwm_red_low_timeout = 0; } pulse = RED_HOLD_LEVEL; } } else { /* 渐暗 */ if (pulse <= RED_STEP_BIG) { pulse = 0; g_flag_pulse = 1; } else { pulse -= RED_STEP_BIG; } } tmr_channel_value_set(TMR14, TMR_SELECT_CHANNEL_1, pulse); } } /** * @brief main function. * @param none * @retval none */ int main(void) { nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); system_clock_config(); /* get system clock */ crm_clocks_freq_get(&g_crm_clocks_freq_struct); at32_board_init(); /* init usart1 */ //2250000 // 115200 #ifdef DEBUG uart_print_init(230400); //115200 PRINT("sys_clock:%d, ahb_freq:%d, sclk_freq:%d\n", system_core_clock, g_crm_clocks_freq_struct.ahb_freq, g_crm_clocks_freq_struct.sclk_freq); #endif loop_timer_io_init(); Timr6_Init(); wdt_init(); // IWDT 看门狗使能 (超时约1.64s), 主循环 poll_wdg() 喂狗 /* enter critical */ taskENTER_CRITICAL(); /* create loop task */ if(xTaskCreate((TaskFunction_t )loop_task_function, (const char* )"Loop_task", (uint16_t )512, (void* )NULL, (UBaseType_t )2, (TaskHandle_t* )&loop_task_handler) != pdPASS) { PRINT("loop task could not be created as there was insufficient heap memory remaining.\r\n"); } else { PRINT("loop task was created successfully.\r\n"); } /* exit critical */ taskEXIT_CRITICAL(); /* start scheduler */ vTaskStartScheduler(); } uint8_t g_flag_output = 0; uint8_t g_flag_output2 = 0; // 1ms interval void TMR6_GLOBAL_IRQHandler(void) { static uint16_t _cnt_5ms = 0; static uint32_t _cnt = 0; if(tmr_interrupt_flag_get(TMR6, TMR_OVF_FLAG) != RESET) { #ifdef DEBUG _cnt++; if(_cnt >= 2000){ g_flag_output = 1; _cnt = 0; } #endif tmr_flag_clear(TMR6, TMR_OVF_FLAG); } } /** * @} */ /** * @} */