USART - Design Flow

本文详细介绍了USART的设计流程,包括波特率时钟生成、发送器、接收器的FSM设计和时序设计,以及如何在顶层模块中整合USART与APB接口。在接收器部分,特别强调了同步串口的采样时序问题和解决办法,同时提供了测试 bench 的回环测试方案。


可以参照uart进行设计,但是还是那句话——设计好再写代码!设计好再写代码!着急写代码是吧,着急写就白想活着!

1. baud_clk_gen

根据波特率分频出一个sck时钟,注意使用ODDR实现了时钟移相180°,以实现下降沿驱动

1.1. RTL Coding

module baud_clk_gen#(
	parameter	BAUD_RATE	=	12500000,
	parameter	PCLK_FREQ	=	50000000
	)(
		input	prstn_sck,
		in
/* add user code begin Header */ /** ************************************************************************** * @file at32a423_int.c * @brief main interrupt service routines. ************************************************************************** * 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. * ************************************************************************** */ /* add user code end Header */ /* includes ------------------------------------------------------------------*/ #include "at32a423_int.h" #include "wk_system.h" volatile uint32_t flow_pulse_count = 0; // 脉冲计数 volatile uint32_t flow_frequency_hz = 0; // 测量频率(Hz) float flow_rate_l_min = 0.0f; // 流量值(L/min) uint32_t last_measure_time = 0;// 上次测量时间戳 static uint32_t interrupt_count = 0; #define FRAME_MAX_LEN 64 // 定义最大帧长度 typedef enum { UART_RX_IDLE = 0, // 空闲状态 UART_RX_RECEIVING, // 接收中状态 UART_RX_COMPLETE // 接收完成状态 } UART_RX_Status; typedef struct { uint8_t buffer[FRAME_MAX_LEN]; // 接收缓冲区 uint16_t index; // 当前接收位置 uint16_t length; // 帧长度 UART_RX_Status status; // 接收状态 uint8_t frameComplete; // 帧接收完成标志 } UART_RX_Handler; UART_RX_Handler uart3_rx; //#define PULSES_PER_LITER 450 // 每升水对应的脉冲数 //#define MEASURE_INTERVAL 1000 // 测量间隔(ms) /* private includes ----------------------------------------------------------*/ /* add user code begin private includes */ /* add user code end private includes */ /* private typedef -----------------------------------------------------------*/ /* add user code begin private typedef */ /* add user code end private typedef */ /* private define ------------------------------------------------------------*/ /* add user code begin private define */ /* add user code end private define */ /* private macro -------------------------------------------------------------*/ /* add user code begin private macro */ /* add user code end private macro */ /* private variables ---------------------------------------------------------*/ /* add user code begin private variables */ /* add user code end private variables */ /* private function prototypes --------------------------------------------*/ /* add user code begin function prototypes */ /* add user code end function prototypes */ /* private user code ---------------------------------------------------------*/ /* add user code begin 0 */ /* add user code end 0 */ /* external variables ---------------------------------------------------------*/ /* add user code begin external variables */ /* add user code end external variables */ /** * @brief this function handles nmi exception. * @param none * @retval none */ void NMI_Handler(void) { /* add user code begin NonMaskableInt_IRQ 0 */ /* add user code end NonMaskableInt_IRQ 0 */ /* add user code begin NonMaskableInt_IRQ 1 */ /* add user code end NonMaskableInt_IRQ 1 */ } /** * @brief this function handles hard fault exception. * @param none * @retval none */ void HardFault_Handler(void) { /* add user code begin HardFault_IRQ 0 */ /* add user code end HardFault_IRQ 0 */ /* go to infinite loop when hard fault exception occurs */ while (1) { /* add user code begin W1_HardFault_IRQ 0 */ /* add user code end W1_HardFault_IRQ 0 */ } } /** * @brief this function handles memory manage exception. * @param none * @retval none */ void MemManage_Handler(void) { /* add user code begin MemoryManagement_IRQ 0 */ /* add user code end MemoryManagement_IRQ 0 */ /* go to infinite loop when memory manage exception occurs */ while (1) { /* add user code begin W1_MemoryManagement_IRQ 0 */ /* add user code end W1_MemoryManagement_IRQ 0 */ } } /** * @brief this function handles bus fault exception. * @param none * @retval none */ void BusFault_Handler(void) { /* add user code begin BusFault_IRQ 0 */ /* add user code end BusFault_IRQ 0 */ /* go to infinite loop when bus fault exception occurs */ while (1) { /* add user code begin W1_BusFault_IRQ 0 */ /* add user code end W1_BusFault_IRQ 0 */ } } /** * @brief this function handles usage fault exception. * @param none * @retval none */ void UsageFault_Handler(void) { /* add user code begin UsageFault_IRQ 0 */ /* add user code end UsageFault_IRQ 0 */ /* go to infinite loop when usage fault exception occurs */ while (1) { /* add user code begin W1_UsageFault_IRQ 0 */ /* add user code end W1_UsageFault_IRQ 0 */ } } /** * @brief this function handles svcall exception. * @param none * @retval none */ void SVC_Handler(void) { /* add user code begin SVCall_IRQ 0 */ /* add user code end SVCall_IRQ 0 */ /* add user code begin SVCall_IRQ 1 */ /* add user code end SVCall_IRQ 1 */ } /** * @brief this function handles debug monitor exception. * @param none * @retval none */ void DebugMon_Handler(void) { /* add user code begin DebugMonitor_IRQ 0 */ /* add user code end DebugMonitor_IRQ 0 */ /* add user code begin DebugMonitor_IRQ 1 */ /* add user code end DebugMonitor_IRQ 1 */ } /** * @brief this function handles pendsv_handler exception. * @param none * @retval none */ void PendSV_Handler(void) { /* add user code begin PendSV_IRQ 0 */ /* add user code end PendSV_IRQ 0 */ /* add user code begin PendSV_IRQ 1 */ /* add user code end PendSV_IRQ 1 */ } /** * @brief this function handles systick handler. * @param none * @retval none */ void SysTick_Handler(void) { /* add user code begin SysTick_IRQ 0 */ /* add user code end SysTick_IRQ 0 */ wk_timebase_handler(); /* add user code begin SysTick_IRQ 1 */ /* add user code end SysTick_IRQ 1 */ } /** * @brief this function handles ADC1 handler. * @param none * @retval none */ void ADC1_IRQHandler(void) { /* add user code begin ADC1_IRQ 0 */ /* add user code end ADC1_IRQ 0 */ /* add user code begin ADC1_IRQ 1 */ /* add user code end ADC1_IRQ 1 */ } void USART3_IRQHandler(void) { /* add user code begin USART1_IRQ 0 */ uint16_t reval; // time_ira_cnt = 0; /* clear upgrade time out flag */ if(usart_flag_get(USART3, USART_RDBF_FLAG) != RESET) { reval = usart_data_receive(USART3); if(reval == 0x5A&& uart3_rx.status == UART_RX_IDLE) //帧头5A { uart3_rx.status = UART_RX_RECEIVING; uart3_rx.index = 0; uart3_rx.buffer[uart3_rx.index++] = reval; } else if(uart3_rx.status == UART_RX_RECEIVING) { // 保存接收到的 uart3_rx.buffer[uart3_rx.index++] = reval; // 帧尾检测 (假设帧尾是0xA5) if(reval == 0xA5) { uart3_rx.length = uart3_rx.index; uart3_rx.status = UART_RX_COMPLETE; uart3_rx.frameComplete = 1; } // 检查是否超出最大长度 else if(uart3_rx.index >= FRAME_MAX_LEN) { uart3_rx.status = UART_RX_IDLE; uart3_rx.index = 0; } } } /* add user code end USART1_IRQ 0 */ /* add user code begin USART1_IRQ 1 */ if(usart_flag_get(USART3, USART_RDBF_FLAG) != RESET) { usart_flag_clear(USART3, USART_RDBF_FLAG); } /* add user code end USART1_IRQ 1 */ } void Process_UART_Frame(void) { // int i; if(uart3_rx.frameComplete) { uint8_t amd; // 解析帧数据 // 示例:假设帧格式为 [0xAA][命令][数据1][数据2]...[0x55] amd = uart3_rx.buffer[1]; // 命令字节 switch(amd) { case 0x03: // 处理03命令 if(uart3_rx.buffer[0] == 0x5A && uart3_rx.buffer[2] == 0xA5) { Send_FlowData_To_USART3(); // 发送流量数据 } break; // case 13:Trigger_Usart_Read(USART_TARGET_2);break; // case 23:Trigger_Usart_Read(USART_TARGET_1);break; // case 33:Trigger_Usart_Read(USART_TARGET_5);break; // case 43: Send_Feedback_Frame(0x03);break; } // 处理完成后重置接收状态 uart3_rx.frameComplete = 0; uart3_rx.status = UART_RX_IDLE; uart3_rx.index = 0; // buffer_position = 0; // 重新启动接收 } } /* add user code begin 1 */ //gpio_init_type gpio_init_struct = {0}; //crm_clocks_freq_type crm_clocks_freq_struct = {0}; //tmr_input_config_type tmr_input_config_struct; //void delay(uint32_t time); //void uart_init(uint32_t bound); //__IO uint32_t tmr3freq = 0; //__IO uint32_t sys_counter = 0; __IO uint16_t capture_count = 0; __IO uint16_t first_capture = 0, second_capture = 0; __IO uint32_t capture_value = 0; volatile uint32_t overflow_count = 0; // 软件溢出计数器 /* add user code end 1 */ void TMR2_IRQHandler(void) { if (tmr_interrupt_flag_get(TMR2, TMR_C1_FLAG) == SET) { tmr_flag_clear(TMR2, TMR_C1_FLAG); if (capture_count == 0) { first_capture = tmr_channel_value_get(TMR2, TMR_SELECT_CHANNEL_1); capture_count = 1; } else { second_capture = tmr_channel_value_get(TMR2, TMR_SELECT_CHANNEL_1); if (second_capture > first_capture) { capture_value = second_capture - first_capture; } else { capture_value = (0xFFFF - first_capture) + second_capture; } if (capture_value > 0) { uint32_t timer_freq = 24000000; // 假设TMR2时钟为24MHz flow_frequency_hz = timer_freq / capture_value; flow_pulse_count ++; // 每个完整周期计数一次 } capture_count = 0; } } } void TMR2_GLOBAL_IRQHandler(void) { // interrupt_count++; if (tmr_interrupt_flag_get(TMR2, TMR_OVF_FLAG) == SET) { tmr_flag_clear(TMR2, TMR_OVF_FLAG); // 清除溢出标志 overflow_count++; // 溢出次数加1 } if (tmr_interrupt_flag_get(TMR2, TMR_C1_FLAG) == SET) { // 通过串口输出调试信息 tmr_flag_clear(TMR2, TMR_C1_FLAG); flow_pulse_count ++; } } void Calculate_FlowRate(void) { static uint32_t last_pulse_count = 0; uint32_t pulses_in_interval; // 计算时间间隔内的脉冲数 pulses_in_interval = flow_pulse_count - last_pulse_count; last_pulse_count = flow_pulse_count; // 计算频率 (Hz) flow_frequency_hz = (pulses_in_interval * 1000) / MEASURE_INTERVAL; // 计算流量 (L/min) = (脉冲数/脉冲每升) × (60/时间间隔秒) flow_rate_l_min = (pulses_in_interval / (float)PULSES_PER_LITER) * (60.0f / (MEASURE_INTERVAL / 1000.0f)); } void Send_FlowData_To_USART3(void) { uint8_t tx_buffer[10]; // 发送缓冲区 uint8_t checksum = 0; // 校验和 uint8_t i; uint8_t j; // 1. 获取流量数据(根据你的实际数据源选择) uint32_t flow_data = flow_pulse_count; // 使用脉冲计数 // 或者: uint32_t flow_data = (uint32_t)(flow_rate_l_min * 100); // 使用流量值(放大100倍) // 2. 构建数据帧 tx_buffer[0] = 0x5A; // 帧头 tx_buffer[1] = 0x03; // 命令字(请求流量数据) tx_buffer[2] = 0x04; // 数据长度(4字节) // 将32位流量数据分解为4个字节(小端序) tx_buffer[3] = (flow_data >> 0) & 0xFF; // 最低字节 tx_buffer[4] = (flow_data >> 8) & 0xFF; tx_buffer[5] = (flow_data >> 16) & 0xFF; tx_buffer[6] = (flow_data >> 24) & 0xFF; // 最高字节 // 3. 计算校验和(从命令字到数据末尾) for( j = 1; j < 7; j++) { checksum ^= tx_buffer[j]; // 异或校验 } tx_buffer[7] = checksum; tx_buffer[8] = 0xA5; // 帧尾 // 4. 通过USART3发送数据 for( i = 0; i < 9; i++) { // 等待发送缓冲区为空 while(usart_flag_get(USART3, USART_TDBE_FLAG) == RESET) { // 可添加超时处理 } // 发送数据字节[6](@ref) usart_data_transmit(USART3, tx_buffer[i]); } // 5. 等待最后字节发送完成 // while(usart_flag_get(USART3, USART_FLAG_TC) == RESET) { // 确保所有数据都已物理发送完成 } /* add user code begin Header */ /** ************************************************************************** * @file at32a423_wk_config.c * @brief work bench config 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. * ************************************************************************** */ /* add user code end Header */ #include "at32a423_wk_config.h" //#define PULSES_PER_LITER 450 // 每升水对应的脉冲数 //volatile uint32_t pulse_count = 0; //float flow_rate_l_min = 0.0f; static __IO uint32_t fac_us; static __IO uint32_t fac_ms; #define STEP_DELAY_MS 50 gpio_init_type gpio_init_struct = {0}; crm_clocks_freq_type crm_clocks_freq_struct = {0}; /* private includes ----------------------------------------------------------*/ /* add user code begin private includes */ /* add user code end private includes */ /* private typedef -----------------------------------------------------------*/ /* add user code begin private typedef */ /* add user code end private typedef */ /* private define ------------------------------------------------------------*/ /* add user code begin private define */ /* add user code end private define */ /* private macro -------------------------------------------------------------*/ /* add user code begin private macro */ /* add user code end private macro */ /* private variables ---------------------------------------------------------*/ /* add user code begin private variables */ /* add user code end private variables */ /* private function prototypes --------------------------------------------*/ /* add user code begin function prototypes */ /* add user code end function prototypes */ /* private user code ---------------------------------------------------------*/ /* add user code begin 0 */ /* add user code end 0 */ /** * @brief system clock config program * @note the system clock is configured as follow: * system clock (sclk) = (hick / 6 * pll_ns)/(pll_ms * pll_fr) * system clock source = HICK_VALUE * - lick = on * - lext = off * - hick = on * - hext = off * - sclk = 150000000 * - ahbdiv = 1 * - ahbclk = 150000000 * - apb1div = 2 * - apb1clk = 75000000 * - apb2div = 1 * - apb2clk = 150000000 * - pll_ns = 75 * - pll_ms = 1 * - pll_fr = 2 * @param none * @retval none */ void wk_system_clock_config(void) { /* reset crm */ crm_reset(); /* config flash psr register */ flash_psr_set(FLASH_WAIT_CYCLE_4); /* enable pwc periph clock */ crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE); /* config ldo voltage */ pwc_ldo_output_voltage_set(PWC_LDO_OUTPUT_1V3); /* enable lick */ crm_clock_source_enable(CRM_CLOCK_SOURCE_LICK, TRUE); /* wait till lick is ready */ while(crm_flag_get(CRM_LICK_STABLE_FLAG) != SET) { } /* enable hick */ crm_clock_source_enable(CRM_CLOCK_SOURCE_HICK, TRUE); /* wait till hick is ready */ while(crm_flag_get(CRM_HICK_STABLE_FLAG) != SET) { } /* config pll clock resource common frequency config list: pll source selected hick or hext(8mhz) _____________________________________________________________________________ | | | | | | | | | | sysclk | 150 | 144 | 120 | 108 | 96 | 72 | 36 | |________|_________|_________|_________|_________|_________|_________________| | | | | | | | | | |pll_ns | 75 | 72 | 120 | 108 | 96 | 72 | 72 | | | | | | | | | | |pll_ms | 1 | 1 | 1 | 1 | 1 | 1 | 1 | | | | | | | | | | |pll_fr | FR_2 | FR_2 | FR_4 | FR_4 | FR_4 | FR_4 | FR_8 | |________|_________|_________|_________|_________|_________|________|________| if pll clock source selects hext with other frequency values, or configure pll to other frequency values, please use the at32 new clock configuration tool for configuration. */ crm_pll_config(CRM_PLL_SOURCE_HICK, 75, 1, CRM_PLL_FR_2); /* enable pll */ crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE); /* wait till pll is ready */ while(crm_flag_get(CRM_PLL_STABLE_FLAG) != SET) { } /* config ahbclk */ crm_ahb_div_set(CRM_AHB_DIV_1); /* config apb2clk, the maximum frequency of APB2 clock is 150 MHz */ crm_apb2_div_set(CRM_APB2_DIV_1); /* config apb1clk, the maximum frequency of APB1 clock is 120 MHz */ crm_apb1_div_set(CRM_APB1_DIV_2); /* enable auto step mode */ crm_auto_step_mode_enable(TRUE); /* select pll as system clock source */ crm_sysclk_switch(CRM_SCLK_PLL); /* wait till pll is used as system clock source */ while(crm_sysclk_switch_status_get() != CRM_SCLK_PLL) { } /* disable auto step mode */ crm_auto_step_mode_enable(FALSE); /* update system_core_clock global variable */ system_core_clock_update(); } /** * @brief config periph clock * @param none * @retval none */ void wk_periph_clock_config(void) { /* enable gpioa periph clock */ crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE); /* enable gpiob periph clock */ crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE); /* enable gpiof periph clock */ crm_periph_clock_enable(CRM_GPIOF_PERIPH_CLOCK, TRUE); /* enable tmr2 periph clock */ crm_periph_clock_enable(CRM_TMR2_PERIPH_CLOCK, TRUE); /* enable usart3 periph clock */ crm_periph_clock_enable(CRM_USART3_PERIPH_CLOCK, TRUE); /* enable usart1 periph clock */ crm_periph_clock_enable(CRM_USART1_PERIPH_CLOCK, TRUE); /* enable adc1 periph clock */ crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE); } /** * @brief nvic config * @param none * @retval none */ void wk_nvic_config(void) { nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0)); nvic_irq_enable(ADC1_IRQn, 0, 0); } /** * @brief init usart1 function * @param none * @retval none */ void wk_usart1_init(void) { /* add user code begin usart1_init 0 */ /* add user code end usart1_init 0 */ gpio_init_type gpio_init_struct; gpio_default_para_init(&gpio_init_struct); /* add user code begin usart1_init 1 */ /* add user code end usart1_init 1 */ /* configure the TX pin */ gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE; gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_mode = GPIO_MODE_MUX; gpio_init_struct.gpio_pins = GPIO_PINS_9; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; gpio_init(GPIOA, &gpio_init_struct); gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE9, GPIO_MUX_7); /* configure the RX pin */ gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE; gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_mode = GPIO_MODE_MUX; gpio_init_struct.gpio_pins = GPIO_PINS_10; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; gpio_init(GPIOA, &gpio_init_struct); gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE10, GPIO_MUX_7); /* config usart1 clock source */ crm_usart_clock_select(CRM_USART1, CRM_USART_CLOCK_SOURCE_PCLK); /* configure param */ usart_init(USART1, 115200, USART_DATA_8BITS, USART_STOP_1_BIT); usart_transmitter_enable(USART1, TRUE); usart_receiver_enable(USART1, TRUE); usart_parity_selection_config(USART1, USART_PARITY_NONE); usart_hardware_flow_control_set(USART1, USART_HARDWARE_FLOW_NONE); usart_enable(USART1, TRUE); /* add user code begin usart1_init 2 */ /* add user code end usart1_init 2 */ } /** * @brief init usart3 function * @param none * @retval none */ void wk_usart3_init(void) { /* add user code begin usart3_init 0 */ /* add user code end usart3_init 0 */ gpio_init_type gpio_init_struct; gpio_default_para_init(&gpio_init_struct); /* add user code begin usart3_init 1 */ /* add user code end usart3_init 1 */ /* configure the TX pin */ gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE; gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_mode = GPIO_MODE_MUX; gpio_init_struct.gpio_pins = GPIO_PINS_7; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; gpio_init(GPIOA, &gpio_init_struct); gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE7, GPIO_MUX_7); /* configure the RX pin */ gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE; gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_mode = GPIO_MODE_MUX; gpio_init_struct.gpio_pins = GPIO_PINS_5; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; gpio_init(GPIOA, &gpio_init_struct); gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE5, GPIO_MUX_7); /* config usart3 clock source */ crm_usart_clock_select(CRM_USART3, CRM_USART_CLOCK_SOURCE_PCLK); /* configure param */ usart_init(USART3, 115200, USART_DATA_8BITS, USART_STOP_1_BIT); usart_transmitter_enable(USART3, TRUE); usart_receiver_enable(USART3, TRUE); usart_parity_selection_config(USART3, USART_PARITY_NONE); usart_hardware_flow_control_set(USART3, USART_HARDWARE_FLOW_NONE); usart_enable(USART3, TRUE); usart_interrupt_enable(USART3, USART_RDBF_INT, TRUE); nvic_irq_enable(USART3_IRQn, 0, 0); // 设置合适的中断优先级 usart_enable(USART3, TRUE); /* add user code begin usart3_init 2 */ /* add user code end usart3_init 2 */ } /** * @brief init adc1 function. * @param none * @retval none */ void wk_adc1_init(void) { /* add user code begin adc1_init 0 */ /* add user code end adc1_init 0 */ gpio_init_type gpio_init_struct; adc_common_config_type adc_common_struct; adc_base_config_type adc_base_struct; gpio_default_para_init(&gpio_init_struct); /* add user code begin adc1_init 1 */ /* add user code end adc1_init 1 */ /* configure the IN0 pin */ gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG; gpio_init_struct.gpio_pins = GPIO_PINS_0; gpio_init(GPIOA, &gpio_init_struct); /* configure the IN1 pin */ gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG; gpio_init_struct.gpio_pins = GPIO_PINS_1; gpio_init(GPIOA, &gpio_init_struct); /* configure the IN2 pin */ gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG; gpio_init_struct.gpio_pins = GPIO_PINS_2; gpio_init(GPIOA, &gpio_init_struct); /* configure the IN3 pin */ gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG; gpio_init_struct.gpio_pins = GPIO_PINS_3; gpio_init(GPIOA, &gpio_init_struct); /* configure the IN4 pin */ gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG; gpio_init_struct.gpio_pins = GPIO_PINS_4; gpio_init(GPIOA, &gpio_init_struct); /* adc_common_settings--------------------------------------------------------------*/ /* config adc clock source */ crm_adc_clock_select(CRM_ADC_CLOCK_SOURCE_HCLK); adc_common_default_para_init(&adc_common_struct); /* config adc clock division */ adc_common_struct.div = ADC_HCLK_DIV_2; /* config inner temperature sensor and vintrv */ adc_common_struct.tempervintrv_state = FALSE; adc_common_config(&adc_common_struct); /* adc_settings------------------------------------------------------------------- */ adc_base_default_para_init(&adc_base_struct); adc_base_struct.sequence_mode = FALSE; adc_base_struct.repeat_mode = FALSE; adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT; adc_base_struct.ordinary_channel_length = 1; adc_base_config(ADC1, &adc_base_struct); /* adc_ordinary_conversionmode---------------------------------------------------- */ adc_ordinary_channel_set(ADC1, ADC_CHANNEL_0, 1, ADC_SAMPLETIME_6_5); adc_ordinary_conversion_trigger_set(ADC1, ADC_ORDINARY_TRIG_SOFTWARE, ADC_ORDINARY_TRIG_EDGE_NONE); /** * Users need to configure ADC1 interrupt functions according to the actual application. * 1. Call the below function to enable the corresponding ADC1 interrupt. * --adc_interrupt_enable(...) * 2. Add the user's interrupt handler code into the below function in the at32a423_int.c file. * --void ADC1_IRQHandler(void) */ adc_enable(ADC1, TRUE); while(adc_flag_get(ADC1, ADC_RDY_FLAG) == RESET); /* adc calibration---------------------------------------------------------------- */ adc_calibration_init(ADC1); while(adc_calibration_init_status_get(ADC1)); adc_calibration_start(ADC1); while(adc_calibration_status_get(ADC1)); /* add user code begin adc1_init 2 */ /* add user code end adc1_init 2 */ } /** * @brief init tmr2 function. * @param none * @retval none */ void wk_tmr2_init(void) { /* add user code begin tmr2_init 0 */ /* add user code end tmr2_init 0 */ gpio_init_type gpio_init_struct; tmr_input_config_type tmr_ic_init_struct; gpio_default_para_init(&gpio_init_struct); crm_periph_clock_enable(CRM_GPIOF_PERIPH_CLOCK, TRUE); // GPIOA时钟 crm_periph_clock_enable(CRM_TMR2_PERIPH_CLOCK, TRUE); // TIM2时钟 // crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE); // IO复用时钟 /* add user code begin tmr2_init 1 */ /* add user code end tmr2_init 1 */ /* configure the tmr2 CH1 pin */ gpio_init_struct.gpio_pins = GPIO_PINS_6; gpio_init_struct.gpio_mode = GPIO_MODE_INPUT; gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_pull = GPIO_PULL_UP; gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE; gpio_init(GPIOF, &gpio_init_struct); gpio_pin_mux_config(GPIOF, GPIO_PINS_SOURCE6, GPIO_MUX_1); /* configure counter settings */ tmr_base_init(TMR2, 0xffff, 0); tmr_cnt_dir_set(TMR2, TMR_COUNT_UP); tmr_clock_source_div_set(TMR2, TMR_CLOCK_DIV1); tmr_period_buffer_enable(TMR2, FALSE); /* configure primary mode settings */ tmr_sub_sync_mode_set(TMR2, FALSE); tmr_primary_mode_select(TMR2, TMR_PRIMARY_SEL_RESET); /* configure pwm input with ch1 */ // 配置输入捕获 tmr_ic_init_struct.input_filter_value = 0x0f; tmr_ic_init_struct.input_channel_select = TMR_SELECT_CHANNEL_1; tmr_ic_init_struct.input_mapped_select = TMR_CC_CHANNEL_MAPPED_DIRECT; tmr_ic_init_struct.input_polarity_select = TMR_INPUT_RISING_EDGE; tmr_pwm_input_config(TMR2, &tmr_ic_init_struct, TMR_CHANNEL_INPUT_DIV_1); tmr_trigger_input_select(TMR2, TMR_SUB_INPUT_SEL_C1DF1); tmr_sub_mode_select(TMR2, TMR_SUB_RESET_MODE); nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); // 启动计数器 nvic_irq_enable(TMR2_GLOBAL_IRQn, 1, 0); tmr_interrupt_enable(TMR2, TMR_C1_INT, TRUE); tmr_interrupt_enable(TMR2, TMR_OVF_INT, TRUE); // 启动计数器 tmr_counter_enable(TMR2, TRUE); /* add user code begin tmr2_init 2 */ /* add user code end tmr2_init 2 */ } void wk_tmr3_init(void) { /* add user code begin tmr3_init 0 */ /* add user code end tmr3_init 0 */ gpio_init_type gpio_init_struct; tmr_input_config_type tmr_input_struct; tmr_input_config_type tmr_ic_init_struct; gpio_default_para_init(&gpio_init_struct); /* add user code begin tmr3_init 1 */ /* add user code end tmr3_init 1 */ /* configure the tmr3 CH1 pin */ gpio_init_struct.gpio_pins = GPIO_PINS_6; gpio_init_struct.gpio_mode = GPIO_MODE_MUX; gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE; gpio_init(GPIOA, &gpio_init_struct); gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE6, GPIO_MUX_2); /* configure the tmr3 CH3 pin */ gpio_init_struct.gpio_pins = GPIO_PINS_0; gpio_init_struct.gpio_mode = GPIO_MODE_MUX; gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE; gpio_init(GPIOB, &gpio_init_struct); gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE0, GPIO_MUX_2); /* configure counter settings */ tmr_base_init(TMR3, 65535, 0); tmr_cnt_dir_set(TMR3, TMR_COUNT_UP); tmr_clock_source_div_set(TMR3, TMR_CLOCK_DIV1); tmr_period_buffer_enable(TMR3, FALSE); /* configure primary mode settings */ tmr_sub_sync_mode_set(TMR3, FALSE); tmr_primary_mode_select(TMR3, TMR_PRIMARY_SEL_RESET); /* configure channel 3 input settings */ tmr_input_struct.input_channel_select = TMR_SELECT_CHANNEL_3; tmr_input_struct.input_mapped_select = TMR_CC_CHANNEL_MAPPED_DIRECT; tmr_input_struct.input_polarity_select = TMR_INPUT_RISING_EDGE; tmr_input_struct.input_filter_value = 0; tmr_input_channel_init(TMR3, &tmr_input_struct, TMR_CHANNEL_INPUT_DIV_1); /* configure pwm input with ch1 */ tmr_ic_init_struct.input_filter_value = 0; tmr_ic_init_struct.input_channel_select = TMR_SELECT_CHANNEL_1; tmr_ic_init_struct.input_mapped_select = TMR_CC_CHANNEL_MAPPED_DIRECT; tmr_ic_init_struct.input_polarity_select = TMR_INPUT_RISING_EDGE; tmr_pwm_input_config(TMR3, &tmr_ic_init_struct, TMR_CHANNEL_INPUT_DIV_1); tmr_trigger_input_select(TMR3, TMR_SUB_INPUT_SEL_C1DF1); tmr_sub_mode_select(TMR3, TMR_SUB_RESET_MODE); tmr_counter_enable(TMR3, TRUE); /* add user code begin tmr3_init 2 */ /* add user code end tmr3_init 2 */ } //void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { // if (htim->Instance == TIM2) { // pulse_count++; // 脉冲计数加1 // } //}void Calculate_FlowRate(void) { // static uint32_t last_pulse_count = 0; // uint32_t pulses_in_interval; // float time_interval_s = 1.0f; // 计算间隔1秒 // // pulses_in_interval = pulse_count - last_pulse_count; // last_pulse_count = pulse_count; // // // 流量计算公式:流量(L/min) = (脉冲数/脉冲每升) × (60/时间间隔秒) // flow_rate_l_min = (pulses_in_interval / (float)PULSES_PER_LITER) * (60.0f / time_interval_s); //} /* add user code begin 1 */ /* add user code end 1 */ void delay_init(void) { /* configure systick */ systick_clock_source_config(SYSTICK_CLOCK_SOURCE_AHBCLK_NODIV); fac_us = system_core_clock / (1000000U); fac_ms = fac_us * (1000U); } void delay_us(uint32_t nus) { uint32_t temp = 0; SysTick->LOAD = (uint32_t)(nus * fac_us); SysTick->VAL = 0x00; SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk ; do { temp = SysTick->CTRL; }while((temp & 0x01) && !(temp & (1 << 16))); SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; SysTick->VAL = 0x00; } /** * @brief inserts a delay time. * @param nms: specifies the delay time length, in milliseconds. * @retval none */ void delay_ms(uint16_t nms) { uint32_t temp = 0; while(nms) { if(nms > STEP_DELAY_MS) { SysTick->LOAD = (uint32_t)(STEP_DELAY_MS * fac_ms); nms -= STEP_DELAY_MS; } else { SysTick->LOAD = (uint32_t)(nms * fac_ms); nms = 0; } SysTick->VAL = 0x00; SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; do { temp = SysTick->CTRL; }while((temp & 0x01) && !(temp & (1 << 16))); SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; SysTick->VAL = 0x00; } } /** * @brief inserts a delay time. * @param sec: specifies the delay time, in seconds. * @retval none */ void delay_sec(uint16_t sec) { uint16_t index; for(index = 0; index < sec; index++) { delay_ms(500); delay_ms(500); } } 怎么过虑占空比40到60之外脉冲波形
最新发布
09-11
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Starry丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值