实现printf重定向和delay_ms对于MCU开发来说非常基本又十分重要,可以为项目的开发提供调试和基本的延时功能。

一、printf重定向

1、UART引脚初始化

<pre>        //init UART pin
  •         PA2_INIT(PA2_UART1_TX);
  •         PA3_INIT(PA3_UART1_RX);</pre>
  • 复制代码

    2、UART初始化及RX中断使能

    UART_Open(UART1,115200,UART_NO_PARITY,UART_TRIGGER_LEVEL_1_BYTE);
  • UART_EnableInt(UART1, UART_RX_INT);
  • NVIC_EnableIRQ(UART1_IRQn);
  • 复制代码

    3、发送一个字节

    <pre>#define DATA 0x5A
  • //send a test data
  • if (UART1->LSR_b.THRE)     //Transmitter Holding Register Empty
  •         UART1->THR=DATA;  // THR:Transmit Holding Register</pre>
  • 复制代码

    4、实现printf重定向

    将me32g03xxxxx lib 20240710\cmsis\Device\ARM\ME32G030\Source\retarget.c加入工程

    1.png

    修改SendChar_ToUART函数,将UART0修改为UART1,因为开发板上使用的是UART1。

    <pre>void SendChar_ToUART(int ch)
  • {
  •         while(UART1->LSR_b.THRE==0);
  •         UART1->THR= ch;
  •         if(ch == '\n')
  •         {
  •                 while(UART1->LSR_b.THRE==0);
  •                 UART1->THR= '\r';
  •         }
  • }
  • </pre>
  • 复制代码

    5、RX接收中断处理

    接收到数据,TX回显

    <pre>void UART1_IRQHandler(void)
  • {
  •         uint8_t byte_data;

  •         if (UART1->LSR_b.RDR)                  //RDR:Receiver Data Ready
  •         {
  •                 if((UART1->LSR_b.THRE))      //THRE:Transmitter Holding Register Empty
  •                 {
  •                         byte_data = UART1->RBR;   //RBR:Receiver Buffer Register
  •                         UART1->THR= byte_data;    //THR: Transmit Holding Register  
  •                 }
  •         }
  • </pre>
  • 复制代码

    6、可以使用printf了

    <pre>        //Loop forever
  •         while(1)
  •         {
  •                 printf("【ME32G030 评测】1、printf重定向\r\n");
  •                 //SYS_Delay(65535);
  •                 //SYS_Delay(65535);
  •                 //SYS_Delay(65535);
  •                
  •                 delay_ms(1000);
  •         }</pre>
  • 复制代码
    SYS_Delay延时很不准确,所以要实现一个delay_ms函数

    2.png


    二、SysTick延时

    1、初始化SysTick定时器

    <pre>extern uint32_t SystemCoreClock;

  • // 初始化SysTick定时器
  • void SysTick_Init(void)
  • {
  •         SysTick->CTRL = 0;                          // 先关闭 SysTick
  •         SysTick->LOAD = SystemCoreClock / 1000 - 1; // 1ms 重载值
  •         SysTick->VAL  = 0;                          // 清空计数器
  •         SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk  // 使用 CPU 时钟
  •                   | SysTick_CTRL_ENABLE_Msk;   // 启用 SysTick(但不启用中断)
  • }</pre>
  • 复制代码

    2、delay_ms

    <pre>// 毫秒级延时
  • void delay_ms(uint32_t ms)
  • {
  •   uint32_t i;
  •   for(i=0;i<ms;i++)
  •   {
  •       SysTick->VAL = 0;  // 清空计数器
  •       while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)); // 等待 1ms 到达
  •   }
  • }</pre>
  • 复制代码

    1.jpg