- 2025-03-09
-
回复了主题帖:
【EV1W0505B-Y-00A评测】隔离DC/DC选型?-看看MIE1W0505B
秦天qintian0303 发表于 2025-3-9 09:35
这个隔离高压有人测试吗?
这个不知道怎么测试,非专业人士,也没有设备。
不知道用打火机的打火器试试不知道可不可以
-
回复了主题帖:
【EV1W0505B-Y-00A评测】隔离DC/DC选型?-看看MIE1W0505B
lemonboard 发表于 2025-3-9 10:19
隔离高压没有办法测试吧!
难度 有点大吧!
这个不知道怎么测试,非专业人士,也没有设备。
不知道用打火机的打火器试试不知道可不可以
-
回复了主题帖:
【EV1W0505B-Y-00A评测】隔离DC/DC选型?-看看MIE1W0505B
PowerAnts 发表于 2025-3-9 10:19
十多年前我就预言,小功率转换器以后完全傻瓜化的,不管是什么应用,都是输入两个脚,输出两个脚。这一天应 ...
是的,集成度会越来越高,关注应用即可。
-
发表了主题帖:
【EV1W0505B-Y-00A评测】纹波测量-数据很好
这一篇来测试下不同电压输出,以及对应的纹波。
先档位选到5V,输出电压4.99,看到非常精准稳定,由于手里的示波器是很便宜的,位数不够,测不到更精确的位数。
使用X1档位,除非带宽要求比较高或者电压高需要X10档,一般使用X1档,减少不必要的衰减影响。
使用交流耦合
带宽限制,消除不不必要的高频噪声
接地尽可能短,最好使用接地弹簧,我手里没有就直接夹了
调整水平垂直档,设置触发
测量峰峰值
如下图通道2是电源输入,通道1是输出,看到输入纹波还是很大的,输出则只有峰峰值60mV了,可以看到输出纹波非常小。
和手册上的数据对比,典型值50,最大值90,比较吻合。
档位选到3.3V,输出电压,看到也是非常精准稳定。
此时测试的纹波如下只有48mV,甚至比手册50mV典型值还小点。
通过以上测试可以看到,该芯片的性能参数是很好的,实测来看纹波数值也符合于手册值的典型值,而不是偏向于最大值,说明没有任何虚标,甚至还有点保守。
- 2025-03-08
-
发表了主题帖:
【EV1W0505B-Y-00A评测】隔离DC/DC选型?-看看MIE1W0505B
本帖最后由 qinyunti 于 2025-3-8 23:24 编辑
一.前言
DC/DC是开发中最常选型的器件之一了,普通DC/DC可选非常多,相信很多人都有自己用的很熟悉的选型库了。但是对于工业上比较严苛应用场景,需要隔离DC/DC时,可选范围就少了很多了,这里EEWORLD试用,推荐了一款隔离DC/DC:MIE1W0505B,拿到的配套开发板是EV1W0505B-Y-00A对应的芯片是MIEW0505BGY-3R,我们就借助这个开发板来熟悉下这颗隔离式DC/DC,其优秀的特征和性能,相信一定可以将其添加到自己的选型库中,以后在合适的应用中就可以考虑使用它了。先熟悉下这颗芯片然后通过不同方面做一些测试。
MIE1W0505B(GLVH)简介
这里官网能找到资料的型号是MIE1W0505B(GLVH),和手里的这个主要是封装和隔离电压等参数不一样。
资料见
https://www.monolithicpower.cn/cn/products/isolation/mie1w0505bglvh.html
下载数据手册
https://www.monolithicpower.cn/cn/documentview/productdocument/index/version/2/document_type/Datasheet/lang/en/sku/MIE1W0505BGLVH/document_id/11153/
基本原理示意如下,可以看到只需要很少的外围器件,输入输出几个电容即可。
主要特征关键字:
输入电压范围3V~5.5V
隔离
输出功率1W
短路保护
过温保护
典型应用电路
MIE1W0505BGLVH 是一款隔离稳压 DC/DC 模块,支持输入电压 (VIN)范围为3V 至 5.5V 的应用。它具有出色的负载和线性调整率,输出功率 (POUT) 可高达 1W。
MIE1W0505BGLVH 将功率 MOSFET、变压器和反馈 (FB) 电路均集成在一颗芯片中,实现了出色的性能并节省了空间。
MIE1W0505BGLVH 支持稳压输出电压 (VOUT)。当 VOUT降至目标电压 (3.3V 或 5V) 以下时,IC 开始切换,功率从 VIN 引脚向 VOUT 引脚输送,直至VOUT再次达到目标电压。
MIE1W0505BGLVH 还集成了VOUT反馈模块,可以在无需传统光耦合器和精密可配置参考 IC 的情况下调节 VOUT。与传统隔离电源模块相比,这种小型解决方案提供了更高的可靠性。
该器件全面的保护功能包括了短路保护 (SCP) 和过温保护 (OTP)。
它采用小尺寸LGA-12(4mmx5mm)封装。
产品特性和优势
3V 至5.5V 输入电压 (VIN) 工作范围
可选 5V 或3.3V 输出电压 (VOUT):
5V 至 5V:可用负载电流 (ILOAD) ≥200mA
5V 至3.3V:可用 ILOAD ≥200mA
3.3V 至 3.3V:可用 ILOAD ≥75mA
2.5kVRMS隔离电压
支持无限电容负载
0.4% 负载调整率
0.3% 线性调整率
连续短路保护 (SCP)
过温保护 (OTP)
符合 IEC 62368-1 CB 认证
满足 EN55032 B 类辐射标准
-40°C 至 +125°C 工作温度范围
采用 LGA-12(4mmx5mm)封装
配套开发板
我这里是EV1W0505B-Y-00A,官网可以找到资料的是EV1W0505B-LVH-00A见
https://www.monolithicpower.com/en/ev1w0505b-lvh-00a.html
手册
https://www.monolithicpower.com/en/documentview/productdocument/index/version/2/document_type/Datasheet/lang/en/sku/EV1W0505B-LVH-00A/document_id/12605/
和我手里的主要是封装和隔离电压不一样,
先来个正反面证件照
先来了解下评估版原理图,外围器件很简单只需要输入输出电容
这里有个跳线用于选择输出电压,EN是常高使能。
PCB layout可以参考下手册
- 2025-03-03
-
回复了主题帖:
EEWorld邀你来拆解(20期)——奥迪原装360全景模块
作为曾经的汽车电子从业人员,现在工作中也有接触摄像头相关应用,对奥迪原装360全景模块比较感兴趣。
1. 希望能用视频分享整个拆解过程。
2.结合工作经验分享产品中个人觉得值得借鉴的优点, 以及可以优化的地方。
3.对方案,比如主要的芯片等进行总结。
- 2024-12-23
-
发表了主题帖:
【极海APM32M3514电机通用评估板】PWM输出周期和死区测试
跑电机之前先来测试下PWM的输出,确保PWM输出是正确的。
如下位置有测试点
为了方便仿真调试先关闭看门狗
没接电机会进入fault状态,可以先注释掉如下fault检测
死区和周期初始化代码
User\Inc\parameter.h中
死去时间定义为1us,即72M时钟,计时72个计数,即1uS
#define DEAD_TIME (1.0f * SYSCLK_HSE_72MHz/1000000) // unit:us 死区时间
测试如下看到非常准确
周期定义如下
#define PWMFREQ 16000 // unit:Hz 载波频率
#define PWM_PERIOD (SYSCLK_HSE_72MHz/PWMFREQ/2)
计数72000000/16000/2=2250个, 除以2是因为时钟中心对齐方式。
实测6个时钟345us,对应频率17.4KHz和16K有点偏差
- 2024-12-06
-
发表了主题帖:
【极海APM32M3514电机通用评估板】开箱与基于SDK快速开发环境搭建体验
前言
APM32M3514系列是极海出品,面向电机驱动市场推出的高集成、高性价比电机控制专用SoC,基于APM32F035系列电机控制专用MCU的性能架构进行优化升级,搭载Arm® Cortex® -M0+内核,内置M0CP协处理器,集成200V 6N-Gate Driver及高性能3.3V LDO。适用于园林工具、手持吸尘器、低压风扇、低压水泵等领域。
主要性能参数如下
详见官网https://www.geehy.com/product/fifth/APM32M3514
我们现在手里拿到了开发板,先来个开箱,了解下开发板资源,然后搭建开发环境。
开发板开箱
包装海比较小清新
介绍卡片
开发板正反面
开发板资源介绍
开发板性能特点
12V~72VDC宽电压输入
最大功率100W
支持电机类型: BLDC、PMSM
支持编码器类型: 霍尔、光电、磁编码器
通讯接口: SCI、SPI、I2C、CAN
单/双电阻采样、三相反电动势采样
芯片优势:内置200V 6N Gate Driver和3.3V LDO
开发环境搭建
从官网下载SDK和pack包,其中FOC的Demo需要申请。
供电与仿真器连接如下
前提是已经安装好MDK。
双击Geehy.APM32M35XX_DFP.1.0.0.pack添加支持包
解压
APM32M35xx_SDK_V1.0.0.zip
打开APM32M35xx_SDK_V1.0.0\Examples\Board_APM32M35XX\GPIO\GPIO_Toggle\Project\MDK下的
GPIO_Toggle.uvprojx
修改APM32M35xx_SDK_V1.0.0\Boards\Board_APM32M35XX\inc\board_apm32m35xx.h中
引脚改为PA12,对应板上的fault引脚。
#define LED2_PIN GPIO_PIN_12
#define LED2_GPIO_PORT GPIOA
#define LED2_GPIO_CLK RCM_AHB_PERIPH_GPIOA
编译无错误
配置仿真器
下载进入仿真环境
Debug->Run
可看到板上fault引脚闪烁。
总结
文档和代码资料都比较规范。基于SDK开发很快就能入手很方便。
- 2024-11-27
-
回复了主题帖:
测评入围名单:极海APM32M3514电机通用评估板
个人信息无误,确认可以完成测评分享计划
- 2024-09-18
-
加入了学习《Follow me第二季第2期视频演示》,观看 演示视频
- 2024-09-14
-
回复了主题帖:
小调查:大家在学习Rust嵌入式遇到哪些困难?如果搞实战项目,有何建议?
Rust的问题就是把简单的事情复杂化了,不容易入门。
- 2024-08-29
-
回复了主题帖:
《嵌入式软件的时间分析》书友问答接龙 第十集:AUTOSAR
Autosar中Runnable和task是什么关系?
-
回复了主题帖:
《嵌入式软件的时间分析》书友问答接龙 第九集:开发过程中的方法技巧
一点小总结:
本文分享了在嵌入式软件开发的每个阶段如何考虑软件时间,
主要包括时间需求和时间分析需求,时间测试以及检测最终的产品时间。
从个人感受而言,业内尤其是国内能专门去做时间需求分析的微乎其微,
其实更多是在乎开发者个人的考虑于能力,这里提供一个简单点实践策略,
就是根据经验总结checklist而不是专门去做时间需求分析,因为大部分嵌入式软件都是类似的,
比如检查malloc/free的时间消耗,可以封装专门的带时间测试的接口,比如检查中断的执行时间,使用IO翻转示波器查看,这些常见的时间分析写入checklist,并对于通用实现一些封装可供直接调用。
- 2024-08-15
-
回复了主题帖:
《嵌入式软件的时间分析》书友问答接龙 第八集:软件运行时间优化
一点小总结:书中总结了很多时间优化的方法和示例,比如memcpy的优化剖析。
个人有点感受,书中提到的数据对齐,在嵌入式开发中其实是很容易获得比较好的优化效果的一个小的编程技巧,平常编程时就可以尽量考虑使用数据对齐。
另外减少存储的拷贝,也是一个优化时间的比较简单有效的方法。
还有就是减少循环体内的执行时间等,也是比较有用的方法,
总之一点,优化时间要先找出花费时间比较大头的地方去优化,首先从算法架构,实现方式去优化,其次才是去利用某些特定特性,比如cache去优化,因为后者往往有副作用需要注意,前者才是通用且成本低效果好的方式。
- 2024-08-08
-
回复了主题帖:
《嵌入式软件的时间分析》书友问答接龙 第七集:多核及多ECU环境下的软件时间
做个小的总结,
这章首先提到了同构,异构,锁步这三种多核架构,其中锁步架构比较有意思,感觉是在宇航级芯片上可能用的多,实际是一种冗余设计,这种冗余要考虑两种实现要不一样,避免同类错误导致"全军覆没",比如镜像放置,时钟偏置,独立时钟等等细节都是处于此考虑。
然后介绍了不同类型的并行执行:应用程序并行执行,函数的并行执行,指令的并行执行。
然后提到了数据一致性的问题,一般低端MCU都没有cache所以遇到比较少,而高端cache会有多级cache,多核,这个问题变得很突出,需要时刻关注数据一致性问题。
- 2024-08-02
-
回复了主题帖:
《嵌入式软件的时间分析》书友问答接龙 第六集:软件时间问题案例
6.5 拉着手刹去比赛,举了一个有趣的例子,由于项目复杂且从闪存执行大量代码导致速度变慢导致功能异常,使能了Cache之后速度加快功能正常了。
其实对于嵌入式开发来说,这里隐含着一个非常需要重视的问题,即事物的正反面,使能了Cache虽然大大提高了性能,但是必定导致数据一致性的问题,应用开发就需要处处关注,是否存在一致性问题,一致性问题很可能导致很多隐蔽难以发现的问题。这就是嵌入式开发中需要处处关注并且最终权衡选择的。
包括存储需求-性能的权衡,可移植性-复杂性的权衡,时间换空间,空间换时间等等。
- 2024-07-25
-
回复了主题帖:
《嵌入式软件的时间分析》书友问答接龙 第五集:软件时间分析方法
hehung 发表于 2024-7-23 13:31
调度模式的原理和工作方式是什么
调度模拟是对操作系统组织任务和中断的执行逻辑进行模拟。
选择用于模拟的操作系统->
创建任务和中断->
静态动态参数配置->
激活模式激活任务并触发中断->
生成追踪图表
-
发表了主题帖:
【瑞萨RA8D1开发板,基于M85内核的图形MCU】移植精简的shell
前面我们移植了xprintf可以方便的打印输出和输入,为了方便后面调试开发,我们进一步移植一个精简的shell,实现命令行交互。
参考微信公众号”嵌入式Lee”的文章
https://mp.weixin.qq.com/s/XLmbJn0SKoDT1aLdxHDrbg 一个超级精简高可移植的shell命令行C实现
Shell.c如下,完全可移植无需修改
#include <stdint.h>
#include "shell.h"
shell_read_pf s_input_pf = 0; /* ?????? */
shell_write_pf s_output_pf = 0; /* ?????? */
shell_cmd_cfg* s_cmd_cfg_pst = 0; /* ?????? */
uint8_t s_enableecho_u8 = 0; /* ????echo?? */
static uint8_t s_cmd_buf_au8[SHELL_CMD_LEN]="\r"; /* ????? */
static uint32_t s_cmd_buf_index_u32 = 0; /* ??????????? */
/**
* ??????
*/
static void shell_putchar(uint8_t val)
{
uint8_t tmp;
if(s_output_pf != 0)
{
tmp = val;
s_output_pf(&tmp, 1);
}
}
/**
* ???????
*/
static void shell_putstring(char* str)
{
uint32_t len = 0;
uint8_t*p = (uint8_t*)str;
while(*str++)
{
len++;
}
s_output_pf(p, len);
}
/**
* ?????
*/
static int shell_getchar(uint8_t *data)
{
if(s_input_pf == 0)
{
return -1;
}
if(0 == s_input_pf(data, 1))
{
return -1;
}
else
{
return 0;
}
}
/**
* ??????????
* ??????????
*/
static uint32_t shell_cmd_len(uint8_t *cmd)
{
uint8_t *p = cmd;
uint32_t len = 0;
while((*p != ' ') && (*p != 0))
{
p++;
len++;
}
return len;
}
/**
* ???????????,????0
*/
static int shell_cmd_check(uint8_t *cmd, uint8_t *str)
{
uint32_t len1 = shell_cmd_len(cmd);
uint32_t len2 = shell_cmd_len(str);
if(len1 != len2)
{
return -1;
}
for(uint32_t i=0; i<len1; i++)
{
if(*cmd++ != *str++)
{
return -1;
}
}
return 0;
}
/**
* ??????
*/
static uint32_t shell_read_line(void)
{
uint8_t ch;
uint32_t count;
/* ????sh> */
if(s_cmd_buf_au8[0]=='\r')
{
shell_putstring("sh>\r\n");
s_cmd_buf_au8[0] = 0;
}
/* ????????? */
if(shell_getchar(&ch) !=0 )
{
return 0;
}
/* ???????????????,?????????
* ????????,????????
*/
if((ch == '\r' || ch == '\n' || ch < ' ' || ch > '~') && (ch != '\b'))
{
if(s_cmd_buf_index_u32==0)
{
/* ?????????????????,?????sh> */
shell_putstring("sh>\r\n");
}
else
{
/* ????????,???????????????
* ?????????,?????,??????
* ???????0
*/
count = s_cmd_buf_index_u32;
s_cmd_buf_au8[s_cmd_buf_index_u32]=0;
s_cmd_buf_index_u32 =0;
shell_putstring("\r\n");
return count;
}
}
else
{
if(ch == '\b')
{
/* ????,???????????????,????? */
if(s_cmd_buf_index_u32 != 0)
{
s_cmd_buf_index_u32--;
shell_putchar('\b');
shell_putchar(' ');
shell_putchar('\b');
s_cmd_buf_au8[s_cmd_buf_index_u32]= '\0';
}
}
else
{
/* ?????,??????
* ??????????????-1,?????????
* -1?????????0??
*/
if(s_enableecho_u8 != 0)
{
shell_putchar(ch);
}
s_cmd_buf_au8[s_cmd_buf_index_u32++] = ch;
if(s_cmd_buf_index_u32>=(sizeof(s_cmd_buf_au8)-1))
{
count = s_cmd_buf_index_u32;
s_cmd_buf_au8[s_cmd_buf_index_u32]=0;
s_cmd_buf_index_u32 =0;
shell_putstring("\r\n");
return count;
}
}
}
return 0;
}
/**
* ??????????
*/
static int shell_exec_cmdlist(uint8_t* cmd)
{
int i;
if(s_cmd_cfg_pst == 0)
{
return -1;
}
for (i=0; s_cmd_cfg_pst[i].name != 0; i++)
{
if (shell_cmd_check(cmd, s_cmd_cfg_pst[i].name) == 0)
{
s_cmd_cfg_pst[i].func(cmd);
return 0;
}
}
if(s_cmd_cfg_pst[i].name == 0)
{
shell_putstring("unkown command\r\n");
return -1;
}
return 0;
}
/**
* ????,????
*/
void shell_exec(void)
{
if(shell_read_line() > 0)
{
shell_exec_cmdlist(s_cmd_buf_au8);
}
}
/**
* ????,???????
*/
void shell_set_itf(shell_read_pf input, shell_write_pf output, shell_cmd_cfg* cmd_list, uint8_t enableecho)
{
s_input_pf = input;
s_output_pf = output;
s_cmd_cfg_pst = cmd_list;
s_enableecho_u8 = enableecho;
}
Shell.h如下,完全可移植无需修改
#ifndef SHELL_H
#define SHELL_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#define SHELL_CMD_LEN 512 /**< ??????? */
typedef void (*shell_command_pf)(uint8_t *); /**< ?????? */
typedef uint32_t (*shell_read_pf)(uint8_t *buff, uint32_t len); /**< ????? */
typedef void (*shell_write_pf)(uint8_t *buff, uint32_t len); /**< ????? */
/**
* \struct shell_cmd_cfg
* ????
*/
typedef struct
{
uint8_t * name; /**< ????? */
shell_command_pf func; /**< ?????? */
uint8_t * helpstr; /**< ?????? */
}shell_cmd_cfg;
/**
* \fn shell_exec
* ???????,??????,????????????
* ???
*/
void shell_exec(void);
/**
* \fn shell_set_itf
* ??????????,??????
* ??shell_exec_shellcmd??,???????????
* \param[in] input \ref shell_read_pf ????
* \param[in] output \ref shell_write_pf ????
* \param[in] cmd_list \ref shell_cmd_cfg ????
* \param[in] enableecho 0:?????, ???:????
*/
void shell_set_itf(shell_read_pf input, shell_write_pf output, shell_cmd_cfg* cmd_list, uint8_t enableecho);
#ifdef __cplusplus
}
#endif
#endif
shell_func.c如下,可以添加自己的命令,默认实现了help命令,打印所有命令信息
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "shell.h"
#include "shell_func.h"
#include "xprintf.h"
static void helpfunc(uint8_t* param);
/**
* ???????0,??????
*/
const shell_cmd_cfg g_shell_cmd_list_ast[ ] =
{
{ (uint8_t*)"help", helpfunc, (uint8_t*)"help"},
{ (uint8_t*)0, 0 , 0},
};
void helpfunc(uint8_t* param)
{
(void)param;
unsigned int i;
xprintf("\r\n");
xprintf("**************\r\n");
xprintf("* SHELL *\r\n");
xprintf("* V1.0 *\r\n");
xprintf("**************\r\n");
xprintf("\r\n");
for (i=0; g_shell_cmd_list_ast[i].name != 0; i++)
{
xprintf("%02d.",i);
xprintf("%-16s",g_shell_cmd_list_ast[i].name);
xprintf("%s\r\n",g_shell_cmd_list_ast[i].helpstr);
}
}
Shell_func.h如下
#ifndef SHELL_FUNC_H
#define SHELL_FUNC_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern const shell_cmd_cfg g_shell_cmd_list_ast[ ];
#ifdef __cplusplus
}
#endif
#endif
实现接口
static uint32_t shell_read_port(uint8_t *buff, uint32_t len)
{
return uart_read(buff,len);
}
static void shell_write_port(uint8_t *buff, uint32_t len)
{
uart_send(buff,len);
}
设置接口
#include "shell.h"
#include "shell_func.h"
shell_set_itf(shell_read_port, shell_write_port, (shell_cmd_cfg*)g_shell_cmd_list_ast, 1);
测试
void blinky_thread_entry (void * pvParameters)
{
uart_init();
xdev_out(xprintf_out_port);
xdev_in(xprintf_in_port);
shell_set_itf(shell_read_port, shell_write_port, (shell_cmd_cfg*)g_shell_cmd_list_ast, 1);
while(1)
{
shell_exec();
vTaskDelay(1);
}
效果如下,上输入help回车,打印所有支持的命令
后面就可以方便添加更多自己的命令,方便调试开发。
- 2024-07-24
-
发表了主题帖:
【瑞萨RA8D1开发板,基于M85内核的图形MCU】移植轻量标准输入输出函数库xprintf
前面我们实现了好用的串口收发接口,进一步我们来实现基于串口的输入输出,方便后面交互打印信息等。
参考微信公众号”嵌入式Lee”的文章
https://mp.weixin.qq.com/s/y4MHV3cd4T0b51L5M4J5Xg 极海半导体APM32F107VC开发板-移植超轻量级标准输入输出函数库xprintf
Xprintf.c如下
/*------------------------------------------------------------------------/
/ Universal String Handler for Console Input and Output
/-------------------------------------------------------------------------/
/
/ Copyright (C) 2021, ChaN, all right reserved.
/
/ xprintf module is an open source software. Redistribution and use of
/ xprintf module in source and binary forms, with or without modification,
/ are permitted provided that the following condition is met:
/
/ 1. Redistributions of source code must retain the above copyright notice,
/ this condition and the following disclaimer.
/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
/
/-------------------------------------------------------------------------*/
#include "xprintf.h"
#define SZB_OUTPUT 32
#if XF_USE_OUTPUT
#include <stdarg.h>
void (*xfunc_output)(int); /* Pointer to the default output device */
static char *strptr; /* Pointer to the output memory (used by xsprintf) */
#if XF_USE_FP
/*----------------------------------------------*/
/* Floating point output */
/*----------------------------------------------*/
#include <math.h>
static int ilog10 (double n) /* Calculate log10(n) in integer output */
{
int rv = 0;
while (n >= 10) { /* Decimate digit in right shift */
if (n >= 100000) {
n /= 100000; rv += 5;
} else {
n /= 10; rv++;
}
}
while (n < 1) { /* Decimate digit in left shift */
if (n < 0.00001) {
n *= 100000; rv -= 5;
} else {
n *= 10; rv--;
}
}
return rv;
}
static double i10x (int n) /* Calculate 10^n */
{
double rv = 1;
while (n > 0) { /* Left shift */
if (n >= 5) {
rv *= 100000; n -= 5;
} else {
rv *= 10; n--;
}
}
while (n < 0) { /* Right shift */
if (n <= -5) {
rv /= 100000; n += 5;
} else {
rv /= 10; n++;
}
}
return rv;
}
static void ftoa (
char* buf, /* Buffer to output the generated string */
double val, /* Real number to output */
int prec, /* Number of fractinal digits */
char fmt /* Notation */
)
{
int d;
int e = 0, m = 0;
char sign = 0;
double w;
const char *er = 0;
if (isnan(val)) { /* Not a number? */
er = "NaN";
} else {
if (prec < 0) prec = 6; /* Default precision (6 fractional digits) */
if (val < 0) { /* Nagative value? */
val = -val; sign = '-';
} else {
sign = '+';
}
if (isinf(val)) { /* Infinite? */
er = "INF";
} else {
if (fmt == 'f') { /* Decimal notation? */
val += i10x(-prec) / 2; /* Round (nearest) */
m = ilog10(val);
if (m < 0) m = 0;
if (m + prec + 3 >= SZB_OUTPUT) er = "OV"; /* Buffer overflow? */
} else { /* E notation */
if (val != 0) { /* Not a true zero? */
val += i10x(ilog10(val) - prec) / 2; /* Round (nearest) */
e = ilog10(val);
if (e > 99 || prec + 6 >= SZB_OUTPUT) { /* Buffer overflow or E > +99? */
er = "OV";
} else {
if (e < -99) e = -99;
val /= i10x(e); /* Normalize */
}
}
}
}
if (!er) { /* Not error condition */
if (sign == '-') *buf++ = sign; /* Add a - if negative value */
do { /* Put decimal number */
w = i10x(m); /* Snip the highest digit d */
d = val / w; val -= d * w;
if (m == -1) *buf++ = XF_DPC; /* Insert a decimal separarot if get into fractional part */
*buf++ = '0' + d; /* Put the digit */
} while (--m >= -prec); /* Output all digits specified by prec */
if (fmt != 'f') { /* Put exponent if needed */
*buf++ = fmt;
if (e < 0) {
e = -e; *buf++ = '-';
} else {
*buf++ = '+';
}
*buf++ = '0' + e / 10;
*buf++ = '0' + e % 10;
}
}
}
if (er) { /* Error condition? */
if (sign) *buf++ = sign; /* Add sign if needed */
do *buf++ = *er++; while (*er); /* Put error symbol */
}
*buf = 0; /* Term */
}
#endif /* XF_USE_FLOAT */
/*----------------------------------------------*/
/* Put a character */
/*----------------------------------------------*/
void xputc (
int chr /* Character to be output */
)
{
xfputc(xfunc_output, chr); /* Output it to the default output device */
}
void xfputc ( /* Put a character to the specified device */
void(*func)(int), /* Pointer to the output function (null:strptr) */
int chr /* Character to be output */
)
{
if (XF_CRLF && chr == '\n') xfputc(func, '\r'); /* CR -> CRLF */
if (func) {
func(chr); /* Write a character to the output device */
} else if (strptr) {
*strptr++ = chr; /* Write a character to the memory */
}
}
/*----------------------------------------------*/
/* Put a null-terminated string */
/*----------------------------------------------*/
void xputs ( /* Put a string to the default device */
const char* str /* Pointer to the string */
)
{
xfputs(xfunc_output, str);
}
void xfputs ( /* Put a string to the specified device */
void(*func)(int), /* Pointer to the output function */
const char* str /* Pointer to the string */
)
{
while (*str) { /* Put the string */
xfputc(func, *str++);
}
}
/*----------------------------------------------*/
/* Formatted string output */
/*----------------------------------------------*/
/* xprintf("%d", 1234); "1234"
xprintf("%6d,%3d%%", -200, 5); " -200, 5%"
xprintf("%-6u", 100); "100 "
xprintf("%ld", 12345678); "12345678"
xprintf("%llu", 0x100000000); "4294967296" <XF_USE_LLI>
xprintf("%lld", -1LL); "-1" <XF_USE_LLI>
xprintf("%04x", 0xA3); "00a3"
xprintf("%08lX", 0x123ABC); "00123ABC"
xprintf("%016b", 0x550F); "0101010100001111"
xprintf("%*d", 6, 100); " 100"
xprintf("%s", "String"); "String"
xprintf("%5s", "abc"); " abc"
xprintf("%-5s", "abc"); "abc "
xprintf("%-5s", "abcdefg"); "abcdefg"
xprintf("%-5.5s", "abcdefg"); "abcde"
xprintf("%-.5s", "abcdefg"); "abcde"
xprintf("%-5.5s", "abc"); "abc "
xprintf("%c", 'a'); "a"
xprintf("%12f", 10.0); " 10.000000" <XF_USE_FP>
xprintf("%.4E", 123.45678); "1.2346E+02" <XF_USE_FP>
*/
static void xvfprintf (
void(*func)(int), /* Pointer to the output function */
const char* fmt, /* Pointer to the format string */
va_list arp /* Pointer to arguments */
)
{
unsigned int r, i, j, w, f;
int n, prec;
char str[SZB_OUTPUT], c, d, *p, pad;
#if XF_USE_LLI
long long v;
unsigned long long uv;
#else
long v;
unsigned long uv;
#endif
for (;;) {
c = *fmt++; /* Get a format character */
if (!c) break; /* End of format? */
if (c != '%') { /* Pass it through if not a % sequense */
xfputc(func, c); continue;
}
f = w = 0; /* Clear parms */
pad = ' '; prec = -1;
c = *fmt++; /* Get first char of the sequense */
if (c == '0') { /* Flag: left '0' padded */
pad = '0'; c = *fmt++;
} else {
if (c == '-') { /* Flag: left justified */
f = 2; c = *fmt++;
}
}
if (c == '*') { /* Minimum width from an argument */
n = va_arg(arp, int);
if (n < 0) { /* Flag: left justified */
n = 0 - n; f = 2;
}
w = n; c = *fmt++;
} else {
while (c >= '0' && c <= '9') { /* Minimum width */
w = w * 10 + c - '0';
c = *fmt++;
}
}
if (c == '.') { /* Precision */
c = *fmt++;
if (c == '*') { /* Precision from an argument */
prec = va_arg(arp, int);
c = *fmt++;
} else {
prec = 0;
while (c >= '0' && c <= '9') {
prec = prec * 10 + c - '0';
c = *fmt++;
}
}
}
if (c == 'l') { /* Prefix: Size is long */
f |= 4; c = *fmt++;
#if XF_USE_LLI
if (c == 'l') { /* Prefix: Size is long long */
f |= 8; c = *fmt++;
}
#endif
}
if (!c) break; /* End of format? */
switch (c) { /* Type is... */
case 'b': /* Unsigned binary */
r = 2; break;
case 'o': /* Unsigned octal */
r = 8; break;
case 'd': /* Signed decimal */
case 'u': /* Unsigned decimal */
r = 10; break;
case 'x': /* Hexdecimal (lower case) */
case 'X': /* Hexdecimal (upper case) */
r = 16; break;
case 'c': /* A character */
xfputc(func, (char)va_arg(arp, int)); continue;
case 's': /* String */
p = va_arg(arp, char*); /* Get a pointer argument */
if (!p) p = ""; /* Null ptr generates a null string */
j = strlen(p);
if (prec >= 0 && j > (unsigned int)prec) j = prec; /* Limited length of string body */
for ( ; !(f & 2) && j < w; j++) xfputc(func, pad); /* Left pads */
while (*p && prec--) xfputc(func, *p++);/* String body */
while (j++ < w) xfputc(func, ' '); /* Right pads */
continue;
#if XF_USE_FP
case 'f': /* Float (decimal) */
case 'e': /* Float (e) */
case 'E': /* Float (E) */
ftoa(p = str, va_arg(arp, double), prec, c); /* Make fp string */
for (j = strlen(p); !(f & 2) && j < w; j++) xfputc(func, pad); /* Left pads */
while (*p) xfputc(func, *p++); /* Value */
while (j++ < w) xfputc(func, ' '); /* Right pads */
continue;
#endif
default: /* Unknown type (passthrough) */
xfputc(func, c); continue;
}
/* Get an integer argument and put it in numeral */
#if XF_USE_LLI
if (f & 8) { /* long long argument? */
v = (long long)va_arg(arp, long long);
} else {
if (f & 4) { /* long argument? */
v = (c == 'd') ? (long long)va_arg(arp, long) : (long long)va_arg(arp, unsigned long);
} else { /* int/short/char argument */
v = (c == 'd') ? (long long)va_arg(arp, int) : (long long)va_arg(arp, unsigned int);
}
}
#else
if (f & 4) { /* long argument? */
v = (long)va_arg(arp, long);
} else { /* int/short/char argument */
v = (c == 'd') ? (long)va_arg(arp, int) : (long)va_arg(arp, unsigned int);
}
#endif
if (c == 'd' && v < 0) { /* Negative value? */
v = 0 - v; f |= 1;
}
i = 0; uv = v;
do { /* Make an integer number string */
d = (char)(uv % r); uv /= r;
if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
str[i++] = d + '0';
} while (uv != 0 && i < sizeof str);
if (f & 1) str[i++] = '-'; /* Sign */
for (j = i; !(f & 2) && j < w; j++) xfputc(func, pad); /* Left pads */
do xfputc(func, str[--i]); while (i != 0); /* Value */
while (j++ < w) xfputc(func, ' '); /* Right pads */
}
}
void xprintf ( /* Put a formatted string to the default device */
const char* fmt, /* Pointer to the format string */
... /* Optional arguments */
)
{
va_list arp;
va_start(arp, fmt);
xvfprintf(xfunc_output, fmt, arp);
va_end(arp);
}
void xfprintf ( /* Put a formatted string to the specified device */
void(*func)(int), /* Pointer to the output function */
const char* fmt, /* Pointer to the format string */
... /* Optional arguments */
)
{
va_list arp;
va_start(arp, fmt);
xvfprintf(func, fmt, arp);
va_end(arp);
}
void xsprintf ( /* Put a formatted string to the memory */
char* buff, /* Pointer to the output buffer */
const char* fmt, /* Pointer to the format string */
... /* Optional arguments */
)
{
va_list arp;
strptr = buff; /* Enable destination for memory */
va_start(arp, fmt);
xvfprintf(0, fmt, arp);
va_end(arp);
*strptr = 0; /* Terminate output string */
strptr = 0; /* Disable destination for memory */
}
#if XF_USE_DUMP
/*----------------------------------------------*/
/* Dump a line of binary dump */
/*----------------------------------------------*/
void put_dump (
const void* buff, /* Pointer to the array to be dumped */
unsigned long addr, /* Heading address value */
int len, /* Number of items to be dumped */
size_t width /* Size of buff[0] (1, 2 or 4) */
)
{
int i;
const unsigned char *bp;
const unsigned short *sp;
const unsigned long *lp;
xprintf("%08lX ", addr); /* address */
switch (width) {
case sizeof (char):
bp = buff;
for (i = 0; i < len; i++) { /* Hexdecimal dump in (char) */
xprintf(" %02X", bp[i]);
}
xputs(" ");
for (i = 0; i < len; i++) { /* ASCII dump */
xputc((unsigned char)((bp[i] >= ' ' && bp[i] <= '~') ? bp[i] : '.'));
}
break;
case sizeof (short):
sp = buff;
do { /* Hexdecimal dump in (short) */
xprintf(" %04X", *sp++);
} while (--len);
break;
case sizeof (long):
lp = buff;
do { /* Hexdecimal dump in (short) */
xprintf(" %08lX", *lp++);
} while (--len);
break;
}
xputc('\n');
}
#endif /* XF_USE_DUMP */
#endif /* XF_USE_OUTPUT */
#if XF_USE_INPUT
int (*xfunc_input)(void); /* Pointer to the default input stream */
/*----------------------------------------------*/
/* Get a line from the input */
/*----------------------------------------------*/
int xgets ( /* 0:End of stream, 1:A line arrived */
char* buff, /* Pointer to the buffer */
int len /* Buffer length */
)
{
int c, i;
if (!xfunc_input) return 0; /* No input function is specified */
i = 0;
for (;;) {
c = xfunc_input(); /* Get a char from the incoming stream */
if (c < 0 || c == '\r') break; /* End of stream or CR? */
if (c == '\b' && i) { /* BS? */
i--;
if (XF_INPUT_ECHO) xputc(c);
continue;
}
if (c >= ' ' && i < len - 1) { /* Visible chars? */
buff[i++] = c;
if (XF_INPUT_ECHO) xputc(c);
}
}
if (XF_INPUT_ECHO) {
xputc('\r');
xputc('\n');
}
buff[i] = 0; /* Terminate with a \0 */
return (int)(c == '\r');
}
/*----------------------------------------------*/
/* Get a value of integer string */
/*----------------------------------------------*/
/* "123 -5 0x3ff 0b1111 0377 w "
^ 1st call returns 123 and next ptr
^ 2nd call returns -5 and next ptr
^ 3rd call returns 1023 and next ptr
^ 4th call returns 15 and next ptr
^ 5th call returns 255 and next ptr
^ 6th call fails and returns 0
*/
int xatoi ( /* 0:Failed, 1:Successful */
char **str, /* Pointer to pointer to the string */
long *res /* Pointer to the valiable to store the value */
)
{
unsigned long val;
unsigned char c, r, s = 0;
*res = 0;
while ((c = **str) == ' ') (*str)++; /* Skip leading spaces */
if (c == '-') { /* negative? */
s = 1;
c = *(++(*str));
}
if (c == '0') {
c = *(++(*str));
switch (c) {
case 'x': /* hexdecimal */
r = 16; c = *(++(*str));
break;
case 'b': /* binary */
r = 2; c = *(++(*str));
break;
default:
if (c <= ' ') return 1; /* single zero */
if (c < '0' || c > '9') return 0; /* invalid char */
r = 8; /* octal */
}
} else {
if (c < '0' || c > '9') return 0; /* EOL or invalid char */
r = 10; /* decimal */
}
val = 0;
while (c > ' ') {
if (c >= 'a') c -= 0x20;
c -= '0';
if (c >= 17) {
c -= 7;
if (c <= 9) return 0; /* invalid char */
}
if (c >= r) return 0; /* invalid char for current radix */
val = val * r + c;
c = *(++(*str));
}
if (s) val = 0 - val; /* apply sign if needed */
*res = val;
return 1;
}
#if XF_USE_FP
/*----------------------------------------------*/
/* Get a value of the real number string */
/*----------------------------------------------*/
/* Float version of xatoi
*/
int xatof ( /* 0:Failed, 1:Successful */
char **str, /* Pointer to pointer to the string */
double *res /* Pointer to the valiable to store the value */
)
{
double val;
int s, f, e;
unsigned char c;
*res = 0;
s = f = 0;
while ((c = **str) == ' ') (*str)++; /* Skip leading spaces */
if (c == '-') { /* Negative? */
c = *(++(*str)); s = 1;
} else if (c == '+') { /* Positive? */
c = *(++(*str));
}
if (c == XF_DPC) { /* Leading dp? */
f = -1; /* Start at fractional part */
c = *(++(*str));
}
if (c <= ' ') return 0; /* Wrong termination? */
val = 0;
while (c > ' ') { /* Get a value of decimal */
if (c == XF_DPC) { /* Embedded dp? */
if (f < 0) return 0; /* Wrong dp? */
f = -1; /* Enter fractional part */
} else {
if (c < '0' || c > '9') break; /* End of decimal? */
c -= '0';
if (f == 0) { /* In integer part */
val = val * 10 + c;
} else { /* In fractional part */
val += i10x(f--) * c;
}
}
c = *(++(*str));
}
if (c > ' ') { /* It may be an exponent */
if (c != 'e' && c != 'E') return 0; /* Wrong character? */
c = *(++(*str));
if (c == '-') {
c = *(++(*str)); s |= 2; /* Negative exponent */
} else if (c == '+') {
c = *(++(*str)); /* Positive exponent */
}
if (c <= ' ') return 0; /* Wrong termination? */
e = 0;
while (c > ' ') { /* Get value of exponent */
c -= '0';
if (c > 9) return 0; /* Not a numeral? */
e = e * 10 + c;
c = *(++(*str));
}
val *= i10x((s & 2) ? -e : e); /* Apply exponent */
}
if (s & 1) val = -val; /* Negate sign if needed */
*res = val;
return 1;
}
#endif /* XF_USE_FP */
#endif /* XF_USE_INPUT */
Xprintf.h如下
/*------------------------------------------------------------------------*/
/* Universal string handler for user console interface (C)ChaN, 2021 */
/*------------------------------------------------------------------------*/
#ifndef XPRINTF_DEF
#define XPRINTF_DEF
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
#define XF_USE_OUTPUT 1 /* 1: Enable output functions */
#define XF_CRLF 1 /* 1: Convert \n ==> \r\n in the output char */
#define XF_USE_DUMP 1 /* 1: Enable put_dump function */
#define XF_USE_LLI 1 /* 1: Enable long long integer in size prefix ll */
#define XF_USE_FP 1 /* 1: Enable support for floating point in type e and f */
#define XF_DPC '.' /* Decimal separator for floating point */
#define XF_USE_INPUT 1 /* 1: Enable input functions */
#define XF_INPUT_ECHO 0 /* 1: Echo back input chars in xgets function */
#if defined(__GNUC__) && __GNUC__ >= 10
#pragma GCC diagnostic ignored "-Wcast-function-type"
#endif
#if XF_USE_OUTPUT
#define xdev_out(func) xfunc_output = (void(*)(int))(func)
extern void (*xfunc_output)(int);
void xputc (int chr);
void xfputc (void (*func)(int), int chr);
void xputs (const char* str);
void xfputs (void (*func)(int), const char* str);
void xprintf (const char* fmt, ...);
void xsprintf (char* buff, const char* fmt, ...);
void xfprintf (void (*func)(int), const char* fmt, ...);
void put_dump (const void* buff, unsigned long addr, int len, size_t width);
#endif
#if XF_USE_INPUT
#define xdev_in(func) xfunc_input = (int(*)(void))(func)
extern int (*xfunc_input)(void);
int xgets (char* buff, int len);
int xatoi (char** str, long* res);
int xatof (char** str, double* res);
#endif
#ifdef __cplusplus
}
#endif
#endif
blinky_thread_entry.c中实现接口
static void xprintf_out_port(int ch)
{
uint8_t val = ch;
uart_send(&val,1);
}
static int xprintf_in_port(void)
{
uint32_t len;
uint8_t val;
do
{
len = uart_read(&val,1);
}while(len == 0);
return val;
}
设置接口,blinky_thread_entry中初始化
xdev_out(xprintf_out_port);
xdev_in(xprintf_in_port);
测试代码如下
#include "xprintf.h"
/* Blinky Thread entry function */
void blinky_thread_entry (void * pvParameters)
{
uart_init();
xdev_out(xprintf_out_port);
xdev_in(xprintf_in_port);
while(1)
{
//static uint8_t rx_buffer[64];
//uint32_t rlen = uart_read(rx_buffer,sizeof(rx_buffer));
//if(rlen > 0)
//{
// uart_send(rx_buffer,rlen);
//}
xprintf("%d\n", 1234); /* "1234" */
xprintf("%6d,%3d%%\n", -200, 5); /* " -200, 5%" */
xprintf("%-6u\n", 100); /* "100 " */
xprintf("%ld\n", 12345678); /* "12345678" */
xprintf("%llu\n", 0x100000000); /* "4294967296" <XF_USE_LLI> */
xprintf("%lld\n", -1LL); /* "-1" <XF_USE_LLI> */
xprintf("%04x\n", 0xA3); /* "00a3" */
xprintf("%08lX\n", 0x123ABC); /* "00123ABC" */
xprintf("%016b\n", 0x550F); /* "0101010100001111" */
xprintf("%*d\n", 6, 100); /* " 100" */
xprintf("%s\n", "abcdefg"); /* "abcdefg" */
xprintf("%5s\n", "abc"); /* " abc" */
xprintf("%-5s\n", "abc"); /* "abc " */
xprintf("%.5s\n", "abcdefg"); /* "abcde" */
xprintf("%-5.2s\n", "abcdefg"); /* "ab " */
xprintf("%c\n", 'a'); /* "a" */
xprintf("%12f\n", 10.0); /* " 10.000000" <XF_USE_FP> */
xprintf("%.4E\n", 123.45678); /* "1.2346E+02" <XF_USE_FP> */
while(1)
{
char input_buffer[32];
char* str = input_buffer;
xprintf("please input two int\r\n");
xgets(input_buffer, sizeof(input_buffer));
long a;
xatoi(&str,&a);
long b;
xatoi(&str,&b);
xprintf("%d+%d=%d\r\n",a,b,a+b);
}
}
测试效果如下
打印正常,输入正常
-
发表了主题帖:
【瑞萨RA8D1开发板,基于M85内核的图形MCU】基于FIFO的串口收发接口
本帖最后由 qinyunti 于 2024-7-24 23:48 编辑
前面我们实现了串口的收发测试,现在来基于FIFO实现好用的串口收发接口。FIFO的实现参考微信公众号”嵌入式Lee”的文章
https://mp.weixin.qq.com/s/MvL9eDesyuxD60fnbl1nag 超级精简系列之十三:超级精简的循环FIFO,C实现
Fifo.c源码如下
#include <string.h>
#include "fifo.h"
#define FIFO_PARAM_CHECK 0
/**
* in????? 0~(buffer_len-1)?
* out????? 0~(buffer_len-1)?
* in == out?????,?????,????len??????????
* ???in??,?????out???
* ????out??,?????in???
* in??out??[out,in)????????
* in??out??[out,buffer_len)?[0,in)????????
***********************************************************
* 0 buffer_len-1 buffer_len
* (1)?? in?out??0
* | |
* in(0)
* out(0)
* len = 0
* (2)??n???? in??n?out??0 ??in??out???
* | |
* out(0)������������>in(n) |
* len = n
* (3)??m????(m<n) in??n?out??m ??in??out???
* | |
* out(m)����>in(n)
* len = n-m
* (4)??????,?????,??in??out???
* | |
* out(m)��������������������������������>
* ��>in(k)
* len = k + buffer_len-m
*/
uint32_t fifo_in(fifo_st* dev, uint8_t* buffer, uint32_t len)
{
uint32_t space = 0; /* ?????????? */
/* ???? */
#if FIFO_PARAM_CHECK
if((dev == 0) || (buffer == 0) || (len == 0))
{
return 0;
}
if(dev->buffer == 0)
{
return 0;
}
#endif
/* ??len??????buffer?? */
if(len > dev->buffer_len)
{
len = dev->buffer_len;
}
/* ????????
* ??dev->len?????dev->buffer_len
*/
if(dev->buffer_len >= dev->len)
{
space = dev->buffer_len - dev->len;
}
else
{
/* ???????, ?????? */
dev->len = 0;
space = dev->buffer_len;
}
/* ???????, ??len???????????????? */
len = (len >= space) ? space : len;
if(len == 0)
{
return 0; /* ??????????,???? */
}
/* ??len??????????,?????? */
space = dev->buffer_len - dev->in; /* ??????in???????????? */
if(space >= len)
{
/* ??????in??????????? */
memcpy(dev->buffer+dev->in,buffer,len);
}
else
{
/* ??????in???????,????????? */
memcpy(dev->buffer+dev->in,buffer,space); /* ???tail?? */
memcpy(dev->buffer,buffer+space,len-space); /* ???????? */
}
/* ????????????? */
dev->in += len;
if(dev->in >= dev->buffer_len)
{
dev->in -= dev->buffer_len; /* ????? ?? dev->in %= dev->buffer->len */
}
dev->len += len; /* dev->len??dev->buffer->len,??%= dev->buffer->len */
return len;
}
uint32_t fifo_out(fifo_st* dev, uint8_t* buffer, uint32_t len)
{
uint32_t space = 0;
/* ???? */
#if FIFO_PARAM_CHECK
if((dev == 0) || (buffer == 0) || (len == 0))
{
return 0;
}
if(dev->buffer == 0)
{
return 0;
}
#endif
/* ??????? */
if(dev->len == 0)
{
return 0;
}
/* ?????????????????? */
len = (dev->len) > len ? len : dev->len;
/* ??len??????????,?????? */
space = dev->buffer_len - dev->out; /* ??????out???????????? */
if(space >= len)
{
/* ??????out??????????? */
memcpy(buffer,dev->buffer+dev->out,len);
}
else
{
/* ??????out???????,????????? */
memcpy(buffer,dev->buffer+dev->out,space); /* ???tail?? */
memcpy(buffer+space,dev->buffer,len-space); /* ???????? */
}
/* ????????????? */
dev->out += len;
if(dev->out >= dev->buffer_len)
{
dev->out -= dev->buffer_len; /* ????? ?? dev->out %= dev->buffer->len */
}
dev->len -= len; /* ??dev->len ?????len,???? */
return len;
}
uint32_t fifo_getlen(fifo_st* dev)
{
#if FIFO_PARAM_CHECK
if(dev == 0)
{
return 0;
}
#endif
return dev->len;
}
void fifo_clean(fifo_st* dev)
{
#if FIFO_PARAM_CHECK
if(dev == 0)
{
return 0;
}
#endif
dev->len = 0;
dev->in = 0;
dev->out = 0;
}
Fifo.h源码如下
#ifndef FIFO_H
#define FIFO_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
/**
* \struct fifo_st
* FIFO?????.
*/
typedef struct
{
uint32_t in; /**< ???? */
uint32_t out; /**< ???? */
uint32_t len; /**< ?????? */
uint32_t buffer_len; /**< ???? */
uint8_t* buffer; /**< ??,???? */
} fifo_st;
/**
* \fn fifo_in
* ?fifo????
* \param[in] dev \ref fifo_st
* \param[in] buffer ??????
* \param[in] len ??????
* \retval ??????????
*/
uint32_t fifo_in(fifo_st* dev, uint8_t* buffer, uint32_t len);
/**
* \fn fifo_out
* ?fifo????
* \param[in] dev \ref fifo_st
* \param[in] buffer ??????
* \param[in] len ?????????
* \retval ??????????
*/
uint32_t fifo_out(fifo_st* dev, uint8_t* buffer, uint32_t len);
uint32_t fifo_getlen(fifo_st* dev);
void fifo_clean(fifo_st* dev);
#ifdef __cplusplus
}
#endif
#endif
Uart.c中定义fifo实例
static uint8_t s_uart_rx_buffer[64];
static fifo_st s_uart_fifo_dev=
{
.in = 0,
.len = 0,
.out = 0,
.buffer = s_uart_rx_buffer,
.buffer_len = sizeof(s_uart_rx_buffer),
};
串口接收中断中,将数据写入fifo
void user_uart3_callback(uart_callback_args_t *p_args);
void user_uart3_callback(uart_callback_args_t *p_args)
{
uint8_t tmp;
switch (p_args->event)
{
case UART_EVENT_TX_COMPLETE:
g_data_transmit_flag = true;
break;
case UART_EVENT_TX_DATA_EMPTY:
g_data_transmit_flag = true;
break;
case UART_EVENT_RX_COMPLETE:
// Start Transmission
fifo_in(&s_uart_fifo_dev, rx_buffer, 1);
R_SCI_B_UART_Read(&g_uart3_ctrl, (uint8_t * const)(rx_buffer), 1U);
//uart_send(rx_buffer,1);
break;
case UART_EVENT_RX_CHAR:
tmp = g_uart3_ctrl.p_reg->RDR_BY;
fifo_in(&s_uart_fifo_dev, &tmp, 1);
//uart_send(&tmp,1);
break;
default:
break;
}
}
临界段接口,中断中操作fifo无需临界段保护,uart_read再线程中调用,需要临界段保护。
#define CriticalAlloc()
#define EnterCritical() __disable_irq()
#define ExitCritical() __enable_irq()
串口读接口,从fifo中读数据
uint32_t uart_read(uint8_t* buffer, uint32_t len)
{
uint32_t rlen;
CriticalAlloc();
EnterCritical();
rlen = fifo_out(&s_uart_fifo_dev, buffer, len);
ExitCritical();
return rlen;
}
最终的uart.c如下
#include "hal_data.h"
#include <stdio.h>
#include <stdbool.h>
#include "r_uart_api.h"
#include "r_sci_b_uart.h"
#include "uart.h"
#include "blinky_thread.h"
#include "fifo.h"
#define CriticalAlloc()
#define EnterCritical() __disable_irq()
#define ExitCritical() __enable_irq()
static uint8_t s_uart_rx_buffer[64];
static fifo_st s_uart_fifo_dev=
{
.in = 0,
.len = 0,
.out = 0,
.buffer = s_uart_rx_buffer,
.buffer_len = sizeof(s_uart_rx_buffer),
};
volatile bool g_data_transmit_flag = false;
uint8_t rx_buffer[1];
void user_uart3_callback(uart_callback_args_t *p_args);
void user_uart3_callback(uart_callback_args_t *p_args)
{
uint8_t tmp;
switch (p_args->event)
{
case UART_EVENT_TX_COMPLETE:
g_data_transmit_flag = true;
break;
case UART_EVENT_TX_DATA_EMPTY:
g_data_transmit_flag = true;
break;
case UART_EVENT_RX_COMPLETE:
// Start Transmission
fifo_in(&s_uart_fifo_dev, rx_buffer, 1);
R_SCI_B_UART_Read(&g_uart3_ctrl, (uint8_t * const)(rx_buffer), 1U);
//uart_send(rx_buffer,1);
break;
case UART_EVENT_RX_CHAR:
tmp = g_uart3_ctrl.p_reg->RDR_BY;
fifo_in(&s_uart_fifo_dev, &tmp, 1);
//uart_send(&tmp,1);
break;
default:
break;
}
}
int uart_init(void)
{
fsp_err_t err;
err = R_SCI_B_UART_Open(&g_uart3_ctrl, &g_uart3_cfg);
if (FSP_SUCCESS != err)
{
return -1;
}
else
{
// Start Transmission
err = R_SCI_B_UART_Read(&g_uart3_ctrl, (uint8_t * const)(rx_buffer), 1U);
if (FSP_SUCCESS != err)
{
return -1;
}
return 0;
}
}
uint32_t uart_send(uint8_t* buffer, uint32_t len)
{
g_data_transmit_flag = false;
for(uint32_t i=0;i<len;i++)
{
g_uart3_ctrl.p_reg->TDR_BY = buffer;
while((g_uart3_ctrl.p_reg->CSR_b.TEND == 0) || (g_uart3_ctrl.p_reg->CSR_b.TDRE == 0));
}
//fsp_err_t err = R_SCI_B_UART_Write(&g_uart3_ctrl, (uint8_t * const)(buffer), len);
//if (FSP_SUCCESS != err)
//{
// return 0;
//}
// Wait for event receive complete
//while (!g_data_transmit_flag)
//{
//}
return len;
}
uint32_t uart_read(uint8_t* buffer, uint32_t len)
{
uint32_t rlen;
CriticalAlloc();
EnterCritical();
rlen = fifo_out(&s_uart_fifo_dev, buffer, len);
ExitCritical();
return rlen;
}
Uart.h如下
#ifndef UART_H
#define UART_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
int uart_init(void);
uint32_t uart_send(uint8_t* buffer, uint32_t len);
uint32_t uart_read(uint8_t* buffer, uint32_t len);
#ifdef __cplusplus
}
#endif
#endif
测试
blinky_thread_entry.c中
#include "uart.h"
void blinky_thread_entry (void * pvParameters)
{
uart_init();
while(1)
{
static uint8_t rx_buffer[64];
uint32_t rlen = uart_read(rx_buffer,sizeof(rx_buffer));
if(rlen > 0)
{
uart_send(rx_buffer,rlen);
}
}
发送任意数据原样返回
以上实现了方便好用的串口收发接口,基于fifo接口简单非常方便。