811|2

504

帖子

4

TA的资源

纯净的硅(高级)

楼主
 

【ST多款开发板返场测评】STM32F767 Nucleo-144 非阻塞串口打印实现 [复制链接]

前言

前面我们实现的串口发送采用的是阻塞查询方式,在USB开发中如果使用该方式作为打印调试,则可能会由于阻塞影响时序。所以需要该为非阻塞方式,我们的思路是先将待发送数据写入到缓存中,然后载在主循环中进行发送。核心部分还是和串口接收FIFO实现一样,可以复用其代码。

 

代码

增加代码uart_debug.c/h

数据结构

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;



static uint32_t uart_debug_pop(uint8_t *buff, uint32_t len);



static uint8_t uart_ring_buffer[1024];



static 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,

};

 

写数据到缓存区

uint32_t uart_debug_push(uint8_t *buffer, uint32_t length)

{

    uint32_t i;

    uint32_t sendlen = 0;

Alloc_Critical();

    Enter_Critical();

    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[s_ring_buffer_t.in_u32] = buffer[i];

            s_ring_buffer_t.datalen_u32++;

            s_ring_buffer_t.in_u32++;

            s_ring_buffer_t.in_u32 %= s_ring_buffer_t.maxlen_u32;

  sendlen++;

        }

        else

        {

            /* full */

            break;

        }

    }

    Exit_Critical();

return sendlen;

}

 

从缓存区读出数据

static uint32_t uart_debug_pop(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[i] = s_ring_buffer_t.buffer_pu8[s_ring_buffer_t.out_u32];

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;

}

 

发送处理,主循环中调用该接口实现真正的发送,

制定了一次发送的最大长度len,这样做目的是避免一次发送过长,导致主循环在这里等待过长,配置len来调整。

int uart_debug_send(uint32_t len)

{

uint32_t i;

uint8_t buff[16];

uint32_t slen;



if(0 != (slen = uart_debug_pop(buff, sizeof(buff))))

{

uart_write(buff, slen);

}

return slen;

}

 

重定向printf的底层接口

int fputc(int ch, FILE *f)

{

uint8_t tmp = (uint8_t)ch;

  /* Your implementation of fputc(). */

uart_debug_push(&tmp, 1);

  return ch;

}

uart_debug.h

#ifndef UART_DEBUG_H
#define UART_DEBUG_H

#include <stdint.h>

uint32_t uart_debug_push(uint8_t *buffer, uint32_t length);
int uart_debug_send(uint32_t len);

#endif

uart_debug.c

#include <stdio.h>
#include "uart.h"
#include "uart_debug.h"
#include "stm32f7xx.h"

#define Alloc_Critical()  
#define Enter_Critical() 
#define Exit_Critical()   
			 
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;

static uint32_t uart_debug_pop(uint8_t *buff, uint32_t len);

static uint8_t uart_ring_buffer[1024];

static 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,
};

static uint32_t uart_debug_pop(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[i] = s_ring_buffer_t.buffer_pu8[s_ring_buffer_t.out_u32];
				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;
}

uint32_t uart_debug_push(uint8_t *buffer, uint32_t length)
{
    uint32_t i;
    uint32_t sendlen = 0;
		Alloc_Critical();
    Enter_Critical();
    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[s_ring_buffer_t.in_u32] = buffer[i];
            s_ring_buffer_t.datalen_u32++;
            s_ring_buffer_t.in_u32++;
            s_ring_buffer_t.in_u32 %= s_ring_buffer_t.maxlen_u32;
					  sendlen++;
        }
        else
        {
            /* full */
            break;
        }
    }
    Exit_Critical();
		return sendlen;
}

int uart_debug_send(uint32_t len)
{
	uint32_t i;
	uint8_t buff[16];
	uint32_t slen;

	if(0 != (slen = uart_debug_pop(buff, sizeof(buff))))
	{
		uart_write(buff, slen);
	}
	return slen;
}

int fputc(int ch, FILE *f)
{
	uint8_t tmp = (uint8_t)ch;
  /* Your implementation of fputc(). */
	uart_debug_push(&tmp, 1);
  return ch;
}

测试

Main.c中

#include "uart_debug.h"



  while (1)

  {

printf("Hello World\r\n");

uart_debug_send(16);

  }

串口调试助手看到打印如下

 

 

 

总结

使用FIFO,将数据先陷入缓存区,再统一下主循环中不断查询发送,这样实现了非阻塞的串口输出,方便后面调试打印使用。

此帖出自stm32/stm8论坛

最新回复

我觉得这种非阻塞的,适用于LOG存到Flash的。   详情 回复 发表于 2023-10-31 13:16
点赞 关注
 

回复
举报

7628

帖子

2

TA的资源

五彩晶圆(高级)

沙发
 

前后台轮询?其实可以试试上个rtos

此帖出自stm32/stm8论坛
 
个人签名

默认摸鱼,再摸鱼。2022、9、28

 

回复

7201

帖子

2

TA的资源

版主

板凳
 

我觉得这种非阻塞的,适用于LOG存到Flash的。

此帖出自stm32/stm8论坛
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表