【ST多款开发板返场测评】STM32F767 Nucleo-144 基于FIFO的串口驱动
<div class='showpostmsg'><h1><b>前言</b></h1><p >为了方便后面USB调试,所以先实现串口通讯接口,前面进行了串口测试,但是接口不方便使用,需要实现方便应用层使用的串口收发接口。通过实现FIFO方式来实现串口的中断接收,发送为了简单使用查询发送方式。</p>
<p > </p>
<h1 ><b>过程</b></h1>
<h2 ><b>Bsp层</b></h2>
<p >先实现bsp层的串口接口</p>
<p >Bsp_uart.c/h</p>
<p > </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, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_9;
HAL_GPIO_Init(GPIOD, &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(&UartHandle);
/* NVIC */
HAL_NVIC_EnableIRQ(USART3_IRQn);
HAL_NVIC_SetPriority(USART3_IRQn,0,1);
LL_USART_EnableIT_RXNE(USART3);
}
</code></pre>
<p > </p>
<p >发送</p>
<pre>
<code class="language-cpp">
void uart_sendbyte(uint8_t ch)
{
uint8_t tmp =ch;
HAL_UART_Transmit(&UartHandle,&ch,1,0xFFFFFFFF);
//LL_USART_TransmitData8(USART3,ch);
}
void bsp_uart_send(uint8_t* p, uint32_t len)
{
HAL_UART_Transmit(&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) && 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(&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) && 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(&ch, 1);
}
}
void uart_sendbyte(uint8_t ch)
{
uint8_t tmp =ch;
HAL_UART_Transmit(&UartHandle,&ch,1,0xFFFFFFFF);
//LL_USART_TransmitData8(USART3,ch);
}
void bsp_uart_send(uint8_t* p, uint32_t len)
{
HAL_UART_Transmit(&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, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_9;
HAL_GPIO_Init(GPIOD, &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(&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 > </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<length; i++)
{
if(s_ring_buffer_t.datalen_u32 < 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<len;i++)
{
if(s_ring_buffer_t.datalen_u32 > 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 > </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<len ;i++)
{
uart_sendbyte(buff);
}
return 0;
}</code></pre>
<p > </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<length; i++)
{
if(s_ring_buffer_t.datalen_u32 < 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<len;i++)
{
if(s_ring_buffer_t.datalen_u32 > 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<len ;i++)
{
uart_sendbyte(buff);
}
return 0;
}</code></pre>
<p > </p>
<p >uart.h</p>
<pre>
<code class="language-cpp">#ifndef UART_H
#define UART_H
#include <stdint.h>
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 > </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))) >0)
{
uart_write(buffer, len);
}
}
}</code></pre>
<p > </p>
<p >使用串口调试助手发送数据,开发板收到原样返回</p>
<p > </p>
<p > </p>
<p > </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> <p>谢谢分享,期待后续评测!</p>
页:
[1]