hollyedward 发表于 2024-3-25 20:02

【GD32VW553-EVAL试用评测】UASRT串口例程学习

<p>GD32VW553-EVAL学习笔记(四)</p>

<p><strong>简介</strong></p>

<p> &nbsp;</p>

<p>&nbsp;</p>

<p><strong>模块内部框图</strong></p>

<p> &nbsp;</p>

<p> &nbsp;</p>

<p> &nbsp;</p>

<p>&nbsp;</p>

<p><strong>1、查看最简单的串口打印例程</strong></p>

<p>首先导入例程至gd32eclipse</p>

<p>右键build project</p>

<p> &nbsp;</p>

<p>在项目目录下找到生成的bin文件</p>

<p> &nbsp;</p>

<p>使用 GD_LINK_CLI.exe 工具进行烧录</p>

<p> &nbsp;</p>

<p>运行结果:USART 将输出&ldquo;please press the Tamper key&rdquo;到超级终端。按下按键Tamper 键,串口继续输出&ldquo;USART printf example&rdquo;。</p>

<p> &nbsp;</p>

<p>查看代码结构</p>

<pre>
<code class="language-cpp">int main(void)
{
    systick_config();
    /* initialize test status LED */
    test_status_led_init();
    /* flash LED for test */
    flash_led(2);
    /* test key initialize */
    test_key_init();
    /* USART initialize */
    gd_eval_com_init(EVAL_COM0);
    /* output a message on hyperterminal using printf function */
    printf("\n\rplease press the Tamper/Wakeup Key\n\r");

    /* the software must wait until TC=1. the TC flag remains cleared during all data
    transfers and it is set by hardware at the last frame end of transmission */
    while(RESET == usart_flag_get(EVAL_COM0 , USART_FLAG_TC));

    while(1){
      if(0 == gd_eval_key_state_get(KEY_TAMPER_WAKEUP)){
            delay_1ms(50);

            if(0 == gd_eval_key_state_get(KEY_TAMPER_WAKEUP)){
                delay_1ms(50);

                if(0 == gd_eval_key_state_get(KEY_TAMPER_WAKEUP)){
                  /* turn on LED1 */
                  gd_eval_led_on(LED1);
                  delay_1ms(200);

                  /* output a message on hyperterminal using printf function */
                  printf("\n\rUSART printf example \n\r");

                  /* the software must wait until TC=1. the TC flag remains cleared during all data
                  transfers and it is set by hardware at the last frames end of transmission */
                  while(RESET == usart_flag_get(USART0 , USART_FLAG_TC));
                  
                  /* wait until the button is released */
                  while(0 == gd_eval_key_state_get(KEY_TAMPER_WAKEUP));
                }else{
                  /* turn off LED1 */
                  gd_eval_led_off(LED1);
                }
            }else{
                /* turn off LED1 */
                gd_eval_led_off(LED1);
            }
      }else{
            /* turn off LED1 */
            gd_eval_led_off(LED1);
      }
    }
}</code></pre>

<p>gd_eval_key_state_get(KEY_TAMPER_WAKEUP)方法检测按键状态,延迟50ms按键消抖,连续检测三次以确保按键按下有效。</p>

<p>如果检测为有效,则打开 LED1 (gd_eval_led_on(LED1)),延时 200 毫秒。</p>

<p>再次向上位机输出信息,表明这是一个 USART 打印示例。</p>

<p>等待串口数据发送完成 (while(RESET == usart_flag_get(USART0 , USART_FLAG_TC)))。</p>

<p>循环等待按键松开 (while(0 == gd_eval_key_state_get(KEY_TAMPER_WAKEUP)))</p>

<p>如果按键未检测有效LED1就会熄灭。</p>

<p>&nbsp;</p>

<p><strong>2、按键中断USART</strong><br />
烧录例程</p>

<p>运行结果:首先,所有灯亮灭一次用于测试。然后USART0 将输出数组tx_buffer 的内容(从0x00 到0xFF)<br />
到支持hex 格式的超级终端并等待接收由超级终端发送的BUFFER_SIZE 个字节的数据。MCU<br />
将接收到的超级终端发来的数据存放在数组rx_buffer 中。在发送和接收完成后,将比较<br />
tx_buffer 和rx_buffer 的值,如果结果相同,LED1,LED2 点亮,LED3 灭;如果结果不相同,<br />
LED3 点亮,LED1,LED2 灭。</p>

<p>这是串口的自发自收嘛</p>

<p>显示十六进制</p>

<p> &nbsp;</p>

<p>代码先初始化 LED 和串口,然后发送一组数据到串口。接着,程序等待接收数据并将其与发送的数据进行比较。如果数据传输成功,则程序会打开 LED1 和 LED2,关闭 LED3;如果数据传输失败,则程序会关闭 LED1 和 LED2,打开 LED3。最后,程序进入一个死循环,等待用户操作。</p>

<p>主程序</p>

<pre>
<code class="language-cpp">int main(void)
{
    /* initialize the LEDs */
    led_init();
   
    /* USART interrupt configuration */
    eclic_irq_enable(USART0_IRQn, 1, 0);
    systick_config();

    /* flash the LEDs for 1 time */
    led_flash(1);
   
    /* initialize the USART */
    gd_eval_com_init(EVAL_COM0);

    /* enable USART TBE interrupt */
    usart_interrupt_enable(EVAL_COM0, USART_INT_TBE);
    /* wait until USART send the tx_buffer */
    while(tx_count &lt; tx_buffer_size);

    while(RESET == usart_flag_get(EVAL_COM0, USART_FLAG_TC));

    /* enable USART RBNE interrupt */
    usart_interrupt_enable(EVAL_COM0, USART_INT_RBNE);
    /* wait until USART receive the rx_buffer */
    while(rx_count &lt; rx_buffer_size);

    /* compare the transmitted buffer and the received buffer */
    transfer_result = memory_compare(tx_buffer, rx_buffer, BUFFER_SIZE);

    if (SUCCESS == transfer_result){
      /* if success, turn on LED1 and LED2, turn off LED3*/
      gd_eval_led_on(LED1);
      gd_eval_led_on(LED2);
      gd_eval_led_off(LED3);
    }else{
      /* if not, turn off LED1 and LED2, turn on LED3*/
      gd_eval_led_off(LED1);
      gd_eval_led_off(LED2);
      gd_eval_led_on(LED3);
    }

    while(1){
    }
}</code></pre>

<p>内存比较</p>

<pre>
<code class="language-cpp">ErrStatus memory_compare(uint8_t* src, uint8_t* dst, uint16_t length)
{
    while (length--){
      if (*src++ != *dst++){
            return ERROR;
      }
    }
    return SUCCESS;
}</code></pre>

<p><strong>3、使用串口DMA功能发送和接收</strong></p>

<p> &nbsp;</p>

<p> &nbsp;</p>

<p> &nbsp;</p>

<p>&nbsp;</p>

<p>烧录相关代码</p>

<p>功能和前面接收发送差不多,但使用DMA功能</p>

<p> &nbsp;</p>

<p>具体过程:</p>

<ol data-sourcepos="5:1-13:17">
        <li data-sourcepos="5:1-5:15">初始化 LED 和串口。</li>
        <li data-sourcepos="6:1-6:14">配置 DMA 控制器。</li>
        <li data-sourcepos="7:1-7:22">配置 USART 发送和接收 DMA。</li>
        <li data-sourcepos="8:1-8:18">等待 DMA 发送和接收完成。</li>
        <li data-sourcepos="9:1-9:13">比较发送和接收数据。</li>
        <li data-sourcepos="10:1-12:36">根据比较结果控制 LED:
        <ul data-sourcepos="11:5-12:36">
                <li data-sourcepos="11:5-11:36">数据传输成功:打开 LED1 和 LED2,关闭 LED3。</li>
                <li data-sourcepos="12:5-12:36">数据传输失败:关闭 LED1 和 LED2,打开 LED3。</li>
        </ul>
        </li>
        <li data-sourcepos="13:1-13:17">进入无限循环,等待用户操作。</li>
</ol>

<pre>
<code class="language-cpp">int main(void)
{
    /* initialize the LEDs */
    led_init();
    systick_config();
   
    /* flash the LEDs for 3 times */
    led_flash(3);
   
    /* initialize the USART */
    gd_eval_com_init(EVAL_COM0);

    /* configure USART DMA */
    dma_config();
   
    /* USART DMA enable for transmission and reception */
    usart_dma_transmit_config(EVAL_COM0, USART_TRANSMIT_DMA_ENABLE);
    usart_dma_receive_config(EVAL_COM0, USART_RECEIVE_DMA_ENABLE);
   
    /* wait DMA channel7 transfer complete */
    while(RESET == dma_flag_get(DMA_CH7, DMA_FLAG_FTF));
   
    /* wait DMA channel2 receive complete */
    while(RESET == dma_flag_get(DMA_CH2, DMA_FLAG_FTF));
   
    /* compare the transmitted buffer and the received buffer */
    transfer_result = memory_compare(tx_buffer, rx_buffer, BUFFER_SIZE);
   
    if (SUCCESS == transfer_result){
      /* if success, turn on LED1 and LED2, turn off LED3 */
      gd_eval_led_on(LED1);
      gd_eval_led_on(LED2);
      gd_eval_led_off(LED3);
    }else{
      /* if not, turn off LED1 and LED2, turn on LED3 */
      gd_eval_led_off(LED1);
      gd_eval_led_off(LED2);
      gd_eval_led_on(LED3);
    }
   
    while(1){
    }
}</code></pre>

<p>DMA配置</p>

<pre>
<code class="language-cpp">void dma_config(void)
{
    dma_single_data_parameter_struct dma_init_struct;
    /* enable the DMA clock */
    rcu_periph_clock_enable(RCU_DMA);
    /* configure the DMA channe7 */
    dma_deinit(DMA_CH7);
    dma_single_data_para_struct_init(&amp;dma_init_struct);
    dma_init_struct.direction = DMA_MEMORY_TO_PERIPH;
    dma_init_struct.memory0_addr = (uint32_t)tx_buffer;
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.periph_memory_width = DMA_MEMORY_WIDTH_8BIT;
    dma_init_struct.number = BUFFER_SIZE;
    dma_init_struct.periph_addr = USART0_TDATA_ADDRESS;
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_single_data_mode_init(DMA_CH7, &amp;dma_init_struct);
    dma_channel_subperipheral_select(DMA_CH7, DMA_SUBPERI4);
    dma_circulation_disable(DMA_CH7);
    /* enable DMA channel7 */
    dma_channel_enable(DMA_CH7);
   
    /* configure the DMA channel2 */
    dma_deinit(DMA_CH2);
    dma_init_struct.direction = DMA_PERIPH_TO_MEMORY;
    dma_init_struct.memory0_addr = (uint32_t)rx_buffer;
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.periph_memory_width = DMA_MEMORY_WIDTH_8BIT;
    dma_init_struct.number = BUFFER_SIZE;
    dma_init_struct.periph_addr = USART0_RDATA_ADDRESS;
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_single_data_mode_init(DMA_CH2, &amp;dma_init_struct);
    dma_channel_subperipheral_select(DMA_CH2, DMA_SUBPERI4);
    dma_circulation_disable(DMA_CH2);
    /* enable DMA channel2 */
    dma_channel_enable(DMA_CH2);
}</code></pre>

<p>&nbsp;</p>

emma2015 发表于 2024-4-18 09:14

发送一组数据到串口。接着,程序等待接收数据并将其与发送的数据进行比较
页: [1]
查看完整版本: 【GD32VW553-EVAL试用评测】UASRT串口例程学习