15686 views|1 replies

58

Posts

0

Resources
The OP
 

[Xiaohua HC32F448 Review] About Xiaohua Semiconductor's UART interrupt sending and PRINTF construction and redirection [Copy link]

 This post was last edited by xuexuexuexuexue on 2023-8-11 16:25
  1. First open the usart folder in the examples folder, then open the usart_uart_int folder, and open the MDK example project. The purpose of this example is to use the serial port assistant on the computer to send data to HC32F448 through RX, and then the development board will send the same data to the serial port assistant through TX and display it.
    First define the serial port on the development board connected to the serial port assistant as USART2
    /* USART RX/TX pin definition */
    #define USART_RX_PORT                   (GPIO_PORT_C)   /* PC11: USART2_RX */
    #define USART_RX_PIN                    (GPIO_PIN_11)
    #define USART_RX_GPIO_FUNC              (GPIO_FUNC_37)
    
    #define USART_TX_PORT                   (GPIO_PORT_C)   /* PC10: USART2_TX */
    #define USART_TX_PIN                    (GPIO_PIN_10)
    #define USART_TX_GPIO_FUNC              (GPIO_FUNC_36)
    

  2. Explain other macro definitions in main.c

    1. LL_PERIPH
      The source and header files of LL_PERIPH are found in hc32_ll.c and hc32_ll.h. ll does not refer to IIC, but low_level, LL library. Peripheral/PERIPH in microcontroller means peripherals, which are obviously used to control peripherals here.

      #define LL_PERIPH_SEL                   (LL_PERIPH_GPIO | LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU | \
                                            LL_PERIPH_EFM | LL_PERIPH_SRAM)

      In the hc32_ll.h header file, we can find that the reference source of the SEL macro definition is ALL. Obviously, this instruction is used to form an 8-bit binary value to turn on or off LL_PERIPH. Definitions such as EFM, FCG, and GPIO are to shift the eight-bit binary 0000 0001 to the left in sequence. If all these values are ORed, they will form 1111 1111, that is, 0xFF. If they are ORed like SEL, they will form 1100 0111.

      #define LL_PERIPH_EFM           (1UL << 0U)
      #define LL_PERIPH_FCG           (1UL << 1U)
      #define LL_PERIPH_GPIO          (1UL << 2U)
      #define LL_PERIPH_INTC          (1UL << 3U)
      #define LL_PERIPH_LVD           (1UL << 4U)
      #define LL_PERIPH_MPU           (1UL << 5U)
      #define LL_PERIPH_PWC_CLK_RMU   (1UL << 6U)
      #define LL_PERIPH_SRAM          (1UL << 7U)
      #define LL_PERIPH_ALL           (LL_PERIPH_EFM | LL_PERIPH_FCG | LL_PERIPH_GPIO | LL_PERIPH_INTC  | \
                                       LL_PERIPH_LVD | LL_PERIPH_MPU | LL_PERIPH_SRAM | LL_PERIPH_PWC_CLK_RMU)
      
    2. USART
      Obviously the macro definition here is used to initialize USART. When we open the header and source files of BSP and usart, there will be similar definitions. FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_USART2, ENABLE) is used to turn on the clock of USART2 in FCG3. The interrupt source number of USART2 in the hc32f448.h header file includes the transmit completion interrupt (USART_INT_TX_CPLT), transmit end interrupt (USART_INT_TENDI), transmit error interrupt (USART_INT_TCI), transmit interrupt (USART_INT_TI), receive error interrupt (INT_SRC_USART2_EI), receive timeout interrupt (USART_INT_RTO), and receive interrupt (USART_INT_RI). INT000 and others are the interrupt event source numbers.
      /* USART unit definition */
      #define USART_UNIT                      (CM_USART2)
      #define USART_FCG_ENABLE()              (FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_USART2, ENABLE))
      
      /* USART Tx complete flag select: USART_INT_TX_CPLT or USART_INT_TX_END */
      #define USART_TX_CPLT_FLAG              (USART_INT_TX_CPLT)
      
      /* USART interrupt definition */
      #define USART_RX_ERR_IRQn               (INT000_IRQn)
      #define USART_RX_ERR_INT_SRC            (INT_SRC_USART2_EI)
      
      #define USART_RX_FULL_IRQn              (INT001_IRQn)
      #define USART_RX_FULL_INT_SRC           (INT_SRC_USART2_RI)
      
      #define USART_TX_EMPTY_IRQn             (INT002_IRQn)
      #define USART_TX_EMPTY_INT_SRC          (INT_SRC_USART2_TI)
      
      #define USART_TX_CPLT_IRQn              (INT003_IRQn)
      #if (USART_INT_TX_CPLT == USART_TX_CPLT_FLAG)
      #define USART_TX_CPLT_INT_SRC           (INT_SRC_USART2_TCI)
      #elif (USART_INT_TX_END == USART_TX_CPLT_FLAG)
      #define USART_TX_CPLT_INT_SRC           (INT_SRC_USART2_TENDI)
      #else
      #error "USART_TX_CPLT_FLAG defined error"
      #endif
         //hc32f488.h头文件中关于USART2的定义。
          INT_SRC_USART2_EI            = 328U,     /* USART_2_EI    */
          INT_SRC_USART2_RI            = 329U,     /* USART_2_RI    */
          INT_SRC_USART2_TI            = 330U,     /* USART_2_TI    */
          INT_SRC_USART2_RTO           = 331U,     /* USART_2_RTO   */
          INT_SRC_USART2_TENDI         = 332U,     /* USART_2_TENDI */
          INT_SRC_USART2_TCI           = 333U,     /* USART_2_TCI   */
  3. Other custom functions in main.c
    static void USART_TxEmpty_IrqCallback(void)//用来发送寄存器数据的中断函数,在数组BUF没有清空前,持续发送一字节数据
    
    static void USART_TxComplete_IrqCallback(void)//中断发送数据完成后的回调函数
    static void USART_RxFull_IrqCallback(void)//接收数据的回调中断函数
    static void USART_RxError_IrqCallback(void)//接收数据发生错误,对中断状态进行重置
    static void INTC_IrqInstalHandler(const stc_irq_signin_config_t *pstcConfig, uint32_t u32Priority)//对所需中断函数进行配置和设置优先级。
    

    The function INTC_IrqInstalHandler(const stc_irq_signin_config_t *pstcConfig, uint32_t u32Priority) is used to configure the interrupt and the corresponding interrupt callback function and its priority.
    The instruction to set the priority in this function is NVIC_SetPriority(pstcConfig->enIRQn, u32Priority);
    the parameter input format of this function is: INTC_IrqInstalHandler(&stcIrqSigninConfig, DDL_IRQ_PRIO_XX); the pointer is defined as: stc_irq_signin_config_t stcIrqSigninConfig;
    the parameter input of Priority is DDL_IRQ_PRIO_00 to DDL_IRQ_PRIO_15.

     */
    /**
     * @defgroup INTC_Priority_Sel Interrupt Priority Level 00 ~ 15
     * @{
     */
    #define DDL_IRQ_PRIO_00                 (0U)
    #define DDL_IRQ_PRIO_01                 (1U)
    #define DDL_IRQ_PRIO_02                 (2U)
    #define DDL_IRQ_PRIO_03                 (3U)
    #define DDL_IRQ_PRIO_04                 (4U)
    #define DDL_IRQ_PRIO_05                 (5U)
    #define DDL_IRQ_PRIO_06                 (6U)
    #define DDL_IRQ_PRIO_07                 (7U)
    #define DDL_IRQ_PRIO_08                 (8U)
    #define DDL_IRQ_PRIO_09                 (9U)
    #define DDL_IRQ_PRIO_10                 (10U)
    #define DDL_IRQ_PRIO_11                 (11U)
    #define DDL_IRQ_PRIO_12                 (12U)
    #define DDL_IRQ_PRIO_13                 (13U)
    #define DDL_IRQ_PRIO_14                 (14U)
    #define DDL_IRQ_PRIO_15                 (15U)
    
  4. Code in the main function:
    static uint8_t m_au8DataBuf[RING_BUF_SIZE];
    static stc_ring_buf_t m_stcRingBuf;
    static __IO en_flag_status_t m_enTxCompleteFlag = SET;
    
    int32_t main(void)
    {
    //    stc_usart_uart_init_t stcUartInit;
        stc_irq_signin_config_t stcIrqSigninConfig;
    
        /* MCU Peripheral registers write unprotected */
        LL_PERIPH_WE(LL_PERIPH_SEL);//解除外设寄存器,允许 写 入外设寄存器
    
        /* Initialize BSP system clock. */
        BSP_CLK_Init();
    
        /* Initialize BSP expand IO. */
        BSP_IO_Init();
    
        /* Initialize BSP LED. */
        BSP_LED_Init();
    
        /* Configure USART RX/TX pin. */
        GPIO_SetFunc(USART_RX_PORT, USART_RX_PIN, USART_RX_GPIO_FUNC);//配置USART2两个引脚的功能
        GPIO_SetFunc(USART_TX_PORT, USART_TX_PIN, USART_TX_GPIO_FUNC);
    
        /* Enable peripheral clock */
        USART_FCG_ENABLE();
    
        /* Initialize ring buffer function. */
        (void)BUF_Init(&m_stcRingBuf, m_au8DataBuf, sizeof(m_au8DataBuf));//初始化一个数组,并让它stcRingBus这个结构体绑定
    
        /* Initialize UART. */
        (void)USART_UART_StructInit(&stcUartInit);
        stcUartInit.u32ClockDiv = USART_CLK_DIV64;//设置分配系数
        stcUartInit.u32Baudrate = 115200UL;//设置波特率
        stcUartInit.u32OverSampleBit = USART_OVER_SAMPLE_8BIT;
        if (LL_OK != USART_UART_Init(USART_UNIT, &stcUartInit, NULL)) {//初始化uart2
            BSP_LED_On(LED_RED);//如果初始化发送错误点亮板上红灯
            for (;;) {
            }
        }
    
        /* Register RX error IRQ handler && configure NVIC. */
        stcIrqSigninConfig.enIRQn = USART_RX_ERR_IRQn;
        stcIrqSigninConfig.enIntSrc = USART_RX_ERR_INT_SRC;
        stcIrqSigninConfig.pfnCallback = &USART_RxError_IrqCallback;
        INTC_IrqInstalHandler(&stcIrqSigninConfig, DDL_IRQ_PRIO_DEFAULT);//设置接受错误中断函数
    
        /* Register RX full IRQ handler && configure NVIC. */
        stcIrqSigninConfig.enIRQn = USART_RX_FULL_IRQn;
        stcIrqSigninConfig.enIntSrc = USART_RX_FULL_INT_SRC;
        stcIrqSigninConfig.pfnCallback = &USART_RxFull_IrqCallback;
        INTC_IrqInstalHandler(&stcIrqSigninConfig, DDL_IRQ_PRIO_DEFAULT);//设置接收中断函数
    
        /* Register TX empty IRQ handler && configure NVIC. */
        stcIrqSigninConfig.enIRQn = USART_TX_EMPTY_IRQn;
        stcIrqSigninConfig.enIntSrc = USART_TX_EMPTY_INT_SRC;
        stcIrqSigninConfig.pfnCallback = &USART_TxEmpty_IrqCallback;
        INTC_IrqInstalHandler(&stcIrqSigninConfig, DDL_IRQ_PRIO_DEFAULT);//设置发送中断函数
    
        /* Register TX complete IRQ handler && configure NVIC. */
        stcIrqSigninConfig.enIRQn = USART_TX_CPLT_IRQn;
        stcIrqSigninConfig.enIntSrc = USART_TX_CPLT_INT_SRC;
        stcIrqSigninConfig.pfnCallback = &USART_TxComplete_IrqCallback;
        INTC_IrqInstalHandler(&stcIrqSigninConfig, DDL_IRQ_PRIO_DEFAULT);//设置发送完成中断函数
    
        /* MCU Peripheral registers write protected */
        LL_PERIPH_WP(LL_PERIPH_SEL);//重新禁止对外设寄存器进行读写操作
    
        /* Enable RX function */
        USART_FuncCmd(USART_UNIT, (USART_RX | USART_INT_RX), ENABLE);//允许USART2接收
        for (;;) {
    				
    			
    			DDL_DelayMS(200);
            if ((SET == m_enTxCompleteFlag) && !BUF_Empty(&m_stcRingBuf)) {
                m_enTxCompleteFlag = RESET;
    #if (USART_INT_TX_END == USART_TX_CPLT_FLAG)
                USART_FuncCmd(USART_UNIT, USART_INT_TX_END, DISABLE);
    #endif
                USART_FuncCmd(USART_UNIT, (USART_TX | USART_INT_TX_EMPTY), ENABLE);
            }
        }
    }
  5. Next, let’s take a look at the effect
  6. Next, we can simply construct a printf function of our own and put my_printf("Hello, World"); in the main loop.
    /**
     * [url=home.php?mod=space&uid=159083]@brief[/url]  printf a word
     * @param  None
     * @retval None
     */
    static void my_printf(char ch[])
    {
    		int8_t  i=0;
        uint8_t u8Data1=ch[0];
    	(void)BUF_Write(&m_stcRingBuf, &u8Data1, 1UL);
    	i++;
    			while(ch[i]!='\0')
    			{
    				u8Data1=ch[i];
    				(void)BUF_Write(&m_stcRingBuf, &u8Data1, 1UL);
    				i++;
    				
    			}
    			
    			u8Data1=0x0A;
    			(void)BUF_Write(&m_stcRingBuf, &u8Data1, 1UL);
    }

  7. Then you can also use the redirected functions in the LL library and BSP.
    First, we have to open hc32f4xx_conf.h, and #define LL_PRINT_ENABLE (DDL_ON).
    Then we open ev_hc32f448_lqfp80.c, and then find the PRINTF related content. You can see a BSP_PRINTF_Preinit function. The two input parameters are a device pointer and a device parameter, void *vpDevice. The definition of this parameter is void type, which means that we can input any type of pointer. Usually we can directly fill in the pointer parameters of USART, SPI, and I2C here. For example: let vpDevice = CM_USART2, CM_USART2 = ((CM_USART_TypeDef *)CM_USART2_BASE). The device parameter refers to the baud rate, which is usually 115200.
    However, we should note that this function has actually defined which USART and baud rate to use in the ev_hc32f448_lqfp80.h header file at line 149.

    /**
     * @defgroup BSP_PRINT_CONFIG BSP PRINT Configure definition
     * @{
     */
    #define BSP_PRINTF_DEVICE               (CM_USART2)
    #define BSP_PRINTF_DEVICE_FCG           (FCG3_PERIPH_USART2)
    
    #define BSP_PRINTF_BAUDRATE             (115200UL)
    #define BSP_PRINTF_BAUDRATE_ERR_MAX     (0.025F)
    
    #define BSP_PRINTF_PORT                 (GPIO_PORT_C)
    #define BSP_PRINTF_PIN                  (GPIO_PIN_10)
    #define BSP_PRINTF_PORT_FUNC            (GPIO_FUNC_36)
    
    /**
     * @brief  BSP printf device, clock and port pre-initialize.
     * @param  [in] vpDevice                Pointer to print device
    //例如:令vpDevice = CM_USART2           ((CM_USART_TypeDef *)CM_USART2_BASE)
     * @param  [in] u32Baudrate             Print device communication baudrate
     * @retval int32_t:
     *           - LL_OK:                   Initialize successfully.
     *           - LL_ERR:                  Initialize unsuccessfully.
     *           - LL_ERR_INVD_PARAM:       The u32Baudrate value is 0.
     */
    int32_t BSP_PRINTF_Preinit(void *vpDevice, uint32_t u32Baudrate)
    {
        uint32_t i;
        float32_t f32Error;
        const uint32_t au32Div[] = {USART_CLK_DIV1,   USART_CLK_DIV4,   USART_CLK_DIV16,  USART_CLK_DIV64,
                                    USART_CLK_DIV128, USART_CLK_DIV256, USART_CLK_DIV512, USART_CLK_DIV1024
                                   };
        stc_usart_uart_init_t stcUartInit;
        int32_t i32Ret = LL_ERR_INVD_PARAM;
    
        (void)vpDevice;
    
        if (0UL != u32Baudrate) {
            /* Set TX port function */
            GPIO_SetFunc(BSP_PRINTF_PORT, BSP_PRINTF_PIN, BSP_PRINTF_PORT_FUNC);
    
            /* Enable clock  */
            FCG_Fcg3PeriphClockCmd(BSP_PRINTF_DEVICE_FCG, ENABLE);
    
            /* Configure UART */
            (void)USART_UART_StructInit(&stcUartInit);
            stcUartInit.u32OverSampleBit = USART_OVER_SAMPLE_8BIT;
            (void)USART_UART_Init(BSP_PRINTF_DEVICE, &stcUartInit, NULL);
    
            for (i = 0UL; i < ARRAY_SZ(au32Div); i++) {
                USART_SetClockDiv(BSP_PRINTF_DEVICE, au32Div[i]);
                i32Ret = USART_SetBaudrate(BSP_PRINTF_DEVICE, u32Baudrate, &f32Error);
                if ((LL_OK == i32Ret) && \
                    ((-BSP_PRINTF_BAUDRATE_ERR_MAX <= f32Error) && (f32Error <= BSP_PRINTF_BAUDRATE_ERR_MAX))) {
                    USART_FuncCmd(BSP_PRINTF_DEVICE, USART_TX, ENABLE);
                    break;
                } else {
                    i32Ret = LL_ERR;
                }
            }
        }
    
        return i32Ret;
    }

    Then we open the hc32_ii_utility.h and .c files. This function is the initialization of the printf() function by the LL library. We only need to initialize this function and we can directly use printf() or DDL_Printf().

    int32_t LL_PrintfInit(void *vpDevice, uint32_t u32Param, int32_t (*pfnPreinit)(void *vpDevice, uint32_t u32Param));
    

    Now we can change the main function to the following, and the effect will be as follows. We only need one instruction: DDL_PrintfInit(CM_USART2,115200,BSP_PRINTF_Preinit);
    But please note that only USART2 can be used here, and the baud rate can only be 115200, because the BSP_PRINTF_Preinit function has been automatically defaulted, so we need to change the definition in the header file.

    int32_t main(void)
    {
    
        /* MCU Peripheral registers write unprotected */
        LL_PERIPH_WE(LL_PERIPH_SEL);
    
        /* Initialize BSP system clock. */
        BSP_CLK_Init();
    
        /* Initialize BSP expand IO. */
        BSP_IO_Init();
    
        /* Initialize BSP LED. */
        BSP_LED_Init();
    		DDL_PrintfInit(CM_USART2,115200,BSP_PRINTF_Preinit);//初始化uart2
    //		DDL_PrintfInit(BSP_PRINTF_DEVICE, BSP_PRINTF_BAUDRATE, BSP_PRINTF_Preinit);
    
        for (;;) {
    				
    			DDL_Printf("Hello,World_n\n");
    			printf("Hello,World_p");
    			DDL_DelayMS(100);
        }
    }

This post is from Domestic Chip Exchange

Latest reply

There are quite a few automatic defaults in the BSP_PRINTF_Preinit function.   Details Published on 2023-8-13 21:54
 
 

1662

Posts

0

Resources
2
 

There are quite a few automatic defaults in the BSP_PRINTF_Preinit function.

This post is from Domestic Chip Exchange
 
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

Featured Posts
MSP432 connects wifi module ESP8266 as server

The wifi module esp8266 is very easy to use. It can be connected to the microcontroller via uart, and it is very easy to ...

【DIY Creative LED V2】Complete production steps

This post was last edited by dcexpert on 2020-10-21 15:09 The production of V2 is much simpler than V1. If everything g ...

Teach you step by step: Use STM32F103 to drive ST7567 LCD screen

ST7567 is one of the driver chips for LCD screens. It is a single-chip dot matrix LCD driver that integrates an LCD c ...

Understand the fast charging protocols of major mobile phone manufacturers

This post was last edited by qwqwqw2088 on 2021-6-21 08:24 Fast charging has become a major battlefield for major mobil ...

15th Anniversary] EE DIY (Progress) -- Upper Computer UI Changes

This post was last edited by RCSN on 2021-7-12 18:00 For details of DIY projects, see this post The previous host com ...

[Flower carving hands-on] Interesting and fun music visualization series of small projects (06) --- dot matrix spectrum lamp

I suddenly had the urge to do a series of topics on sound visualization. This topic is a bit difficult and covers a wide ...

[Flower carving DIY] Interesting and fun music visualization series of small projects (15) - horizontal LED square tube lights

I had the urge to do a series of topics on sound visualization. This topic is a bit difficult and covers a wide range of ...

41 "Wanli" Raspberry Pi car - ROS learning (ROSBridge controls the little turtle)

This post was last edited by lb8820265 on 2022-11-3 22:29 Previously, we introduced how to control the turtle using t ...

Modelsim simulation problem

First picture: 710815 I searched online and found that I need to modify the environment variables. 710816 But there is n ...

[ACM32G103RCT6 development board evaluation] +ADC and NTC to achieve temperature detection

Temperature detection is inseparable from temperature sensors. In terms of temperature sensor types, they are mainly div ...

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list