华大HC32F460初使用及串口测试

前言

因工作需求,上手了一块HC32F460,网上资料不是很多,因此记录下调试记录供后人参考。

使用环境

  • IDE: Keil v5.23.0
  • DDL: hc32f46x_ddl_Rev1.3.1
  • PROJECT: uart_irq_rx_tx

时钟配置

简单介绍

HC32提供了六个时钟源,例程采用的是8M外部时钟,因此这里也使用外部时钟。内部时钟配置暂时未搞明白,等后期更新。

外部晶振定义在system_hc32f46x.h第103行

#if !defined (XTAL_VALUE)
#define XTAL_VALUE ((uint32_t)8000000)  /*!< External high speed OSC freq. */
#endif

需要根据实际晶振大小配置。晶振错误时系统仍能运行,但是串口等需要时钟的设备数据会出现错误。

我手上的开发板晶振是12Mhz,因此修改定义为12000000。

设置分频

例程在main.cstatic void ClkInit(void)对系统时钟进行了配置,采用的是Xtal to MPLL的方法。这里只关心分频倍数。

   /* Set bus clk div. */
   stcSysClkCfg.enHclkDiv  = ClkSysclkDiv1;
   stcSysClkCfg.enExclkDiv = ClkSysclkDiv2;
   stcSysClkCfg.enPclk0Div = ClkSysclkDiv1;
   stcSysClkCfg.enPclk1Div = ClkSysclkDiv2;
   stcSysClkCfg.enPclk2Div = ClkSysclkDiv4;
   stcSysClkCfg.enPclk3Div = ClkSysclkDiv4;
   stcSysClkCfg.enPclk4Div = ClkSysclkDiv2;

这里对工作时钟进行分频。通过系统框图可以看到,这时输入时钟MPLL倍频出来的MPLLP。

image

分频时注意不要超过工作时钟的上限即可。

通过下列结构体进行倍频

    /* MPLL config. */
    stcMpllCfg.pllmDiv = 1u; /* XTAL 8M / 1 */
    stcMpllCfg.plln = 50u;   /* 8M*50 = 400M */
    stcMpllCfg.PllpDiv = 4u; /* MLLP = 100M */
    stcMpllCfg.PllqDiv = 4u; /* MLLQ = 100M */
    stcMpllCfg.PllrDiv = 4u; /* MLLR = 100M */

MLLP为100M,可以计算出

    /* Set bus clk div. */
    stcSysClkCfg.enHclkDiv  = ClkSysclkDiv1;//100M
    stcSysClkCfg.enExclkDiv = ClkSysclkDiv2;//50M
    stcSysClkCfg.enPclk0Div = ClkSysclkDiv1;//100M
    stcSysClkCfg.enPclk1Div = ClkSysclkDiv2;//50M
    stcSysClkCfg.enPclk2Div = ClkSysclkDiv4;//25M
    stcSysClkCfg.enPclk3Div = ClkSysclkDiv4;//25M
    stcSysClkCfg.enPclk4Div = ClkSysclkDiv2;//50M

由于我需要测试串口最大速率,所以需要修改系统频率最高(200M)。

12M分 /倍频

分频和例程相同,倍频如下

    stcMpllCfg.pllmDiv = 12u; /* XTAL 12M / 3=4M */
    stcMpllCfg.plln = 400u;   /* 4M*100 = 400M */
    stcMpllCfg.PllpDiv = 2u; /* MLLP = 200M */
    stcMpllCfg.PllqDiv = 2u; /* MLLQ = 200M */
    stcMpllCfg.PllrDiv = 2u; /* MLLR = 200M */

查看配置时钟

SDK中提供了获取时钟频率的APICLK_GetClockFreq

要使用它,需要先初始化时钟频率结构体。

stc_clk_freq_t          stcClkFreq;//系统频率

然后通过 CLK_GetClockFreq(&stcClkFreq);获取频率值。

image

可以看到,频率和设置相同。

配置串口

例程默认采用的USART3

/* USART channel definition */
#define USART_CH                        (M4_USART3)

/* USART baudrate definition */
#define USART_BAUDRATE                  (115200ul)

/* USART RX Port/Pin definition */
#define USART_RX_PORT                   (PortE)
#define USART_RX_PIN                    (Pin04)
#define USART_RX_FUNC                   (Func_Usart3_Rx)

/* USART TX Port/Pin definition */
#define USART_TX_PORT                   (PortE)
#define USART_TX_PIN                    (Pin05)
#define USART_TX_FUNC                   (Func_Usart3_Tx)

由于修改串口配置牵涉到的地方较多,这里直接采用USART3进行测试。

烧录工程到板子上后,串口发送数据后会回显到屏幕上,如果时钟不对,会出现回显数据和发送数据不一致的情况。

收发逻辑

在接收到数据后,系统跳转到UsartRxIrqCallback函数,读取接收值,并且打开串口发送和TxEmpty中断。

static void UsartRxIrqCallback(void)
{
    m_u16RxData = USART_RecData(USART_CH);
    USART_FuncCmd(USART_CH, UsartTxAndTxEmptyInt, Enable);
}

此时由于TxBuff为空,会进入UsartTxIrqCallback,发送读取的值出去,关闭TxEmpty中断,打开UsartTxCmplt中断。

static void UsartTxIrqCallback(void)
{
    USART_SendData(USART_CH, m_u16RxData);
    USART_FuncCmd(USART_CH, UsartTxEmptyInt, Disable);
    USART_FuncCmd(USART_CH, UsartTxCmpltInt, Enable);
}

发送数据成功后,进入UsartTxCmpltIrqCallback,关闭中断和串口发送功能。

static void UsartTxCmpltIrqCallback(void)
{
    USART_FuncCmd(USART_CH, UsartTxCmpltInt, Disable);
    USART_FuncCmd(USART_CH, UsartTx, Disable);
}

这些中断回调函数通过中断号绑定到具体中断上

    /* Set USART RX IRQ */
    stcIrqRegiCfg.enIRQn = Int000_IRQn;
    stcIrqRegiCfg.pfnCallback = &UsartRxIrqCallback;

需要注意的是,由于关闭了UsartTx功能,后续无法发送任何数据出去,除非再次打开该功能。

DEBUG功能

SDK默认重定义printf函数到串口3上,不需要自己修改文件即可使用Printf。

相关的代码实现在hc32f46x_utility.c中,也同样包括毫秒延时和微妙延时函数(秒延时未提供,但无伤大雅)。

把串口发送中断关掉,只保留串口接收中断

static void UsartRxIrqCallback(void)
{
    m_u16RxData = USART_RecData(USART_CH);
//    USART_FuncCmd(USART_CH, UsartTxAndTxEmptyInt, Enable);
}

然后打开串口发送功能(在while(1)上面)

    /*Enable RX && RX interupt function*/
    USART_FuncCmd(USART_CH, UsartRx, Enable);
    USART_FuncCmd(USART_CH, UsartRxInt, Enable);
    USART_FuncCmd(USART_CH, UsartTx, Enable);

然后就可以使用printf或者USART_SendData发送数据了。

    while (1)
    {
//      printf("testing,[%d]\r\n",i);
      USART_SendData(USART_CH,0xA5);
      sysVar.txCount++;
      Ddl_Delay1ms(1000);
    }

波特率测试

理论上串口最高波特率为PCLK/32,PCLK为400MHz时,波特率为12.5Mhz

通过示波器抓数据得,2Bit为6.25MHz,符合理论值。

image

posted @ 2022-04-08 17:54  USTHzhanglu  阅读(2981)  评论(1编辑  收藏  举报