发帖数

50

原创数

50

关注者

12

阅读数

8744

点赞数

4

蔡琰

  • 8脚51单片机DIY时间显示+闹钟技术分享(三)

    PCB设计

    延续前篇,感谢大家能关注我的实现过程,废话不多说,接下来就是跟大家分享我的PCB设计过程了,PCB设计首先就是先把板框做好了,因为这个小玩意是自己想来做的,所以板框也自定义就好。然后把原理图导入到PCB,就开始实现PCB设计过程了,在这里我主要分享我的设计思路,布局以及走线需要避开的坑。


    具体实现如果大家感兴趣的话也可以试一下的,会有很多收获的。后面我会分享出我的实现过程的视频部分,如果大家感兴趣可以关注下呢,可以跟自己做的对比下,到时候欢迎大家跟我多交流学习哈~


    那我就继续了,首先呢导入了就是开始设置规则了,我们知道做任何事情都要有规则,有了规则才不会乱套,大城市之所以好,是因为规则性好,人人守规则才会有更好的发展。我们接着回来说下布局前的规则设置,我一般的设置都有哪些,大家都有自己的习惯,我先分享出我的习惯,如果有更好的建议随时欢迎沟通,

    接下来我就开始规则设置了:

    1、先是间距设置,常规我设置线的间距(线和线,线和过孔等的距离)是0.2mm,这是经验值;然后我会设置敷铜间距,单独添加间距规则设置敷铜的间距,这个我设置的0.3mm,根据实际情况来定,这个也是我的经验值。



    1.jpg


    2、接下来就是线宽了,线宽推荐值我不变,最小线宽设置为0.2mm,最大设置为2mm,一般情况下布线常规线宽就是推荐值,电源和地线会用大点,所以这里规则要先设置好。

    2.jpg


    3、接着就是设置过孔,对于过孔来说,有内径大小和外径大小,都有相应的最小值、推荐值和最大值,在这里我只改变内径最小值(0.3mm)和外径的最小值(0.6mm),其他就是默认就可以了。

    3.jpg

    4、接下来就是我会设置下敷铜连接方式,单独新建规则来设置过孔的连接方式,常规默认是十字连接,这里我设置为直连就可以了。

    4.jpg


    5、后面的设置就是孔到孔的间距、最小阻焊的间距、丝印到阻焊的间距、丝印到丝印的间距、元件的间距,这些我一般都会全部设置为0,主要靠自己布局把握了。

    主要规则设置就上面这些,其他我会在过程中需要的情况下再进行设置,但是主要设置就是这些,规则设置好更方便布局以及走线,否则过程中一直出现绿色报错还要去看规则会影响工作进度还会影响心情的吧,所以为了工作效率还是先把规则设置好,至少我是这样认为的。


    那么规则设置好了,就开始布局之旅了,布局也是有讲究的,当设计一个产品时,器件放哪里更合理,器件间的特性关系都是需要有考量的。

    一般我设计过程都是左边输入,右边输出原则。

    首先需要完成四个孔,安装用的,分别在四个脚的位置,M3孔,具体画图方法可以参考后续这个小闹钟的视频设计过程,这里就不详细说了,如下面所示:

    5.png

     

    继续看下布局方面,由于这个是小闹钟,又是选用USB供电,所以左端是USB口,需要外接的是供电端和程序下载端口,所以程序下载端口选择放在右边。DIY的闹钟,所以显示(所有LED)放在顶层,其他元件全部放在底层。这样看起来也清爽多了。

    按照模块化布局,再移入板框中,首先从左边开始看,

    USB供电进来,我把电池和时钟芯片放在这里,跟供电相关的部分,由于把下载端口放在右边了,所以单片机放在右边。看下图布局,电池,时钟芯片,晶振,三极管,还有电阻,电容。滤波电容放在管脚端,效果更好。这是正面布局哦。

     

    6.png


    接下来看下数码管驱动芯片,因为我把按键放在板子上端了,所以这个芯片放在中间比较合理,周边就是一些限流电阻、滤波和储能电容,先摆好吧,参考下呢

    7.png


    接下来看下就剩下单片机和蜂鸣器了,单片机管脚有跟数码管芯片连接,如果把蜂鸣器放在中间会比较难走线,所以单片机放在数码管驱动芯片旁边,接着是蜂鸣器和下载端口了,依次这样排开就可以方便走线了。

    8.jpg

    布局的大体过程就是这样的,具体还要根据走线再做调整。

    接下来我跟大家分享下我的走线过程,走线需要注意的,其实走线是需要细致的过程,真的是需要一直调整器件,调整线,最终目的就是合理,正确。


    首先走线大家可能都知道不能走直线,然后电源和地我选择粗线(0.4mm),其他线都是推荐值就可以了。地的部分是通过敷铜共地的,所以需要大过孔来共地,有的地方需要打过孔是为了铜皮电位平等。线尽量走的有规则些,所以在走线的过程先考虑好哪些在顶层,哪些在底层,否则过程中走的越来越乱,并且这个小闹钟看似简单,实际还是很需要下功夫的,具体的实现后面会有详细视频,因为走线还是需要实践的,我只能说下我的思路和一些需要注意的地方,具体的每条线的走向描述还是看视频来的直接点。当然后面要是出产品还有敷铜,DRC检测,出图等很多呢,再有提醒一点需要加的就是泪滴,这个是手动焊接对焊盘连接线的保护。这里我只分享设计过程,那些流程化的东西就可以省掉了,但是做事一定要认真,每个细节都要认真对待,每次你的认真都会得到回报的,我们的付出都在慢慢得到印证的。

    最终的效果图大家看下呢,


    9.png

    做到这里所有布局和走线的思路都讲完了,其实纵观看下只要有条理,还需要细心,然后就都可以实现。PCB设计就这样完成了,大家看下我的设计有没有值得借鉴的地方或者有需要改进的,随时欢迎沟通交流。实现方法有很多,或者大家有更多更好的方法呢,欢迎来交流啊。后面会陆续更新,下面一篇会展现我的程序设计过程,感兴趣的持续关注

    收藏 0 回复 0 浏览 73
  • 单片机漫漫学习路

    当你在懵懂的年纪的时候,是否也对身边的新鲜事物感兴趣过?也试过很多超越想象的第一次?每个人都是在慢慢成长,有时候会碰到喜欢的事情留恋不已,回想起来是不是觉得当时也是对的?谁还没点回忆呢。谁都有过青春期,谁都有过抗拒学习的心理,那个时候觉得除了学习什么都是美好的。当你真正过了那个阶段,发现学习才能最好的武装自己,有的人会继续前行,把浪费掉的补上;有的人则会真的掉队了,去做了再也不能学习的路。


    其实每个人都有自己的特长,当你发现自己的特长并发挥出来都算是成功的。并不是每个人都能考第一,不是每个人都要上清华北大才算是有出息。话说360行,行行出状元。每个人都要找准自己的定位,发挥了自己的优势,生活自然不会亏待你。


    不管什么年纪,每个人都在调整自己的心态和眼界,每个人都在时间的长河里醒悟自己,及时调整自己,让自己能有个更好的状态。不管是什么岗位,都要保持积极向上的心态,保持让自己不断进步才是最佳状态。每天都很美好,每天伸手都能触碰到阳光,人生需要奋斗。


     图片1.jpg

    除了心态,还要有选择后的坚持,其实近几年智能化产品几乎都占领了大多市场,物联网正是火热,沉静下来,或许你也能找到自己的那一块发光发热的土地。


    就拿单片机来说,说难不难,说简单不简单,学精了真的可以有自己的傲娇的小领地可以去施展一下的。

    现在太多芯片厂商为了获取客户的依赖,做了很多底层的库函数,所以才会导致太多程序员要依附于他们的工具,依附于他们的库函数做产品,甚至连芯片手册都没碰过,觉得我能实现就好了啊,碰到问题百度好了呀。产品到了交付期,问题还很多,这个时候你焦急了没有?话说真的太多单片机程序员碰到过的。大环境所致,很少有人能静下来心来去研究单片机到底是怎么启动的?到底是怎么工作的?结构是怎么样的?只有碰到问题百感交集时才会觉得其实自己真的不懂单片机,只是会拷贝,会改动。真正从头到尾做过一个产品吗?从底层启动到寄存器配置到上层应用逻辑?话说真的绝大多数程序员没有做过的。


    那么到最后是不是发现自己其实什么长进都没有,都在做修修补补的活了。跳槽是不是成了奢望了,想有跳槽的资本就要去做别人不会的,别人没做过的。比如单片机,很多人说我会啊,做项目做产品,可说到一些基本的单片机操作又慌乱了。


    如果你尚且有些梦想,如果你是在做单片机软件程序工作,请一定要去把它的原理搞懂,从底层一步一步去实现一下,工程都是从小到大的,当你碰到很多困难还继续前行了,那等待你的肯定是更多的机会。你付出了多少的汗水都会有多少的收获等着你的。只要努力了坚持了,那么看到的风景都是不一样的。加油吧打工人,我们都会更好的~


    图片2.jpg

    收藏 0 回复 0 浏览 72
  • MDK中Buil/ReBuild背后你不知道的故事

    在程序开发过程中,大家都会去点击编译按钮,直接开始仿真调试,基本上不怎么关注编译和链接的过程,因为我们使用的工具一般都是厂家做好的集成开发环境(IDE),比如MDK、IAR等。IDE通常将编译和链接合并到一起,虽然 IDE 提供的默认配置、编译和链接参数对于大部分应用程序来说已经足够使用了,但是作为学习,我们可以弄清楚从源代码生成可执行文件的原理。


        事实上,从源代码生成可执行文件可以分为四个步骤,分别是预处理(Preprocessing)、编译(Compilation)、汇编(Assembly)和链接(Linking)。下图是生成可执行文件的过程:

    1.jpg     

    预处理(Preprocessing)过程主要是处理程序中以#开头的命令,比如 #include、#define等。预处理的规则一般如下:

    1.将程序中所有的#define宏定义进行替换。

    2.处理程序中所有条件编译命令,比如 #if、#ifdef、#elif、#else、#endif 等。

    3.处理#include命令,会将被包含的头文件的内容插入到该预处理命令所在的位置,需要注意的是,这个过程是递归进行的,也就是说被包含的头文件中还可能会包含其他的头文件。

    4.删除程序中的注释。

    5.添加行号和文件名标识,便于在调试和出错时给出具体的代码位置。

    6.保留程序中的#pragma命令,因为编译器需要使用它们。


         预处理的结果是生成.i文件。.i文件也包含C语言代码的源文件,只不过所有的宏已经被展开,所有包含的文件已经被插入到当前文件中。当你无法判断宏定义是否正确,或者文件包含是否有效时,可以查看.i文件来确定问题。


        编译(Compilation)就是把预处理完的文件进行一些列的词法分析、语法分析、语义分析以及优化后生成相应的汇编代码文件(.txt文件)。编译是整个程序构建的核心部分,也是最复杂的部分之一,涉及到的算法较多。


    在MDK中可以按照以下步骤生产预处理文件和编译文件。勾选之后,再重新Build或者ReBuild就可以了。


             2.jpg


    汇编(Assembly)的过程就是将上一步生成的汇编指令转换成可以执行的机器指令。汇编过程相对于编译来说比较简单,只是根据汇编语句和机器指令的对照表翻译就可以了。汇编的结果是产生目标文件,即为.o文件。


    目标文件已经是二进制文件,与可执行文件的形式类似,只是有些函数和全局变量都是分散的,地址还没有找到,程序不能执行。链接(Linking)的作用就是找到这些目标地址,将所有的目标文件组织成一个可以执行的二进制文件。


       以上就是你点击了MDK中的Buil/ReBuild之后,被雪藏的背后的过程,你清楚了吗?

    收藏 0 回复 0 浏览 69
  • USB令牌包

    上一篇文章我们介绍了数据包的结构以及传输过程,提到了令牌、数据、握手、特殊等等专业的名词,后面的文章我们来一个一个详细介绍一下他们,今天我们先来介绍令牌包。

    令牌包用来启动一次USB传输。因为USB是主从结构的拓扑结构,所以所有的数据传输都是由主机发起的,设备只能被动地接听数据(唯一的例外是支持远程唤醒的设备能够主动改变总线的状态让集线器感知到设备的唤醒信号,但是这个过程并不传送数据,只是改变一下总线的状态)。这就需要主机发送一个令牌来通知哪个设备进行响应,如何响应。

    令牌包有4,分别为输出(OUT)、输入(In)、建立(SETUP)和帧起始(sOF Start Of Frame).

    >输出令牌包用来通知设备将要输出一个数据包。

    >输入令牌包用来通知设备返回一个数据包。

    >建立令牌包只用在控制传输中,它跟输出令牌包的作用一样,也是通知设备将要输出一个数据包,两者的区别在于: SETUP令牌包后只使用DATA0数据包,且只能发到设备的控制端点,并且设备必须要接收,OUT令牌包没有这些限制。

    >帧起始包在每帧(或微)开始时发送,它以广播的形式发送,所有USB全速设备和高速设备都可以接收到SOF包。USB全速设备每毫秒产生一个帧,而高速设备每125s产生一个微帧USB主机会对当前帧号进行计数,在每次帧开始时(或者微帧开始时,每毫秒有8个微帧,8个微帧的帧号是一样的,即相同的SOF)通过SOF包发送帧号。SOF中的帧号是11位的。在4个令牌包中,只有SOF令牌包之后不跟随数据传输,其他的都有数据传输图1.9.2SOF令牌包的结构。

    每个令牌包,最后都有一个CRC5的校验,它只校验PID之后的数据,不包括PID本身,因为PID本身已经有4个取反的位进行校验了。

    image.png

    1  SOF令牌包的结构图

    1.9.3OUTINSETUP令牌包的结构。它们具有同样的结构:同步域、包标识域、地址域、端点域、CRC5校验域和包结束。其中,地址域是要访问的设备的地址,端点域是要访问的端点号(还记得前面说过的教学楼模型吗?回忆一下地址和端点的概念);CRC5校验只计算PID之后的地址域和端点域,而不包括PID。前面说过,数据在总线上传输时,每个域的LSB在前,请记住这一点。例如,7位地址在总线上传输的先后就是A0A1A2A3A4A5A6

    image.png

    2  OUT IN SETUP令牌包结构图

    上面就是令牌包的全部介绍了,大家对令牌包有一个认识了吗?


    收藏 0 回复 0 浏览 69
  • C语言与汇编混合工程

    大家好!我是张飞实战电子蔡琰老师,今天给大家分享C语言与汇编混合工程。

    除了汇编语言工程和C语言工程,许多嵌入式工程既包含C语言又包含汇编语言。由于Keil MDK的默认启动代码是用汇编编写的,但是又是独立的一个启动代码是汇编实现,一般其他程序都是C语言实现。

    我们一起来看下混合语言工程中,就比如在汇编程序中调用C函数,或者在C语言代码中调用汇编函数需要注意什么,稍不留意结果就可能是无法预测的。比如程序在一种版本的编译器下可以正常工作,而在另外的版本下,或者更换编译器后,工程可能会由于寄存器的使用冲突而停止工作。

    1、在汇编中调用C函数

    当在汇编文件中调用C函数的时候,需要注意一下方面:

    ①寄存器R0R3R12以及LR可能会被更改,如果这些寄存器中的数据之后还要使用,就需要将它们保存到栈上。

    SP的值应该是双字对齐的

    ③需要确保输入参数存储在正确的寄存器中(比如简单例子,使用R0~R3

    ④返回值(假定为32位或更小)一般存在R0

    举个例子:如果有一个将四个值相加的函数:

    int my_add(int x1,int x2,int x3,int x4)

    {
    return (x1+x2+x3+x4);

    }

    Keil MDK中,可以使用以下的代码在汇编中调用C函数:

    MOVS  R0,#1    ;第一个参数(x1

    MOVS  R1,#2    ;第二个参数(x2

    MOVS  R2,#3    ;第三个参数(x3

    MOVS  R3,#4    ;第四个参数(x4

    IMPORT my_add

    BL     my_add   ;调用“my_add”函数,结果保存在R0

    如果汇编代码是按照C文件中的嵌入式汇编编写的,应该使用_CPP关键字代替IMPORT关键字来引入地址符号。

    _CPP的用法如下:

    上例程中:

    IMPORT my_add

    BL     my_add   ;调用“my_add”函数,结果保存在R0

    改为:

    BL    _CPP(my_add)  ;调用“my_add”函数,结果保存在R0

    Keil  MDK中,_CPP关键字用于访问CC++编译时的常量表达式,而对于其他工具链,情况可能就有所不同了。

    2、C代码中调用汇编函数

    如果要从C代码中调用汇编函数,在实现汇编函数时,需要注意一下几点:

    ①若改变了寄存器R4R11里的任何数值,需要将原始数值保存到栈中,并且在返回到C代码以前恢复原始值。

    ②若要在汇编函数中调用另一个函数,需要将LR的值保存在栈中,并且利用它执行返回操作。

    ③函数返回值一般存在R0

    举个例子:如果一个实现4个数相加的汇编函数:

    EXPORT   my_add

    my_add FUNCTION

    ADDS  R0,R0,R1

    ADDS  R0,R0,R2

    ADDS  R0,R0,R3

    BX   LR    ;返回值在R0

    ENDFUNC

    C代码中,需要将函数声明为:

    extern  int my_add(int x1,int x2,int x3,int x4);

    int y;

    ……

    y= my_add(1,2,3,4);//调用my_add函数

    如果汇编代码需要访问C代码中的一些变量,也可以使用IMPORT关键字。

    大多数情况下,可能只需要一到两个简单的汇编函数,所以就想将这些汇编代码嵌入C代码的文件中。多数开发工具都有一种被称作内联汇编的特性,而ARM工具链则采用了另外一种特性“嵌入汇编”。

    通过嵌入汇编,我们可以在C文件中实现汇编函数。例如,将4个参数相加的函数可以如下写法:

    _asm int my_add(int x1,int x2,int x3,int x4)

    {

    ADDS  R0,R0,R1

    ADDS  R0,R0,R2

    ADDS  R0,R0,R3

    BX    LR  ;返回值在R0

    }

    可以在C代码中像普通C函数一样调用这个函数:

    y = my_add(1,2,3,4);

    嵌入汇编允许你在异常处理中定位栈帧,这也是嵌入汇编的一个优势。

     


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