发帖数

50

原创数

50

关注者

12

阅读数

8966

点赞数

4

蔡琰

  • USB与TTL通信之默契轨道---技术剖析(一)

    话说做这个转换的全隔离小模块也是因为自己做单片机软件设计那么多年,各种通信端口软件都做过,然而需要调试都会用到这些辅助模块来跟上位机通信,这个是最简洁的通信验证方式,那么这些小模块还是很容易坏的,好多时候都会赶在项目节点上突然故障,被迫停下赶紧采购,影响进度不说,还很影响调试产品的心情啊,所以才想去研究设计一个,自己做过的不是用起来也会顺手一些呢。


    首先开始分析实现流程,然后选取集成芯片等工作。

    开始了,那一起看下标题,我想要实现的是转换通信模块,那么需要一个转换芯片;还有就是全隔离,自然需要一个隔离芯片。这是大体方向,细节再慢慢实现下吧。


    1、既然是USB转,那么我直接用USB供电就好了,就不需要再外部供电了

    输入5V电,后端TTL也是5V;输入端加个保险丝,以及后面加的隔离芯片,都是为了保护电脑USB接口。输入端一般我会加一个LED灯,指示用的。

    1.png


    2、输入后的信号就开始进行转换了,我选用了CH340G转换芯片,附件可以自行查看下数据手册啊,如果对你其他项目有帮助可以查看下呢。

    信号线一般需要加个小电阻(10R够了)做防震荡作用,这个芯片工作起来需要一个晶振,晶振的起震电容设计就不用多说了吧,电源端部分还要有储能和滤波电容,这个也不用多说了吧,那么一起来看下转换端部分的设计原图:

    2.png


    3、信号转换后就是进行全隔离了,前面加保险丝的时候说明了隔离的作用,就是保护,有些时候我们也知道如果没隔离,对于我们的USB接口还是有不确定性的,接入的模块你不确定会不会有干扰,什么干扰,我觉得还是很有必要对这些频繁用到的模块加隔离比较稳妥,个人见解。

    对于隔离,除了信号还有电源和地的隔离,这才叫全隔离,那上图看下吧。

     

    3.png

    4.png

    另外输出部分有电源、地、信号发送接收了,输出是5V输出能力100mA,如果目标板电流过大,建议使用外部独立电源供电,使用外部独立供电时可不接5V,但必须要接GND,这个是要注意的。

    主要部分的设计就完成了,是不是觉得其他我们平时买的小模块内容也没想象中那么复杂,其实做任何设计都要选定芯片研读芯片手册,不管做软件设计也好,硬件设计也好,只是关注点不一样。当然还有一些是经验值。

    当我们熟悉了这些模块的设计,即便买来的碰到故障了不是很容易分析处理一下的,最起码不会影响工作进度的。多学点总归没错的。


    后面就开始设计PCB过程了,最后产品出来就可以通信使用了,每个过程都会有收获的,如果大家感兴趣的话就持续关注我吧。后面会陆续分享出我的设计视频过程,随时欢迎大家跟我来探讨,也让我可以开阔下思路,或许还有其他实现方式,不同的尝试过程才是经验积累成长的过程。


    收藏 0 回复 0 浏览 121
  • BMS电池管理系统

    大家好!我是张飞实战电子蔡琰老师,今天给大家分享BMS电池管理系统


    随着新能源、可穿戴设备等的发展,BMS成为热议的话题,经久不衰,这篇文章我们就一起来学习一些关于BMS的知识。



    Q1.什么是BMS?

    BMS是对电池进行监控和管理的系统(Battery Management System),通过对电池的电压、电流、温度、剩余容量(SOC)、放电功率,报告电池劣化程度(SOH)、电池均衡管理、报警提醒等参数采集、计算进而控制电池放电过程,实现对电池的保护,提升电池综合性能的管理系统。它还根据电池的电压电流及温度用算法控制最大输出功率以获得最大续航,用算法控制充电机进行最佳电流的充电,它通过通信线与其他控制单元进行通信,比如我们手机或新能源汽车的快充、电量显示等都与BMS有着密切的关系。



    Q2.动力电池和非动力电池区别?

    提到电池,一般被分为动力电池和非动力电池,新能源汽车的动力来源一般主要是以动力电池为主。一般,动力电池实际上就是为交通运输工具提供动力来源的一种电源。它与普通电池的主要区别为动力电池相比于普通电池,其放电功率大。它可以在很短的时间内将电池的电放完。动力电池一般容量要小于非动力电池。



    Q3.什么是充放电倍率?

    一般电池后面的xxC它表示了电池的放电能力,C:用来表示电池充放电电流大小的比率,即倍率。充放电倍率=充放电电流/额定容量,例如1000mAh的电池,1C放电,就是1A放电,那么1个小时就可以放完,2C放电,就是2A放电,半个小时就可以放完。当然不同材质的电池,放电能力也是不一样的。



    Q4.什么是均衡控制?

    生产制造和使用过程的差异性,造成了动力电池单体天然就存在着不一致性。不一致性主要表现在单体容量、内阻、自放电率、充放电效率等方面。单体的不一致,传导至动力电池包,必然的带来了动力电池包容量的损失,进而造成寿命的下降。


    根据木桶短板效应,充电和放电时都是性能最差的单体先达到截止条件,其他还有一部分能力并未释放出来,这样就造成了浪费。


    电池单体的不一致,会随着时间的推移,在温度以及振动条件等随机因素的影响下进一步恶化,趋势无法逆转,但可以干预,降低它的恶化速率。方法之一就是通过电池管理系统对电芯实施均衡。


    均衡包括主动均衡和被动均衡,被动均衡,运用电阻器,将高电压或者高荷电量电芯的能量消耗掉,以达到减小不同电芯之间差距的目的,是一种能量的消耗。主动均衡,运用储能器件等,将荷载较多能量的电芯部分能量转移到能量较少的电芯上去,是能量的转移。


    但是均衡也存在一定的局限性,被动均衡,电流无法完全按照实际需求去做,因为通过电阻消耗的能量,转化成热量,对电池管理系统以及电池包都会产生不良影响;主动均衡,需要配置相应电路和储能器件,体积大,成本上升,这两个条件一起决定了主动均衡不容易推广应用。电池包的每个充电放电过程,都伴随着一部分电池局部的附加充放过程,无形中增加了电池的循环次数。



    Q5.一般BMS管理系统是什么样的?

    在一些系统中对成本的要求比较高,比如手扶电动两轮车,在这个系统中BMS电池管理系统设计也相对简单一些,仅由一颗专用的管理芯片即可实现电池管理,当然这个管理是纯硬件的,没有加入软件,实现一些基本的功能:正常充放电、过充过放、温度保护、平衡等。


    在复杂的管理系统中,从系统层次来进行架构管理,会引入一些控制单元(如单片机)做一些控制算法,它不仅包含硬件,还包含底层软件、应用层软件等。

    image.png

    如上图(来源于网络),分为主控,从控,电压电流采集控制、仪表显示等功能,非常复杂。单单这一个系统里面用到的单片机数量是十分可观的。


    上面我们简单对BMS一些问题进行了了解,作为控制工程师,首先学好单片机是非常重要的,还等什么,赶紧行动起来吧!


    收藏 0 回复 0 浏览 114
  • 程序的调试和宏使用的技巧

    在程序的开发过程中,调试语句是程序开发的一种主要的辅助手段。C语言主要的调试语句使用的是printf,它的定位是系统的标准输出。在嵌入式系统中,printf()的输出可能是屏幕、也可能是串口。


    #字符串转化操作符

    在编译系统中,可以使用#将当前的内容转换成字符串,例如:

    #define dprint(expr)  printf(<main>%s = %d n,#expr,expr)


    ①在程序中可以使用如下的方式调用:

    1.jpg

    在以上的例子中,使用#expr表示根据宏中的参数(即表达式的内容),生成一个字符串。因此,#expr代表将dprintexpr)括号中的内容生成一个字符串。一般来说,宏中的参数将作为一个变量被引用,而增加了#修饰之后的表达式,即代表了将宏中的参数名称直接转换成字符串。

    上述过程同样是由编译器产生的,编译器在编译源文件的时候,如果遇到了类似的宏(示例中的dprint)会自动根据程序中表达式的内容,生成一个字符串的宏(示例中的#expr)。这样宏同样可以在程序中表示一个字符串。


    ②进一步,在程序中可以按照如下的形式调用以上宏:

    2.jpg

    从运行结果的第一行可以看到,编译器的生成字符串的时候,不会照搬宏参数中的所有内容,注释类的内容是不会被放入字符串的宏,这也是因为去注释是编译器预处理阶段的内容,也就是说在实际的编译过程之前,程序中的注释已经被去掉。从运行结果的第二行看出,由于a不是整数,而是字符串的指针,因此打印出a的值实际是变量a的地址,而字符串的内容依然是a。从运行结果的第三行看出,对于直接写入程序的数值(立即数),编译器也可以将它的内容转换成字符串。


    这种方式的优点是可以用统一的方法打印表达式的内容,在程序的调试过程中可以方便直观地看到转换成字符串之后的表达式。具体的表达式的内容是什么,是由编译器“自动”写入程序中的,这样使用相同的宏打印所有表达式的字符串。


    由于#expr本质就是一个表示字符串的宏,因此在程序中也可以不使用%打印它的内容,而是可以将其直接和其他的字符串连接。上面的宏可以等价为以下的形式:

    #define dprint (expr)  printf(<main> #expr =%d n,expr)

    注意:#C语言预处理阶段的字符串转化操作符,可以将宏中的内容转换成字符串。


    ##:连接操作符

    在编译系统中,##C语言中的连接操作符,可以在编译的预处理阶段实现字符串连接的操作。

    以下的程序是一个使用##的示例:

    #define test(x) test ## x

    void test1(int a)      void test2(char *s)

    {         {

    printf(Test 1 interger: %d n,a);   printf(Test 2 String : %s n,s);

    }         }

    3.jpg

    在上面这个程序,test(x)宏被定义为test##x,它表示test字符串和x字符串的连接,因此test(1)将被预处理器为:test1,test(2)将被预处理器处理为:test2。预处理器仅仅是转换字符串而已,所以上面的test1test2刚好转换成两个函数的名称。


    条件编译调试语句


    在嵌入式系统的调试中,调试语句可以在程序运行的过程中输出程序的运行状态。然而调试语句的调用是有开销的,在最终发布版的程序中,调试语句都是应该去掉的。去掉调试语句最简单的方式将其注释掉,但是主要就需要维护两种源程序:一种是带有调试语句的调试版程序,另一种是不带有调试语句的发布版程序。这显然不是一种很好的方式,理想的方式是只有一套源程序,根据不同的条件编译选项,编译出不同的调试版和发布版的程序。


    在实现的过程中,可以使用一个调试宏来控制调试语句的开关,如下所示:

    #ifndef USE_DEBUG

    #define DEBUG_OUT(fmt,args...) printf(File:%s Function:%s Line:%dfmt,_FILE_,_FUNCTION_,_LINE_,

    ##args)

    #else

    #define DEBUG_OUT(fmt,args...)

    #endif

    在上面的程序中,宏USE_DEBUG用来控制调试语句的开关,当USE_DEBUG被定义的时候,将调试语句DEBUG_OUT定义成上面部分的形式,当没有定义的时候,宏定义为空,在这种情况下,即使程序中写很多DEBUG_OUT,编译器也会将其处理为没有任何语句。

    注意:一条语句太长换行需要在每行的结尾使用,表示下一行的内容是和上面的连续的。


    使用do...while的宏定义


    使用宏定义可以将一些较为短小的功能封装,方便使用。宏的形式和函数类似,但是可以节省函数跳转的开销。如何将一个语句封装成一个宏,在程序中常常使用do...while(0)的形式,例如,对一个简单打印的语句的宏封装如下所示:

    #define HELLO(str)  do{ printf(hello:%sn,str); }while(0)

    在上面这个语句中,将实际执行的功能封装在一个do...while(0)循环内。事实上,do...while(0)由于条件不成立,因此循环体之间的语句只会执行一次。然而,这样做的好处是就是可以让do...while(0)之中的语句像函数一样使用,而不必担心编译器发生错误。


    如果直接把后面语句放入宏使用,不用do...while,那么宏在一般顺序执行语句中使用没有问题,如果使用在if...else中,都会发生错误编译。事实上,一般的语句中多一个分号,只相当于多了一条空语句,没有影响。这里却是在if语句后面多出一个分号,它们代表if语句的结束。因此,后面的else就会被视为一条新的语句(相当于前面没有if只有else,这就会发生编译错误。


    而如果使用do...while(0)的形式就没有以上的问题,而且一般的C语言编译器都会对do...while(0)进行优化,使其和一般的一条函数等价,在其中可以含有任意条语句。

    收藏 0 回复 0 浏览 113
  • 【重磅】在这 一芯难求 各种涨价的时代,STM32G0闪亮登场了........

    由于芯片制造工艺的区别,STM32G0被委以重任,撑起一片天,据我从官方了解的情况可以得出一个结论,不管从价格上还是从性能上STM32G0都可以用来代替STM32F0,我们话不多说直接来看看它的区别:

    一:我们从外部封装引脚上来看

    1.jpg 

    G0没有F0的100PIN的封装,但是它增加了SO8封装的引脚,这样的话性能很强大,价格很有诱惑力,极具性价比。


    二:我们从外设配置资源来看:

     2.jpg

     

    1. 内核更高级:F0:Cortex-M0内核,主频高达48MHZ;G0:Cortex-M0+内核,主频高达64MH,主频高,程序运行更快!

    2. G0的FLASH存储器方面有缩小,SRAM方面有扩展。

    4.  ADC速率更高,F0:ADC时钟频率提高到14Mhz,G0:ADC时钟频率提高到16Mhz,G0的AD模拟采样转换速率更快。举例:(1.5为采样周期,12.5为转换周期)

    G0:With ADC_CLK = 16 MHz and a sampling time of 1.5 ADC clock cycles:

    Tconv = 1.5 + 12.5 = 14 ADC clock cycles = 0.875 µs

    F0:With ADC_CLK = 14 MHz and a sampling time of 1.5 ADC clock cycles:

    Tconv = 1.5 + 12.5 = 14 ADC clock cycles = 1 µs

    5.  外设资源更丰富,增加了AES加密单元、普通定时器单元、硬件随机数RNG单元、DMA多路复用请求仲裁单元,可编程映射DMA请求,好处是使DMA通道对应的外设更加灵活,不再受限、低功耗串口等,更加安全高效。当然相比之下也有牺牲,比如说全速USB2.0,串口数量、CAN等。


    三:我们从系统架构上来瞧瞧看:

    3.jpg

    4.jpg

    1. F0的AHB2总线消失了,引入了新的IOPORT总线,STM32F0的GPIO Ports由总线矩阵通过AHB2总线访问,STM32G0的GPIO Ports直接挂在IOPORT总线上CPU可直接访问,速度更快!


    5.jpg 

    2. STM32F0的外部中断EXIT模块由总线矩阵通过AHB1总线->(AHB->APB桥)来访问,STM32G0的外部中断EXIT模块由总线矩阵通过AHB1总线直接访问,速度更快!


    四:从时钟来看:

    6.jpg 

    由于内核使用区别,两款芯片的RCC时钟也略有区别,如上图所示,主要体现在内部的时钟资源及频率差异,最大主频差异以及复位后的系统时钟频率差异。


    五:从电源供电来看

     

    7.jpg 

    供电电压范围更宽,G0:1.6V-3.6V    F0:1.8V-3.6V,相比之下G0的低功耗睡眠模式更加出色。


    六:最后跟大家看一下M0和M0+内核的区别

    8.jpg 

     

    除了上面展示的内容之外,还有部分区别未展示,比如说中断向量表的内容有改变,G0支持向量表位置重定义、低功耗改善等等、其中不得不提到一点相比F0,G0增加了内部外设的互联功能,通过配置外设中间可直接互联,可以减小CPU额外开销!


    收藏 0 回复 0 浏览 103
  • STM32学习回忆录---------第3次写流水灯程序

    这是我第3次用STM32写流水灯程序了,感触颇深,想和大家分享我学习STM32的故事。


                     初次相识STM32

    2008年春天的第一场雪,来的比往年更大一些,这个春节,我留在深圳,无法回到河南。我在街上乱逛,无意间看到公交站台上的广告,深圳会在春季举办IIC (国际集成电路)大会,那是我刚刚大学毕业,学的是芯片制造专业,所以我决定参加。

     

    到那一天,在会展上,我看到了国外IC的先进制程,心想中国再过几年也会达到这个水平吧。

    后来,我看到了一个蝴蝶展厅,那是STM32展馆,我感觉这个芯片不错。这是我和STM32的初次相识。

     

    几年以后,STM32在国内迅速火了起来,因为我的专业在国内很难找到工作,我决定学习STM32


       1次学习STM32

     

    培训地点: 河南郑州,时间: 2013年,学习方式:线下。

    这是我第1次用STM32写流水灯,也是第一次用库函数,使用的芯片是STM32F103,用库函数的方式写流水灯,终于告别了寄存器,当时认为这是一种先进的方法,因为使用起来相当方便,想着以后单片机就不用查寄存器了,这是单片机历史上的伟大跨越。这个老师的教学方式是直接使用库函数,没有讲过库函数。在学习中,查错是一件让我头痛的事情,没有用过单步仿真,出现问题不知道,错在哪里,库函数固然好用,但库函数无法找出错误。使用printf(),有效果,但效果有限。我的这个老师非常诚实,我有不会的问题,他能给我解决就解决了,解决不了,老师就会说:“这个我也不会” !


     

    2次学习STM32

     

    培训地点: 广东深圳,时间: 2016年,学习方式:线下。

    这是我第2次用STM32写流水灯,也是用库函数的方式,使用的芯片是STM32F103。这个老师的水平要高一些,他把用到的库函数都讲了一遍,但是很少讲解寄存器。当我写流水灯程序的时候,我不仅会用库函数,而且还能够看懂库函数。当时觉得官方的库函数写的太好了,我不禁为官方点赞!。我问老师,这个启动代码能不能讲一下,老师说:你会用就行了,启动代码官方已经为你写好了,你不用知道为什么,你需要知道哪个是F1 的启动代码就可以了。出现错误的时候,依然没有查看寄存器和变量,用的是printf(),来进行调试,排查错误还是让人头疼。

    4月份的时候,我参加了STM32深圳峰会,官方介绍了CubeMx ,并说这是一种比库函数还方便的图形化编程方法,我认为汇编语言过时了,用C语言查寄存器的方法也过时了,现在STM32用的是库函数,但这种方法必将被CubeMx 所代替,因为随着编程技术的不断发展,新的技术必然会取代旧的技术。

    随着STM32 学习的深入,我开始学习一些高大上的东西,例如 触摸屏CAN SDIO 文件系统 USB等,难度太大了,我陷入其中,无法自拔。


    3次学习STM32

    培训地点: 河南老家,时间2021年,学习方式:线上。

     

    学了单片机两个月了,以流水灯为例,学到了前两次所没有学到的东西,因此感悟大不相同。

     

    1. 对寄存器的操作,就是往正确的地址写或读正确的数据。有点像送快递的,找到地址送或收快递。

     

    2. 能够被编译器发现的错误,解决比较容易,而能通过编译,却不能实现期望的功能,这种错误往往要费点时间,这个需要单步仿真,查看寄存器或变量值,此便对错误进行定位,因此必须缩小代码的范围,从工程到文件,到函数,到语句,这个有点像修电路板,从电路板到单元电路,最终找到坏的那个元器件。有些情况下,即便通过单步调试,但当整个程序运行时,还是无法实现功能。这时,还要对程序进行优化,直到实现期望的功能。自己的程序出现错误,自己检查几遍都检查不出来,但是交给别人,别人很快就能找到问题,可是问题来了,自已必须具备查错的能力,因为别人不可能总为你查错。

     

    3.即然编译器可以把C语言翻译为汇编语言,那么写程序的人也能够这样,汇编语言有一定的难度,不是面向人的,那么就可以用面向人的C语言,去翻译成汇编语言,用C语言作为桥梁,就可以大大降低难度。不得不承认,汇编语言在一些场合,还是要用到的,无法替代,例如有的8位单片机,或者FOC中。以前,我认为学习单片机,跳过汇编语言,跳过寄存器,是一种好的方法,但事实并非如此!而操作寄存器是一种通用的方法,不受库函数的依赖,换了单片机,依旧可以很快上手!

     

    我感觉这两个月确实收获很大,报这个单片机线上班我觉得很值,比前两个靠谱多了,因为我发现:我再也不用走弯路了!

     

     

     

                                                                       河南学员

       2021/3/26


    收藏 0 回复 0 浏览 101
×
蔡琰