流水源 发表于 2026-6-27 23:53:06

【Telink - 泰凌 TL322X 开发板】+串口发送接收测试

串口是基本的常用外设,本次来试试开发板的串口输入输出功能。
首先选择串口工程例子。
!(//m.qjumbo.com/forum/data/attachment/forum/202606/27/234105voxsobdwyomwybhm.png)

例子是是兼容多款开发板的,代码看着比较复杂,我精简了一下,去掉了无用的部分。
关于串口部分的一些API调用可以参口这里:(https://doc.telink-semi.cn/doc/zh/software/res/sdk/driver/driver_sdk_cn/#uart)
!(//m.qjumbo.com/forum/data/attachment/forum/202606/27/235250nwsens3u1m1m6ejs.png)



```
typedef struct fifo_buffer_t
{
    volatile uint32_t    read_i;
    volatile uint32_t    write_i;
    uint8_t            buff;
}fifo_buffer_t;

typedef struct shell_uart_buffer_t
{
    fifo_buffer_t       tx;
    fifo_buffer_t       rx;
    volatile uint32_t    tx_cpl:   1;

}shell_uart_buffer_t;

shell_uart_buffer_tg_shell_uart=
{
    .tx.read_i = 0,
    .tx.write_i = 0,

    .rx.read_i = 0,
    .rx.write_i = 0,

    .tx_cpl = 0,
};

uint8_tuart_send_buff;


void uart_get_data_send(void)
{
    int n,m;
    for(n=0;n<128;n++)
    {
      if(g_shell_uart.tx.read_i != g_shell_uart.tx.write_i)
      {
            uart_send_buff = g_shell_uart.tx.buff;
            g_shell_uart.tx.read_i &= 0x1ff; //256Byte
      }else break;
    }
    if(n)
    {
      g_shell_uart.tx_cpl = 1;
      for (m = 0; m < n; m++)
      {
                 uart_send_byte(UART_MODULE_SEL, uart_send_buff);
      }
      g_shell_uart.tx_cpl = 0;
    }
}


void uart_send_char(uint8_t ch)
{
    while(((g_shell_uart.tx.write_i+1)&0x1ff) == g_shell_uart.tx.read_i)
    {
      //fifo buffer full
      if((g_shell_uart.tx_cpl == 0))
      {
            uart_get_data_send();
      }
    }

    g_shell_uart.tx.buff = ch;
    g_shell_uart.tx.write_i &= 0x1ff;//256Byte

    if((g_shell_uart.tx_cpl == 0))
    {
      uart_get_data_send();
    }
}

uint8_t USART_Flush(void)
{
    if(g_shell_uart.tx_cpl == 0)
    {
      uart_get_data_send();
      return 0;
    }
    return 1;
}

uint8_t USART_PutChar(uint8_t ch)
{
        uart_send_char(ch);
    return 0;
}

uint8_t USART_GetChar(uint8_t *ch)
{
    if(g_shell_uart.rx.read_i != g_shell_uart.rx.write_i)
    {
      *ch = g_shell_uart.rx.buff;
      g_shell_uart.rx.read_i &= 0x1ff; //256Byte
      return 0;
    }
    return 1;
}


uint32_t USART_Flush_Rxbuff(void)
{
    uint32_t len = 0;
    while(g_shell_uart.rx.read_i != g_shell_uart.rx.write_i)
    {
      USART_PutChar(g_shell_uart.rx.buff);
      len++;
    }
    return len;
}

int USART_PutStr(const char* str, uint32_t len)
{
    while(len --)   uart_send_char(*str++);
    return 0;
}

int USART_GetStr(char* str, uint32_t len)
{
    uint32_t rlen = 0;

    for(uint32_t i=0;i<len;i++)
    {
      if(g_shell_uart.rx.read_i != g_shell_uart.rx.write_i)
      {
            str = g_shell_uart.rx.buff;
            g_shell_uart.rx.read_i &= 0x1ff;
      }
    }
    return rlen;
}

void user_init(void)
{
    unsigned short div= 0;
    unsigned charbwpc = 0;

    gpio_function_en(LED1);
    gpio_output_en(LED1); //enable output
    gpio_input_dis(LED1); //disable input
    gpio_function_en(LED2);
    gpio_output_en(LED2); //enable output
    gpio_input_dis(LED2); //disable input
    gpio_function_en(LED3);
    gpio_output_en(LED3); //enable output
    gpio_input_dis(LED3); //disable input
    gpio_function_en(LED4);
    gpio_output_en(LED4); //enable output
    gpio_input_dis(LED4); //disable input

    uart_hw_fsm_reset(UART_MODULE_SEL);
    uart_set_pin(UART_MODULE_SEL, UART0_TX_PIN, UART0_RX_PIN);

    uart_cal_div_and_bwpc(115200, sys_clk.pclk * 1000 * 1000, &div, &bwpc);
    uart_init(UART_MODULE_SEL, div, bwpc, UART_PARITY_NONE, UART_STOP_BIT_ONE);

    uart_tx_irq_trig_level(UART_MODULE_SEL, 0);
    uart_rx_irq_trig_level(UART_MODULE_SEL, 1);

    uart_set_irq_mask(UART_MODULE_SEL, UART_RX_IRQ_MASK | UART_ERR_IRQ_MASK);
    uart_set_rx_timeout_with_exp(UART_MODULE_SEL, bwpc, 12, UART_BW_MUL2, 0);
    uart_set_irq_mask(UART_MODULE_SEL, UART_RXDONE_MASK);
    plic_interrupt_enable(IRQ_UART0);
    core_interrupt_enable();

}

void main_loop(void)
{
    if(g_shell_uart.rx.read_i != g_shell_uart.rx.write_i)
    {
            uart_send_char(g_shell_uart.rx.buff);
      g_shell_uart.rx.read_i &= 0x1ff; //256Byte
    }
    USART_Flush();
}


_attribute_ram_code_sec_ void uart0_irq_handler(void)
{
        if (uart_get_irq_status(UART_MODULE_SEL, UART_RX_ERR)) {
                uart_clr_irq_status(UART_MODULE_SEL, UART_RXBUF_IRQ_STATUS); // it will clear rx_fifo,clear hardware pointer and rx_err_irq ,rx_buff_irq,so it won't enter rx_buff_irq interrupt.
        }
        if (uart_get_irq_status(UART_MODULE_SEL, UART_RXBUF_IRQ_STATUS)) {
                gpio_set_high_level(LED3);
                unsigned char fifo_cnt = uart_get_rxfifo_num(UART_MODULE_SEL);
          for (unsigned char k = 0; k < fifo_cnt; k++)
          {
                  if(((g_shell_uart.rx.write_i+1)&0x1ff) != g_shell_uart.rx.read_i)
                  {
                          g_shell_uart.rx.buff = uart_read_byte(UART_MODULE_SEL);
                         g_shell_uart.rx.write_i &= 0x1ff;//256Byte
                  }
          }
        }
        if (uart_get_irq_status(UART_MODULE_SEL, UART_RXDONE_IRQ_STATUS)) {
                gpio_set_high_level(LED4);
                unsigned char fifo_cnt = uart_get_rxfifo_num(UART_MODULE_SEL);
                for (unsigned char k = 0; k < fifo_cnt; k++)
                {
                        if(((g_shell_uart.rx.write_i+1)&0x1ff) != g_shell_uart.rx.read_i)
                        {
                                g_shell_uart.rx.buff = uart_read_byte(UART_MODULE_SEL);
                               g_shell_uart.rx.write_i &= 0x1ff;//256Byte
                        }
                }
                uart_clr_irq_status(UART_MODULE_SEL, UART_RXDONE_IRQ_STATUS);
        }
}
PLIC_ISR_REGISTER(uart0_irq_handler, IRQ_UART0)
```

首先要配置串口引脚。

```
#define UART0_TX_PINGPIO_FC_PD6
#define UART0_RX_PINGPIO_FC_PD7
```

!(//m.qjumbo.com/forum/data/attachment/forum/202606/27/234521duvxubvu8a4899k5.png)
使用NDMA模式通过中断接收串口数据。
!(//m.qjumbo.com/forum/data/attachment/forum/202606/27/234618iepo4sdxinak3ex3.png)

修改之后编译下载。
!(//m.qjumbo.com/forum/data/attachment/forum/202606/27/234725be0ba29ben21iwit.png)

实现的效果就是开发板通过串口收到数据然后转发数据回来。连接USB转串口接口到电脑,可以看到串口号,然后通过串口助手测试串口发送接收效果。
!(//m.qjumbo.com/forum/data/attachment/forum/202606/27/234834qu3j63w7n8jdgjgz.png)



页: [1]
查看完整版本: 【Telink - 泰凌 TL322X 开发板】+串口发送接收测试

Baidu
map