rtthread的串口框架、485框架
一、串口接收超时中断的实现。
1. rtthread中定义的串口超时结构体
定义串口接收超时的结构体
CM_TMR0_TypeDef 为TM0的实例(实际有CM_TMR0_1 CM_TMR0_2 对应华大460的两个TMR0单元 )
channel 每个timer0有两个通道(TMR0_CHA、TMR0_CHB)clock 为FCG2_PERIPH_TMR0_1、FCG2_PERIPH_TMR0_2
timeout_bits 为超时的位个数 40表示40bit位传输时间
irq_config 包含 .irq_num 中断IRQ .irq_prio 中断优先级 .int_src 中断源
irq_callback 中断回调指针
/* HC32 config Rx timeout */ struct hc32_uart_rxto { CM_TMR0_TypeDef *TMR0_Instance; rt_uint32_t channel; rt_uint32_t clock; rt_size_t timeout_bits; #if defined (HC32F460) || defined (HC32F4A0) struct hc32_irq_config irq_config; func_ptr_t irq_callback; #endif };
eg 如下格式化
#define UART1_RXTO_CONFIG \ { \ .TMR0_Instance = CM_TMR0_1, \ .channel = TMR0_CH_A, \ .clock = FCG2_PERIPH_TMR0_1, \ .timeout_bits = 20UL, \ .irq_config = \ { \ .irq_num = BSP_UART1_RXTO_IRQ_NUM, \ .irq_prio = BSP_UART1_RXTO_IRQ_PRIO, \ .int_src = INT_SRC_USART1_RTO, \ }, \ }
hc32_dma_config中调用hc32_uart_rx_timeout
/* Initialization uart rx timeout for DMA */
hc32_uart_rx_timeout(serial);
hc32_uart_rx_timeout中根据serial的rx_timeout初始化TMR0
启用TMR0的时钟 (TMR0_1 或TMR0_2)
FCG_TMR0_CLK(uart->config->rx_timeout->clock, ENABLE);
清零CNTR , //TMR0_Instance为CM_TMR0_1 或CM_TMR0_2
/* TIMER0 basetimer function initialize */
TMR0_SetCountValue(TMR0_Instance, ch, 0U);
使用外部时钟XTAL32 分频系数1。计算CMPR的值。
TMR0_StructInit(&stcTmr0Init);
stcTmr0Init.u32ClockDiv = TMR0_CLK_DIV1;
stcTmr0Init.u32ClockSrc = TMR0_CLK_SRC_XTAL32;
if (TMR0_CLK_DIV1 == stcTmr0Init.u32ClockDiv)
{
alpha = 7UL;
}
else if (TMR0_CLK_DIV2 == stcTmr0Init.u32ClockDiv)
{
alpha = 5UL;
}
else if ((TMR0_CLK_DIV4 == stcTmr0Init.u32ClockDiv) || \
(TMR0_CLK_DIV8 == stcTmr0Init.u32ClockDiv) || \
(TMR0_CLK_DIV16 == stcTmr0Init.u32ClockDiv))
{
alpha = 3UL;
}
else
{
alpha = 2UL;
}
/* TMR0_CMPA<B>R calculation formula: CMPA<B>R = (RTB / (2 ^ CKDIVA<B>)) - alpha */
ckdiv = 1UL << (stcTmr0Init.u32ClockDiv >> TMR0_BCONR_CKDIVA_POS);
cmp_val = ((rtb + ckdiv - 1UL) / ckdiv) - alpha;
DDL_ASSERT(cmp_val <= 0xFFFFUL);
stcTmr0Init.u16CompareValue = (uint16_t)(cmp_val);
TMR0_Init(TMR0_Instance, ch, &stcTmr0Init);
2.启用USART的 RX_TIMEOUT功能,将为每一字节启动定时功能。
/* TMR0_CMPA<B>R calculation formula: CMPA<B>R = (RTB / (2 ^ CKDIVA<B>)) - alpha */
ckdiv = 1UL << (stcTmr0Init.u32ClockDiv >> TMR0_BCONR_CKDIVA_POS);
cmp_val = ((rtb + ckdiv - 1UL) / ckdiv) - alpha;
DDL_ASSERT(cmp_val <= 0xFFFFUL);
stcTmr0Init.u16CompareValue = (uint16_t)(cmp_val);
TMR0_Init(TMR0_Instance, ch, &stcTmr0Init);
TMR0_HWStartCondCmd(TMR0_Instance, ch, ENABLE);
TMR0_HWClearCondCmd(TMR0_Instance, ch, ENABLE);
/* Clear compare flag */
TMR0_ClearStatus(TMR0_Instance, (uint32_t)(0x1UL << (ch * TMR0_STFLR_CMFB_POS)));
#if defined (HC32F460) || defined (HC32F4A0)
NVIC_EnableIRQ(uart->config->rx_timeout->irq_config.irq_num);
#endif
USART_ClearStatus(uart->config->Instance, USART_FLAG_RX_TIMEOUT);
USART_FuncCmd(uart->config->Instance, (USART_RX_TIMEOUT | USART_INT_RX_TIMEOUT), ENABLE);
3.发送超时后会置为TMO中断
irq_config 和irq_callback 绑定,当TMO置位时触发IRQ中断执行irq_callback
hc32_install_irq_handler(&uart_config[i].rx_timeout->irq_config,
uart_config[i].rx_timeout->irq_callback, RT_FALSE);