qinyunti 发表于 2023-10-30 12:26

【ST多款开发板返场测评】STM32F767 Nucleo-144 基于FIFO的串口驱动

<div class='showpostmsg'><h1><b>前言</b></h1>

<p >为了方便后面USB调试,所以先实现串口通讯接口,前面进行了串口测试,但是接口不方便使用,需要实现方便应用层使用的串口收发接口。通过实现FIFO方式来实现串口的中断接收,发送为了简单使用查询发送方式。</p>

<p >&nbsp;</p>

<h1 ><b>过程</b></h1>

<h2 ><b>Bsp层</b></h2>

<p >先实现bsp层的串口接口</p>

<p >Bsp_uart.c/h</p>

<p >&nbsp;</p>

<p >初始化</p>

<pre>
<code class="language-cpp">void bsp_uart_init(void)
{
GPIO_InitTypeDefGPIO_InitStruct;

       
        /* IO Cfg
       * PD9 USART3_RX
       * PD8 USART3_TX
       */
        __HAL_RCC_GPIOD_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
        GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOD, &amp;GPIO_InitStruct);
       
GPIO_InitStruct.Pin = GPIO_PIN_9;
HAL_GPIO_Init(GPIOD, &amp;GPIO_InitStruct);
       
/* Enable USART3 clock */
__HAL_RCC_USART3_CLK_ENABLE();
       
        /* USART3 Cfg */
UartHandle.Instance      = USART3;

UartHandle.Init.BaudRate   = 115200;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits   = UART_STOPBITS_1;
UartHandle.Init.Parity   = UART_PARITY_NONE;
UartHandle.Init.HwFlowCtl= UART_HWCONTROL_NONE;
UartHandle.Init.Mode       = UART_MODE_TX_RX;
        HAL_UART_Init(&amp;UartHandle);
       
        /* NVIC */
        HAL_NVIC_EnableIRQ(USART3_IRQn);
        HAL_NVIC_SetPriority(USART3_IRQn,0,1);
       
        LL_USART_EnableIT_RXNE(USART3);
}
</code></pre>

<p >&nbsp;</p>

<p >发送</p>

<pre>
<code class="language-cpp">
void uart_sendbyte(uint8_t ch)
{
        uint8_t tmp =ch;
        HAL_UART_Transmit(&amp;UartHandle,&amp;ch,1,0xFFFFFFFF);
        //LL_USART_TransmitData8(USART3,ch);
}

void bsp_uart_send(uint8_t* p, uint32_t len)
{
        HAL_UART_Transmit(&amp;UartHandle,p,len,0xFFFFFFFF);
}</code></pre>

<p >串口接收中断处理</p>

<pre>
<code class="language-cpp">extern void uart_rx_handler(const uint8_t *buffer, uint32_t length);

void USART3_IRQHandler(void)
{
        uint8_t ch;
if(LL_USART_IsActiveFlag_RXNE(USART3) &amp;&amp; LL_USART_IsEnabledIT_RXNE(USART3))
{
    /* RXNE flag will be cleared by reading of RDR register (done in call) */
                ch = LL_USART_ReceiveData8(USART3);
                //LL_USART_TransmitData8(USART3,ch);
                //while(LL_USART_IsActiveFlag_TC(USART3) == 0);
                uart_rx_handler(&amp;ch, 1);
}
}</code></pre>

<p >代码详见</p>

<p >bap_uart.c</p>

<pre>
<code class="language-cpp">#include "stm32f7xx_hal.h"
#include "stm32f7xx_ll_usart.h"


UART_HandleTypeDef UartHandle;


extern void uart_rx_handler(const uint8_t *buffer, uint32_t length);

void USART3_IRQHandler(void)
{
        uint8_t ch;
if(LL_USART_IsActiveFlag_RXNE(USART3) &amp;&amp; LL_USART_IsEnabledIT_RXNE(USART3))
{
    /* RXNE flag will be cleared by reading of RDR register (done in call) */
                ch = LL_USART_ReceiveData8(USART3);
                //LL_USART_TransmitData8(USART3,ch);
                //while(LL_USART_IsActiveFlag_TC(USART3) == 0);
                uart_rx_handler(&amp;ch, 1);
}
}

void uart_sendbyte(uint8_t ch)
{
        uint8_t tmp =ch;
        HAL_UART_Transmit(&amp;UartHandle,&amp;ch,1,0xFFFFFFFF);
        //LL_USART_TransmitData8(USART3,ch);
}

void bsp_uart_send(uint8_t* p, uint32_t len)
{
        HAL_UART_Transmit(&amp;UartHandle,p,len,0xFFFFFFFF);
}
       
void bsp_uart_init(void)
{
GPIO_InitTypeDefGPIO_InitStruct;

       
        /* IO Cfg
       * PD9 USART3_RX
       * PD8 USART3_TX
       */
        __HAL_RCC_GPIOD_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
        GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOD, &amp;GPIO_InitStruct);
       
GPIO_InitStruct.Pin = GPIO_PIN_9;
HAL_GPIO_Init(GPIOD, &amp;GPIO_InitStruct);
       
/* Enable USART3 clock */
__HAL_RCC_USART3_CLK_ENABLE();
       
        /* USART3 Cfg */
UartHandle.Instance      = USART3;

UartHandle.Init.BaudRate   = 115200;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits   = UART_STOPBITS_1;
UartHandle.Init.Parity   = UART_PARITY_NONE;
UartHandle.Init.HwFlowCtl= UART_HWCONTROL_NONE;
UartHandle.Init.Mode       = UART_MODE_TX_RX;
        HAL_UART_Init(&amp;UartHandle);
       
        /* NVIC */
        HAL_NVIC_EnableIRQ(USART3_IRQn);
        HAL_NVIC_SetPriority(USART3_IRQn,0,1);
       
        LL_USART_EnableIT_RXNE(USART3);
}

</code></pre>

<p >bap_uart.h</p>

<pre>
<code class="language-cpp">#ifndef BSP_UART_H
#define BSP_UART_H

void bsp_uart_init(void);
void bsp_uart_send(uint8_t* p, uint32_t len);

#endif</code></pre>

<h2 ><b>驱动层</b></h2>

<p >实现FIFO数据结构</p>

<pre>
<code class="language-cpp">typedef struct
{
      uint32_t datalen_u32;
      uint32_t maxlen_u32;
      uint32_t in_u32;
      uint32_t out_u32;
      uint8_t* buffer_pu8;
}ring_buffer_t;


uint8_t uart_ring_buffer;

ring_buffer_t s_ring_buffer_t=
{
        .datalen_u32 = 0,
        .maxlen_u32 = sizeof(uart_ring_buffer),
.in_u32 = 0,
.out_u32 = 0,
.buffer_pu8 = uart_ring_buffer,
};
</code></pre>

<p >临界段处理</p>

<pre>
<code class="language-cpp">#define Alloc_Critical()
#define Enter_Critical()__disable_irq()
#define Exit_Critical()   __enable_irq</code></pre>

<p >&nbsp;</p>

<p >接收处理,接收中断服务函数中调用</p>

<pre>
<code class="language-cpp">void uart_rx_handler(const uint8_t *buffer, uint32_t length)
{
    uint32_t i;
    for(i=0;i&lt;length; i++)
    {
      if(s_ring_buffer_t.datalen_u32 &lt; s_ring_buffer_t.maxlen_u32)
      {
            s_ring_buffer_t.buffer_pu8 = buffer;
            s_ring_buffer_t.datalen_u32++;
            s_ring_buffer_t.in_u32++;
            s_ring_buffer_t.in_u32 %= s_ring_buffer_t.maxlen_u32;
      }
      else
      {
            /* full */
            break;
      }
    }
}</code></pre>

<p >接收API</p>

<pre>
<code class="language-cpp">uint32_t uart_read(uint8_t *buff, uint32_t len)
{
    uint32_t readlen = 0;
    //uint32_t mask;
    if(s_ring_buffer_t.datalen_u32 == 0)
    {
      return 0;
    }
                Alloc_Critical();
    Enter_Critical();
    uint32_t i;
    for(i=0;i&lt;len;i++)
    {
                        if(s_ring_buffer_t.datalen_u32 &gt; 0)
      {
                                buff = s_ring_buffer_t.buffer_pu8;
                                s_ring_buffer_t.datalen_u32--;
                                s_ring_buffer_t.out_u32++;
                                s_ring_buffer_t.out_u32 %= s_ring_buffer_t.maxlen_u32;
                                readlen++;
                        }
                        else
                        {
                                break;
                        }
    }
    Exit_Critical();
    return readlen;
}</code></pre>

<p >&nbsp;</p>

<p >发送API</p>

<pre>
<code class="language-cpp">int uart_write(uint8_t *buff, uint32_t len)
{
        uint32_t i;
        for(i=0; i&lt;len ;i++)
        {
                uart_sendbyte(buff);
        }
        return 0;
}</code></pre>

<p >&nbsp;</p>

<p >代码详见</p>

<p >uart.c</p>

<pre>
<code class="language-cpp">#include "uart.h"
#include "bsp_uart.h"
#include "stm32f7xx.h"

#define Alloc_Critical()
#define Enter_Critical()__disable_irq()
#define Exit_Critical()   __enable_irq()
                       
typedef struct
{
      uint32_t datalen_u32;
      uint32_t maxlen_u32;
      uint32_t in_u32;
      uint32_t out_u32;
      uint8_t* buffer_pu8;
}ring_buffer_t;


uint8_t uart_ring_buffer;

ring_buffer_t s_ring_buffer_t=
{
        .datalen_u32 = 0,
        .maxlen_u32 = sizeof(uart_ring_buffer),
.in_u32 = 0,
.out_u32 = 0,
.buffer_pu8 = uart_ring_buffer,
};

void uart_rx_handler(const uint8_t *buffer, uint32_t length)
{
    uint32_t i;
    for(i=0;i&lt;length; i++)
    {
      if(s_ring_buffer_t.datalen_u32 &lt; s_ring_buffer_t.maxlen_u32)
      {
            s_ring_buffer_t.buffer_pu8 = buffer;
            s_ring_buffer_t.datalen_u32++;
            s_ring_buffer_t.in_u32++;
            s_ring_buffer_t.in_u32 %= s_ring_buffer_t.maxlen_u32;
      }
      else
      {
            /* full */
            break;
      }
    }
}

uint32_t uart_read(uint8_t *buff, uint32_t len)
{
    uint32_t readlen = 0;
    //uint32_t mask;
    if(s_ring_buffer_t.datalen_u32 == 0)
    {
      return 0;
    }
                Alloc_Critical();
    Enter_Critical();
    uint32_t i;
    for(i=0;i&lt;len;i++)
    {
                        if(s_ring_buffer_t.datalen_u32 &gt; 0)
      {
                                buff = s_ring_buffer_t.buffer_pu8;
                                s_ring_buffer_t.datalen_u32--;
                                s_ring_buffer_t.out_u32++;
                                s_ring_buffer_t.out_u32 %= s_ring_buffer_t.maxlen_u32;
                                readlen++;
                        }
                        else
                        {
                                break;
                        }
    }
    Exit_Critical();
    return readlen;
}

int uart_write(uint8_t *buff, uint32_t len)
{
        uint32_t i;
        for(i=0; i&lt;len ;i++)
        {
                uart_sendbyte(buff);
        }
        return 0;
}</code></pre>

<p >&nbsp;</p>

<p >uart.h</p>

<pre>
<code class="language-cpp">#ifndef UART_H
#define UART_H

#include &lt;stdint.h&gt;

void uart_rx_handler(const uint8_t *buffer, uint32_t length);
uint32_t uart_read(uint8_t *buff, uint32_t len);
int uart_write(uint8_t *buff, uint32_t len);

extern void uart_sendbyte(uint8_t ch);

#endif</code></pre>

<p >&nbsp;</p>

<h2 ><b>测试</b></h2>

<p><b>main.c中</b></p>

<pre>
<code class="language-cpp">#include "bsp_uart.h"
#include "uart.h"


bsp_uart_init();

  uint8_t tx_buffer={0xAA,0x55};

  /* Infinite loop */

  while (1)

  {

uint8_t buffer;

for(;;)

{

uint32_t len=0;

  if((len = uart_read(buffer, sizeof(buffer))) &gt;0)

  {

     uart_write(buffer, len);

  }

  }

  }</code></pre>

<p >&nbsp;</p>

<p >使用串口调试助手发送数据,开发板收到原样返回</p>

<p >&nbsp;</p>

<p > &nbsp;</p>

<p >&nbsp;</p>

<h1 ><b>总结</b></h1>

<p >基于bsp层的串口收发,实现了基于FIFO的串口驱动,给应用层提供串口收发接口,uart.c和uart.h具备可移植性,方便移植到不同平台。方便后面的调试使用。</p>
</div><script>                                        var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;"   style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
                                       
                                        if(parseInt(discuz_uid)==0){
                                                                                                (function($){
                                                        var postHeight = getTextHeight(400);
                                                        $(".showpostmsg").html($(".showpostmsg").html());
                                                        $(".showpostmsg").after(loginstr);
                                                        $(".showpostmsg").css({height:postHeight,overflow:"hidden"});
                                                })(jQuery);
                                        }                </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>

freebsder 发表于 2023-10-30 15:52

<p>谢谢分享,期待后续评测!</p>
页: [1]
查看完整版本: 【ST多款开发板返场测评】STM32F767 Nucleo-144 基于FIFO的串口驱动