当前位置: 首页 > article >正文

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);


http://www.kler.cn/a/557965.html

相关文章:

  • Redis常用数据类型及其应用案例
  • 前端八股——JS+ES6
  • 百度搜索,能否将DeepSeek变成“内功”?
  • AIGC视频扩散模型新星:SVD——稳定扩散的Video模型
  • C++面试笔记(持续更新...)
  • 长短期记忆网络:从理论到创新应用的深度剖析
  • 【含文档+PPT+源码】基于Django的新闻推荐系统的设计与实现
  • linux中的查用命令
  • 【进程 】
  • DDD领域驱动开发第2讲:领域驱动开发在货代订单业务的实践
  • kubernetes proxy中 发现长时间运行的tcp连接 如何处理invalid包 如果更优雅的解决需要修改哪个参数?
  • 透彻理解:方差、协方差、相关系数、协方差矩阵及其应用
  • HTML之JavaScript DOM简介
  • 激光雷达YDLIDAR X2 SDK安装
  • 微信小程序中将图片截图为正方形(自动居中)
  • C++ MFC添加RichEditControl控件后,程序启动失败
  • windows环境下用docker搭建php开发环境dnmp
  • 【Bluedroid】AVRCP 连接源码分析(一)
  • Nginx web服务器+uWSGI web服务器+Django生产环境部署
  • OpenCV卡尔曼滤波器使用详细教程