发帖数

43

原创数

43

关注者

17

阅读数

10116

点赞数

2

张角

  • RISC-V鸿蒙系统开发板SPI通信模块调试3(项目连载6)


    大家好,我们继续SPI通信接口部分的调试分析。

    上篇文章我们提到CLK的波形幅值最高处只有2.2V,远远没有达到3.3V这一芯片工作电压。同时CLK波形的底部也不是0V。我们因此怀疑RISC-V单片机发出的CLK波形,存储芯片有可能分辨不出来。应该说这个怀疑是合理的。如果大家想从最基础的原理上去辨别出来这个波形的正确性,需要仔细去研读单片机和Flash存储芯片的datasheet。因为我们这块板子是参考睿思芯科一块老的开发板来进行设计的,在他们原有的开发板上这个Flash存储芯片是可以正常读取的。那么我们可以先测试一下原有板子这个引脚处的CLK波形是什么样子的,对比一下就知道,CLK的这个波形是不是正确的。

    下图是我们实际测试到的他们原有开发板上CLK引脚处的波形,大家可以看一下这个波形。这个波形的幅值和频率和我们现有开发板上的波形是一致的,那换句话说我们这个我们板子上的CLK信号也是可以让存储芯片正常工作的。

    图片13.jpg

    既然CLK波形是没有问题,那为什么还收不到数据呢?那我们看一下MOSIMISO的波形,看一看到底是哪里出问题了。如果单片机这一侧能够发送控制信号到W25Q128这一侧,按理说应该是MOSI这条回路是没有问题的。如果MISO这条回路,在单片机侧能够收到波形,那说明MISO这条信号传输回路没有问题;某种意义上它还可以说明,存储芯片W25Q128FVSG收到单片机指令之后,进行了响应。

    图片14.jpg

    大家看一下这个波形,这个是MOSI回路在W25Q128这一侧测到的波形。这个至少可以说明了刚才我们提到的结论:单片机成功给W23Q128发送了信号。

    图片15.jpg

    大家看一下这个波形,这个是MISO回路在芯片这一侧的波形。如果使用示波器的捕获功能,同时使用两个通道来捕获波形,一个是MISO,一个是CLK,那么截取的波形就是下面这个样子。

    图片16.jpg

    同样地,这个图片也说明了一个结论,那就是W25Q128确实收到了单片机发出的指令,并且进行了响应,只是波形不对。那问题出在哪了呢?大家看一下MISO的波形,这个信号也出现了“高”没有“高”上去,有些地方“低”却没有“低”下来的情况。波形看起来比较奇怪,看不出来,这个到底是什么数据。

    问题卡在这里了,那到底是哪里出错了呢?

    首先引起怀疑的就是时钟信号的频率有点太高了,以至于MISO这根线上相应的器件响应速度根本反应不过来,或者是发生了震荡,所以才导致了这种高不高、低不低的情况发生。

    解决这个问题的办法,一般是在发送引脚和接收引脚之间串联一个电阻,用以防止震荡的发生,但是因为我们这个电路已经画好了,已经没有办法再增加电阻。目前能够尝试的办法就是降低信号发送的频率了。降低信号的频率之后,震荡自然也就不会发生了。

    图片17.jpg

    调试的方向明确了,我们要从软件上把通信时钟的频率降低下来,这里要做三处更改。因为SPI接口读取Flash的程序是使用Linux kernel里面的框架来写的,改动起来相对来说比较复杂。

    主要修改的地方有三处,我们在这里耽误了不少时间,主要的原因是这个kernel框架比较复杂。SPI1_CLK_DIV_DWH是一个宏,我们可以通过更改这个宏的值,来改变系统时钟分频的系数。

    图片18.jpg

    图片19.jpg

    图片20.jpg


    不过,比较悲催地是,频率降低以后,MISO的波形依然是不对的,还是这种不高不低的样子。那就奇怪了,这到底是什么原因引起的呢?实在是有点难以理解呀。信号传输的电路都是通的,而且都有波形出来,只是波形不对,难道是存储芯片坏了?不应该呀。实在是不应该出现这样的错误。

    那读取W25Q128 ID的波形具体应该是什么样子的呢?根据W25Q128这个芯片的datasheet,读取它的ID时,MISO返回的数据应该是这样的。

    图片21.jpg

    调试到这个时候,实在是已经没有可怀疑的了。只能是怀疑睿思芯科提供的参考原理图是错误的(芯片刚刚出来,资料不齐全,这个也是可以理解的),经过仔细的引脚比对,果不其然,他们提供的原理图接口顺序是不对的。我的天!在这里,来来回回调试了一周的时间,最后的结果竟然是原理图错了!!!虽然都是用的这四个引脚,但是接线顺序是不对的,唯一正确的就是CLK!!!

    把接线顺序调整后,实测MISO的波形,如下。

    图片22.jpg

    高位在前,低位在后,大家是不是可以判断出这个波形表示的数据是(EFh)呀。

    读取ID的指令只要能够发送成功,那么其他指令自然也是可以发送成功的。程序模块中对Flash芯片的数据擦除、写入也就成功了。

    现在需要总结的一个问题是,为什么刚一开始的时候,我没有怀疑到它的原理图可能是错误的呢?我总结一下,可能有两个原因。第一是,芯片本身的资料是不全的,引脚核对工作不是那么方便;第二是,他们提供了一个参考的板子,这个板子上的SPI Flash芯片是可以正常读取的,这个现象在一定程度上,打消了我对他们接线图的怀疑。这个事情告诉我们,对于不成熟的东西,一定要仔细根据最可靠的文档来核对自己的电路是不是正确。因为不成熟,大家都比较容易犯错,以至于以讹传讹。

    希望我分享的相关调试经验,能够给大家带来一些帮助。


    收藏 0 回复 0 浏览 155
  • 基于RISC-V单片机的鸿蒙开发板项目简介(项目连载1)

    大家好,我是张飞实战电子的张角老师。我目前正在做的一个项目是开发一块基于RISC-V架构单片机的鸿蒙系统开发板。

     

    鸿蒙系统是华为公司开发的新一代物联网操作系统系统,RISC-V单片机是不同于ARM架构的单片机,目前形势一片大好。在美国对我国芯片以及操作系统等高新科技的疯狂打压的背景下,鸿蒙系统以及RISC-V架构单片机这两种产品的发展以及突破显得尤其重要。它们两个很大概率上会是电子信息领域我们突破美国技术封锁的两个突破口。

     

    张飞实战电子,愿意在力所能及的情况下,为这两块产品的推广添砖加瓦,贡献自己的力量。为此,我们愿意把这块基于RISC-V架构单片机的鸿蒙系统开发板的实现过程,尽可能清楚的展现给大家,争取越详细越好,为大家以后进行相关的产品开发提供一些经验参考。

     

    这块开发板使用的单片机是深圳睿思芯科的Pygmy-E系列的单片机,这是一款32位的面向IOT领域的单片机,具备超低功耗的特性以及丰富的外设接口。

     

    开发板的硬件电路模块包括电源电路,电平转换电路,单片机最小电路,USBSPI电路,USBUART电路,温湿度检测电路,片外SPI Flash电路,红外模块检测电路,开关检测电路,蜂鸣器电路,流水灯电路。

     

    电源电路包括12V电源接口电路,12V5V Buck电路,5V3V3 Buck电路,3V3 1V8 LDO电路,3V30V9 buck电路,3V30V 8 buck电路。BUCK电源和LDO电源是我们做开发板的过程中非常常用的电源,在这个模块,我将和大家分享下BUCK以及LDO电路的设计方法。

     

    电平转换电路主要是利用双向电平转换芯片TXS0104以及TXB0104等实现电平的双向转换。为什么我们需要电平转换芯片呢,主要是因为我们使用的这块单片机是还处于验证阶段,单片机IO的电平是1V8,而我们常用器件的电平以3V3的居多,比如我们用的FT4222 USBSPI芯片,SHT20温湿度检测传感器等。

     

    单片机最最小外围电路包括供电模块,晶振模块,复位电路模块,BOOT启动模块等。

     

    其他模块电路我们就不一一介绍了,等以后我们再展开分析。

    软件这块,我们打算依据硬件电路开发一些demo。这些demo主要分为三个板块,一个是睿思芯科RISCV单片机的外围驱动开发模块,主要包括GPIOUARTI2CSPI等接口的驱动开发;一个是鸿蒙系统Liteos-M模块的内核实验;再一个就是,利用外围电路我们我们要演示的一些demo,比如流水灯,蜂鸣器唱歌,红外信号检测,温湿度检测,外置SPI Flash读取等。

     

    软件的开发和编译是在Ubuntu 中进行的,会使用到一些简单的Linux命令。这里我们会尽可能详细的介绍清楚编译环境的搭建,以及调试过程。

     

    整个项目涉及到的硬件、软件等相关的东西比较庞杂,我们争取尽可能清晰完整地展现所有的细节。因此估计更新的时间会比较长,期待大家能够和我一起坚持到最后。久久为功,方能修成正果。一起加油!

     


    收藏 0 回复 0 浏览 146
  • 斜坡补偿的由来

    在开关电源中,有一个相对不容易解释清楚,但是对整个系统的稳定性又起到重要作用的知识点-斜坡补偿。我们打算后面用一系列文章来深入探讨一下这方面的知识,争取让大家能够对这块内容有相对深入的理解。


    我们首先需要回答的问题,就是开关电源系统为什么需要斜坡补偿,或者说斜坡补偿解决了哪方面的问题?从宏观上看,开关电源的调节系统可以分为两部分,一个是内环电流环,一个是外环电压环。之所以把电流环称之为内环,主要是因为它的调节速度更快,属于单周期调节。电压环,调节速度相对电流环肯定是更慢的,对于输出滤波电容来说,电压是电流的积分。电流环调节的结果要经过数十个周期之后,才能在电压信号上做出反应。


    当系统的输出电流或者说电感电流,因为负载变化或者输入电压变化产生扰动的时候,在电压环起到调节作用之前,有可能发生电感电流的次谐波震荡,或者说是电感电流的振铃现象。


    这里之所以说是有可能,主要是因为这个现象发生在CCM模式下,而且占空比大于50%的时候。当占空比小于50%的时候,扰动电流的震荡会自动趋于收敛。我们下面用图形化的方式给大家演示一下。

    image.png

    上图是占空比小于50%的时候,负载变化引起的电流扰动。大家可以看一下,这个扰动在几个周期后,会自动收敛。具体为什么会收敛呢?我们可以推算一下电流扰动量的变化公式。

    image.png


    大家可以看一下,当占空比小于50%的时候,Ton的时间内电流上升的斜率大于Toff时间内电流下降的斜率。那么这个电流抖动量的变化趋势和这两个斜率的比值很有关系。


    具体的推导公式,如上图所示。我们这里是分两个三角形来进行计算的。在θ0的三角形内,根据正切关系可以得到δIo和It(两个三角形的公共部分)比例关系式①。实际上这个正切关系本质上是不是就是斜率呀。同样的,在θ1这个三角形内,我们也可以得到式子②。这两个式子化简以后,就会得到关系式③。大家可以看一下,δI1是不是要比δIo要小呀,因为m2小于m1,对吧。当占空比小于50%的时候,是不是m2一定小于m1呀。那么经过几个周期的迭代,是不是扰动量慢慢变小后,系统也就收敛了。


    但是当占空比大于50%的时候,也就是m2大于m1的时候,这个扰动量是不是也来越大,结果也就会出现电感电流的震荡,如下图所示。

    image.png

    对于控制系统的开关芯片而言,Ton的时间也就会出现波动,也就是会出现所谓的大小波交替现象的发生。这个波动的电流对系统的稳定性是无益的,需要想办法解决掉。那么该怎么解决呢?这个也就是斜坡补偿的由来:既然这种情况下m2大于m1,我们能不能通过斜坡补偿的方式使得整体的斜率大小关系发生改变呢?


    下篇文章,将会对这个问题进行更深入的分析。


    收藏 0 回复 0 浏览 141
  • RISC-V开发板SPI通信模块调试1(项目连载4)

    我们这块开发板使用的是W25Q128FVSG这个Flash进行外部存储的,这个Flash和单片机之间的通信方式是SPI通信。Flash模块焊接完成之后,一直通信不成功,我们在这个地方的调试花费了非常长的时间。有不少经验值得总结分享。

    还是先上实物图和原理图,给大家一个感性的认识。

    图片1.jpg

    1  W25Q128FVSG连接电路

    上图是SPI Flash实物接口电路,红框中的就是W25Q128FVSG芯片。黄框里面的是1.8V3.3V双向电平转换芯片。为什么需要这个电平转换芯片呢,主要是因为我们单片机的IO接口输入输出是1.8V的电平,然而这个存储Flash的工作电压是3.3V。这个1.8V的芯片IO输出电压,在实际使用的单片机中是比较少见的,我们这款单片机某种程度上应该算是一种原型机,1.8V的电压是芯片内部的电压。

    图片2.jpg


    2 SPI接口电路原理图

    关于SPI接口电路图的原理部分,我们在这里就先不做详细介绍了,整体也比较简单,具体的接线方式,我们可以查看一下datasheet引脚的对接口的描述方式。然后按照datasheet的接线要求来接就可以了。

    比如datasheet中,对WP引脚的描述,是这样的。

    图片3.jpg


    它说这个WPWrite Protect)是低有效的,也就是说这个引脚被拉低的时候,Flash存储芯片是没有办法写入数据的。我们自己的程序是需要往存储芯片写数据,那么这个引脚肯定是要被拉高的。

    再比如这个Hold引脚,datasheet中的描述如下,显然这个也是低有效,也就是说Hold引脚被拉低的时候,DO这个引脚是高阻抗状态,也就是说无法进行数据传输了。我们自己的程序肯定是需要数据传输的,所以这个引脚是要被拉高的。

    图片4.jpg

    上面两个部分的举例,主要是为了说明我们画原理图的时候,如何根据datasheet引脚进行端口确认。不少时候,我们可以直接拿到别人的原理图,进行参考。不过我个人的看法还是自己详细读一下datasheet,再进行一下确认,一是防止被别人带进坑里去,另外一个也能够让自己在调试的时候更有信心。

    我们的Flash读取程序是基于一个Linux内核SPI NOR框架,比如在linux5.2.0内核中,关于这个框架的说明在 “Documentation/mtd/spi-nor.txt”这个文档中。大家先对这个框架有所理解就行,等系列文章分享完成后,我这边会把所有的代码给大家共享。

    图片5.jpg


    在对FLASH存储模块存入、读取、擦除数据的操作实施之前,我们第一步是不是要先验证这个芯片是不是我们需要的芯片呀。那怎么验证呢?在程序中使用的办法,就是读取这个FlashID,看看芯片反馈回来的IDdatasheet说明的是不是一致。

    图片6.jpg

    在程序中,就是通过这一段代码来实现的。但是实际收取到的信息却是如下的,那说明读取不成功。

    图片7.jpg

    正确读取的时候,JEDEC id的结果应该是这样的。

    图片8.jpg

    那该怎么解决这个问题呢,SPI调试系列的第二篇文章,我会给大家详细的剖析一下调试过程。


    收藏 0 回复 0 浏览 136
  • 讲透有史以来广受欢迎的运算放大器μA741(1)---镜像电流源,Widlar电

    大家好,我是张飞实战电子张角老师!

    从今天起,我们开始分析运放uA741的内部结构,争取把它的工作原理给大家讲清楚,讲透彻。只有知道了运放的内部结构,我们才真正可能看得清楚运放的一些参数,在运放选型的时候,才会更加有的放矢。

    虽然较新设计的运算放大器在几乎所有可能的方面(速度、噪音、电压范围等等)都超过了它,但最初的741仍然广受喜爱,并在今天依然大量使用。我们对运放的学习,不能仅仅止步于外围电路的搭建,那样对运放的了解不可能深刻。我想通过这一系列的文章,争取能够把uA741这款运放的工作原理给大家讲解得尽可能透彻,让大家在学习运放的时候,能够更加深入,少走一些弯路。

    与设计外围电路不同,电流源在运放内部更加常用。比如恒流源、镜像电流源、Widlar电流源、增强型镜像电流源等等。为什么会出现这样的情况呢?其中最为主要的原因,就是运放需要放大的是差分信号,那么这里就遇到一个问题:如何把电压差转化为一个差值信号。运放内部目前选择的方案,就是把电压差转化为电流差。那么要产生这个电流差信号,就需要恒流源,其实这里类似一个加法。两个电流之和是一个恒流,那么一个电流大了,肯定另一个电流就小了。有了这个电流差之后,运放内部的电路再把这个差值信号转化一个电压差信号,然后通过这个电压差信号驱动中间级的放大电路。中间级的放大电路现在一般采用达林顿管来实现,这样放大倍数就会很大了,假定每一级的放大倍数是200倍,那么达林顿管总体的放大倍数就会有200*200 = 40000倍。实现了信号放大以后,输出级需要解决的就是功率输出的问题了。毕竟运放是一个模拟器件,它需要一定的带载能力,一般情况下,输出级主要是使用推挽电路来做的。当然因为受制于封装的原因,这个电流值也不能太大,所以这里还有保护电路存在(限流作用)。

    整体上运放的工作原理,就如上面所示,741也不例外。

    大家最常见到的电流源,估计就是电流镜或者说叫做镜像电流源源了。它常见的拓扑结构如下图所示。这个电路的目的,就是实现Io电路和Iref几乎是相同的。这样的话,如果我们要想获得一个特定的电流Io,那么我们只需要去设定Iref就可以了,也就是说Iref侧进行电流的设定,在Io侧实现电流的输出。而下面这个电路,就像镜子一样,可以实现电流的映射。

    image.png

    这个镜像电流源的工作原理,大体如下。因为T1T2是在同一个晶圆上刻出来的,所以它们具有较高的对称性。T1T2的引脚是连接在一起的,所以它们对地的电位是相同的。因为对地的电位是相同的,所以它们的基极电流也是相同的。我们说这两个管子是在同一块晶圆上雕刻出来的,那么它们的放大倍数是也是近似相同的。那么当两个管子都是处于放大状态的时候,他们的Ic电流也就是相同,也就是Ic1 = Io

    那么到了此时,我们只是实现了Ic1Io的镜像关系。但是我们设计的目的其实是Io=Iref,是吧,那么也就是说这里存在一定的误差。这个误差值是多少呢,是不是Ibf是吧。按照上图画下来,Ibf = 2*Ib,对吧。如果T1T2这两个运放的放大倍数比较大,我们假定100倍好吧,那么Ibf带来的误差是不是差不多在1/50左右呀。这个误差,是不是可以近似忽略呀,所以我们可以在总体上认为Io就等于Iref。上面提到的就是镜像电流源的工作原理。

    我们明白了镜像电流工作原理之后,要想产生我们需要的电流,比如10uA。按照我们上面的思路,那么第一个工作,是不是要指定Iref。但是这里面临一个问题,就是这个10uA的电流,如果使用电阻限流的方式来搞,那么就需要非常大的电阻。我们假定供电电压是20V,电流是10uA,那么差不多需要2MR的电阻,这个电阻值太大了。电阻值太大了,芯片在封装的时候,就会面临体积上的问题:电阻越大,某种程度上意味着体积越大。这对芯片设计是非常不利的,所以我们面临一个问题,就是如何使用更小的电阻去产生一个较小的电流呢?

    在运放内部,实现这个功能的,就是Widlar电流源。我们也可以把它理解成在镜像电流源上的改进版。这个电流源的拓扑如下图所示。

    image.png

    我这里先给大家分析一下,这个电路的工作原理。本质上,这里是通过R2上电阻的分压,减少了Vbe2的电压值。T1T2这里都是处于放大状态,Vbe2的电压值变小了,那么那么流经BE PN节的电流值也就变小了,进而放大之后的电流值Ic也就变小了。那么这样的话,即使Iref这边有很大的电流,Io那边的电流也不会很大,这样就解决了R1电阻太大不好封装的问题。具体的公式推导如上图所示,Is是二极管的反向饱和电流,UT=k*T/q,是一个常数。但是这个电流源也有一定的问题,大家看一下公式中存在UT这个常数,但是UT是容易受到温度影响的,所以Io自然也就容易受到温度影响。如果,我们对电流的值要求很精密,这个电流源可能就满足不了要求了。

    解决了Iref电流值设定的问题之后,我们基本上解决了运放中电流源设计的主要障碍。但是我们说运放放大部分和功率部分的最好都踩在地上,我们才好进行电路设计是吧。实际上,大家如果常看运放内部的结构图的话,经常会发现恒流源的符号,但是这个符号经常是挂在源端的。比如像LM324这个片子,它内部的恒流源符号很多。关于图中的恒流源是怎么做的,可能会有一些疑问,毕竟这块的电路图,很少有厂商会画出来。

    image.png

    那么也就是说,我们希望的是不是一个P管做的恒流源,不是N管的对吧。一般P管做的恒流源放在源端,N管做的恒流源放在地端是吧。其实P管的恒流源和N管的恒流源思路是一样的

    那么如图所示,Iref是不是就可以映射到Io上去了呀,这样这个电流源是不是就可以为后面的负载所用了,对吧。但是741使用的并不是这样的方案,它使用的是一个电流反馈的思路,本质上应该是一样的。我们下一篇文章,继续分析741运放的电流源的部分。

    image.png


    收藏 0 回复 0 浏览 135
×
张角