发帖数

53

原创数

53

关注者

11

阅读数

9160

点赞数

1

黄忠

  • ​单片机C语言程序的存储区域解读


    C语言代码(文本文件)形成可执行程序(二进制文件),需要经过编译-汇编-链接三个阶段。编译过程把C语言文本文件生成汇编程序,汇编过程把汇编程序形成二进制机器代码,链接过程则将各个源文件生成的二进制机器代码文件组合成一个文件。

    C语言编写的程序经过编译-链接后,将形成一个统一文件,它由几个部分组成。在程序运行时又会产生其他几个部分,各个部分代表了不同的存储区域:

    1、代码段(CodeText

    代码段由程序中执行的机器代码组成。在C语言中,程序语句进行编译后,形成机器代码。在执行程序的过程中,CPU的程序计数器指向代码段的每一条机器代码,并由处理器依次运行。

    2、只读数据段(RO data

    只读数据段是程序使用的一些不会被更改的数据,使用这些数据的方式类似查表式的操作,由于这些变量不需要更改,因此只需要放置在只读存储器中即可。

    3、已初始化读写数据段(RW data

    已初始化数据是在程序中声明,并且具有初值的变量,这些变量需要占用存储器的空间,在程序执行时它们需要位于可读写的内存区域内,并具有初值,以供程序运行时读写。

    4、未初始化数据段(BSS

    未初始化数据是在程序中声明,但是没有初始化的变量,这些变量在程序运行之前不需要占用存储器的空间。

    5、堆(heap

    堆内存只在程序运行时出现,一般由程序员分配和释放。在具有操作系统的情况下,如果程序没有释放,操作系统可能在程序(例如一个进程)结束后回收内存。

    6、栈(stack

    栈内存只在程序运行时出现,在函数内部使用的变量、函数的参数以及返回值将使用栈空间,栈空间由编译器自动分配和释放。

    C语言目标文件的内存布局如下图:

    图片32.png

    代码段、只读数据段、读写数据段、未初始化数据段属于静态区域,而堆和栈属于动态区域。代码段、只读数据段和读写数据段将在连接之后产生,未初始化数据段将在程序初始化的时候开辟,而堆和栈将在程序的运行中分配和释放。

    C语言程序分为映像和运行时两种状态。在编译-链接后形成的映像中,将只包含代码段(Text)、只读数据段(RO Data)和读写数据段(RW Data)。在程序运行之前,将动态生成未初始化数据段(BSS),在程序的运行时还将动态形成堆(Heap)区域和栈(Stack)区域。

    一般来说,在静态的映像文件中,各个部分称之为节(Section),而在运行时的各个部分称之为段(Segment)。如果不详细区分,可以统称为段。

    每一个源文件生成的目标代码有了这些段的区分,那么每个段就能表示出源文件想要表达的信息和功能。下一篇我们一起深入分析下在这些段中是怎么体现的源码的信息的。


    收藏 1 回复 0 浏览 33
  • 51单片机DIY抽奖-技术分享(一)

       

    想着年底临近了一年一度的年会都开始陆续开始了,抽奖的方式算是样式很多了,我们在商场看到过那种转盘抽奖自己用力让它转起来然后停下来指针指向哪里就是奖项的结果了这种是常见的了再有就是我们年会抽奖箱更是常见的基本都是一个抽奖箱,里面放了跟发放到自己手里的号牌是一样的一组序号,抽到哪个对照就可以了,这样是最传统的了,我想着能做个DIY效果的抽奖器,不是好玩又实用吗?想到就来做,外形呢可以仿照商场那种转盘样式,两个按键就够了,开始和停止啊,然后就是数字显示了,想着先实现以下,就做了两位数码管的样式,DIY效果嘛,就选择了LED(主要还有便宜哦),这样其实占用单片机管脚还是多了,资料搜索和同事推荐,选择了好用还实惠的一款芯片(CH455G),太好用了,显示和按键只要一个I2C接口就够了,这款芯片简直解决了大问题,主要的管脚确定了,然后我想做个抽奖结束可以唱歌,可以通过蜂鸣器实现,写个谱子和调调就可以了,这个还是要下功夫来研究下的,对于我这个五音不全的人来说简直是难到不行啊,既然想做到有创意,我还是硬着头皮上的啊,不能太死板了吧,做小东西可以很好玩的。

       转盘效果我们知道是人为转起来,有转的效果,那我既然做这个,就可以显示数字快速轮训显示,然后周边做一圈不同颜色的LED快速轮转就可以了,那这样是不是光脑子想想都觉得好玩呢。

    既然大体的都想到了,最后就是根据需求来定单片机了,显示和按键需求最大的都解决了,我就可以选择一款管脚少的单片机了,我选择了下面这款:

    图片7.jpg

    下面是管脚图:

    图片8.jpg


       附件内我放了这款单片机的数据手册,有需要的可以自行下载啊,没准就是很适合你做项目的款呢。

       现在我们知道大部分产品都是用USB供电,那我这个小产品也选择用USB供电(要紧跟潮流啊),这款单片机好的一点是用串口下载和仿真,其实性价比还是很好的啊,之前我做过一款USBTTL,刚好这里用上了。

       到这里万事俱备了,那就开干了,先把选择好的芯片数据手册研读好,不能觉得简单就直接进入设计,每个芯片的规则不一样,还是要认真点好,不然做出板子又出问题不是更麻烦吗(费时费力还费钱不是)。芯片手册需要的部分很有必要反复确认,然后就开始我的设计之旅了,哇,想想成品都是开心的,接下来就是原理图设计和PCB画板了,原理图设计还要把控好一些电阻电容的部分,话不多说,我会持续分享我后面踩坑避坑的过程,如果有兴趣的就关注我这个产品的实现过程吧,过程坎坷又收货满满。如果有其他想法的可以跟我交流啊,下个DIY可能会更有思路了呢。


    附件资料领取:

    163272329500046e4.pdf


    收藏 0 回复 0 浏览 36
  • 51单片机DIY抽奖-技术分享(二)

    1 原理图设计

    前情提要:上一篇我介绍了我做这个小产品的想法和准备工作,其实很有动手的必要,有时候不要觉得简单就不做,每一个产品实现的过程都不是一帆风顺的,都会增加不同的经验,我是深有体会的。话不多说,只要能让大家想起来我的需求和想法就好了,现在就是实现过程了,先来做原理图设计了。

    看我的标题明确的说了DIY抽奖,所以对这个数码管显示数字部分我用的LED(红色---目的就是压降低),一圈旋转的灯就是黄绿蓝三色切换,一共用了18个。

    image.png

    我只做了两位显示,最大到99,有需要做三位以及四位都是可以添加的。我这里就是实现了两位的,主要功能实现了,其他都不问题了是吧。

    我选择了USB供电,USB供电进来我加了一个保险丝(9V/200mA),起到一个保护作用。

    因为我要实现的功能相对简单,主要靠编程实现效果,所以电路设计就比较容易实现了,但是还是需要想下用最少的资源实现最强的效果了。

    接下来看下单片机模块的实现,先看下我设计的电路图:

    image02.png

    选用了8脚单片机,电源端加了一个滤波电容,一个储能电容,这个没什么问题。然后就是一个蜂鸣器,我想当抽奖停止一次就通过蜂鸣器唱歌,然后有一个蜂鸣器端口,可以通过PWM输出不同的频率来实现歌曲的调子。这个还要研究下歌曲呢,谱子啥的,瞬间感觉自己都高能了。

    右边部分就是I2C接口了,连接的按键显示芯片的端口。下面两个是串口通讯口,这里是单片机下载程序用的。这几个端口的10R电阻是防震荡作用的。

    接下来我们看下按键显示模块的实现,先上图吧:

    image03.png

    图中可以很清晰的看出显示的段和位部分,这里的100R电阻是对LED限流用的,这个电阻可以根据实际情况调节的。I2C端口的4.7K电阻是接口需求,这个可以查阅相关I2C标准,我就不多说了。下面这两个电容是电源端的滤波电容和储能电容。按键由于是共阴设计,所以加一个电阻是限流作用了。这一部分就设计完成了,是不是还挺简单的。

    接下来就剩下的是蜂鸣器部分了,我选用的是无源压电式蜂鸣器,先上图看下设计思路吧:

    image04.png

    电源端的电容就是滤波电容和储能电容了,上面这个10R电阻就是限流作用了,因为选用的是压电式无源蜂鸣器,所以下面这个R15就是为蜂鸣器放电用的了,因为我是要给蜂鸣器PWM实现唱歌,所以BEEP就是单片机给出的相当于信号了,所以下面加了一个三极管,R16作用就是限流电阻了,R17就是对三极管结电容加速关断的作用了。这样蜂鸣器部分就设计完成了。

    对于抽奖DIY的原理图设计部分就这些,是不是看起来很简单呢。其实好玩的在后面呢,PCB设计像转盘一样的抽奖样式,程序实现效果。都要动一番心思的。我实现了这样的一个小产品,大家可以看下我的原理图部分有没有需要改进的地方呢?随时欢迎交流啊,或者有更好玩的产品一起探讨实现啊,每个都有每个的特点,都能学到不一样的知识点。如果你能在我这有所启发是最好了,分享和交流的过程就是成长的过程。后面我会陆续更新,下面一篇就是对PCB的实现了,感谢大家对我的持续关注,还希望能给出更多的意见和建议啊。



    收藏 0 回复 0 浏览 40
  • 51单片机DIY抽奖-技术分享(三)

    PCB设计

    前情提要:上一篇我介绍了我做这个小产品的原理图设计思路,通过对原理图部分的设计说明,大家可能觉得没什么东西,当你动手实现了整个过程,再回过头去看,其实收货还是比想象的多,每一次的历练都不是徒劳的,当你收获多个小产品的经验后,有一天你接手一个大项目就不会感觉束手无措,会感觉自己平时的经验都能用的上了,话不多说,下面就分享我的PCB设计过程,PCB设计首先就是定义板框,我这里想到抽奖的小产品,那么模样也不能差太多了吧,话说我从网上搜了下抽奖转盘图片,常规我们看到的都是类似下面这种吧?

    image.png


    那设计开始吧,板框设计,由于这是一个实验品,不需要做成像平时我们见到的那么大吧,所以我只需要自定义一个能把所有元器件放下的就可以了。


    image02.png


    板框实现了,就是把原理图导入到PCB了,接下来就是实现PCB的设计实现过程了。在这里呢,我主要分享我的实现过程,还有过程中我碰到的一些小问题,我会给大家分享出来,做个提示,如果碰到同样问题,那就可以少走弯路了。

    具体实现细节大家可以持续关注下,后续我会把实现的过程视频分享给大家,互相学习嘛,有需要借鉴的就可以少走弯路,有我需要改进的欢迎大家来跟我交流哈。

    那继续看下PCB设计前应该做的事情吧,首先就是规则设置了,无规矩不成方圆,这个也同理了,所以在布局前先把规则设置好,后面所有的事情做起来就只要守规矩就好了,否则会做出警示了。那么设置规则有没有讲究呢,就请跟着我的设置来看下我常规的经验,这个只是我个人常规使用,也可以根据自己实际情况调整的。



    接下来一起看下规则设置:

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

    image03.pngimage04.png


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

    image05.png


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

    image06.png


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

    image07.png


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

    主要的规则设置就上面这些了,具体的可以在实际过程中根据需求再设置就好了,规则设置好方便布局和走线的规范性,做事还是规范点好,不然真的好麻烦啊。

    规则设置好了,就可以开始布局了,布局的讲究除了看起来合理,产品出来用起来顺手,还要考虑走线等等,真的不是随便摆摆就好了,我只是分享我的思路,还是那句,方法很多,可以借鉴感觉别人优势的地方。

    既然像转盘转起来的感觉,我做的是个电子产品,有转起来的感觉就可以了,那么就把这个圆盘做了一圈的LED,然后通过程序来实现循环点亮,逐渐加快速度,同时把两位数码管(LED组成)数据循环显示(速度快无法分辨当前实际数值),两位数码管就放在上面正中间了。

    image08.png


    由于是USB供电,所以要在端口处(最下面),既然上面显示,那么USB供电上面就可以放置两个按键,一个开始,一个停止。是不是简单多了。也可以通过按键的长按或者组合实现调整数据等操作,所以这里两个按键就够用了。

    image09.png


    因为这个产品元器件不多,所以除了蜂鸣器我放在底层,其他都放在顶层,这样对于走线也方便。

    针对模块化,我们先来看下,

    第一部分就是单片机部分了,单片机连接了数码管驱动芯片以及蜂鸣器部分。

    那么先把单片机涉及的部分放在中间,模块化布局可以把原理图放置在平行界面,当选中模块后,对应的PCB模块部分就可以选中来组合了,下图中所示:

    image10.png


    那么针对前面说到的数码管显示放在上面,按键放在下面,自然就是数码管驱动芯片放在显示和按键中间合理了吧,又有和单片机的连接,所以看下图:

    image11.png


    那么剩下的就是蜂鸣器部分了,一起看下显然就是放在单片机左侧了,然而我说了选择放在底层,所以合理放置就可以了。

    image12.png

    布局就这样实现了,是不是挺简单的,接下来就是走线了,走线根据实际情况要不断的调整,顶层无法走了需要打过孔来走底层。这是最繁琐的一个过程了,也是考验细致和耐心的过程。具体走线细节可以关注后面的视频,这个看的过程中如果感兴趣还是需要实践下的,不实际操作看了真的没什么效果。

    那么走线就不具体说了,走线完成还有敷铜,DRC检测,出图等很多流程,这里就不详细说了,主要在于设计过程的分享,还有注意事项,最后还有一项需要提醒的是泪滴,这个是对焊接时焊盘连接线的保护,还是要注意下的。

    最终效果图看下吧:

    image13.png


    对于抽奖DIY的PCB设计部分就这些,是不是看起来也不难呢。其实实现起来真的没你想的那么简单,每个实践过程都会有很大收获的,后续会分享我的程序实现过程以及效果。都会经历不同的坎坷啊。当你遇到不同的问题的时候慢慢解决了才是经验的积累过程。这个抽奖DIY小产品PCB设计就完成了,大家可以看下我的实现有没有需要改进的地方呢?随时欢迎交流啊,或者有更好玩的产品一起探讨实现啊,每个都有每个的特点,都能学到不一样的知识点。如果你能在我这有所启发是最好了,分享和交流的过程就是成长的过程。后面我会陆续更新,下面一篇就是对程序的实现了,感谢大家对我的持续关注,还希望能给出更多的意见和建议啊。


    收藏 0 回复 0 浏览 58
  • 51单片机DIY抽奖-技术分享(四)

    软件设计

    延续前篇,继续分享我的DIY抽奖设计之软件部分,上一篇我介绍了我做这个小产品的PCB设计过程,然后现在就到了实物板调试的阶段了,只有把相应的程序实现了,这个产品才能真正实现自己的价值,实现的过程可能会比较曲折,但没有过程哪来的结果,没有实践哪来的经验,话说真的一点没错吧。

    这里我只能描述实现过程和碰到的一些小问题,具体实现过程以及程序源码细节我也会陆续更新出视频,感兴趣的可以关注下~自己实践下更好了。

    我们要完成一个程序设计的话需要先设计算法,然后再实现算法,实现就要用到计算机语言来表述了,不然单片机也不认不是。这里我说一个概念就是结构化程序的设计强调程序设计风格和程序结构的规范化,那么就提倡用清晰的结构,我们不管是新手还是老手,规范化还是很有必要的,对自己程序的逻辑关系的考验,或者是对阅读者都是很好的,以至于到后期的调试或者扩展和修改算法都会变得容易了。

    我要实现抽奖功能,首先不能只有大的想法就够了,既然要实现就要把每个细节的逻辑关系都要落实才行,否则就不会出现你想要的结果。

    那么接下来我从大的方向到细化的过程以及设计要点都分享下哈~

    1、程序主要实现的功能:

    image01.pngimage02.png


    简单清晰,主要的调试点在内部实现的逻辑关系上。后续精彩着呢,待更完~


    2、顺序往下吧,对于单片机设计,首先就是要初始化,对IO口和定时器等进行配置才能使得单片机正常工作,每款单片机对外设的配置都是不一样的,那么就要研读数据手册了,这是避不开的。先来看下我的初始化部分。

    image03.png


    既然前面提到了分模块,从初始化到实际处理都要分模块进行,这样思路清晰。比如第一个函数是对单片机的初始化,主要就是I2C通信的IO口部分,蜂鸣器的IO口部分,定时器的部分,那么初始化就是直接对外设寄存器的配置;后面的模块主要就是对当前模块的全局变量的初值配置了。全局变量我一般都是用结构体来实现,每个模块定义一个结构体,名称和用法一目了然,想扩展也方便。


    3、初始化了,只能说单片机可以用了,具体还要看需要的应用模块,这样单片机才能顺利完成你需要的使命。继续看下抽奖大的模块,就是显示和按键了,再有一个就是蜂鸣器模块。

    有了大的模块就可以细分,把具体功能先确定好,再去实现就方便多了,我觉得做程序一定要把模块做好,然后模块间的全局变量尽量通过结构体来实现,这样结构清晰,逻辑性好。

    这是我个人经验,当能把习惯养好的时候,一定不要随意,否则浪费时间不说,程序结果也会不稳定。



    4、那这里我就分享下我的小DIY的模块的逻辑实现,先说显示部分吧,首先我做的这个有两个按键,一个开始,一个停止。按键开始后我会把对应显示模式的变量配置好,对应不同的模式再去进行处理。

    image04.png


    接下来细化了,就是在不同模式下做些什么,先来看下我的流程图,然后我再针对设计细节把想法说一下。

    image05.png


    对于获取当前获奖者,我的处理方法是通过指针获取当前序号对应数组的值,同时把当前值从数组中删除,直到数组中数据全部被抽完为止。

    流水灯以及显示数值由慢变快是怎么做的呢,主要就是定义一个全局变量,作为时间参数配置一个大一点的初始值,定时时间到时间参数减值,直到减到一个很小的值,这就是一个渐变的过程。

    image06.png


    具体的实现过程可以关注我的视频,所有代码都会分享到。

    5、那么按键模块的话就是扫描和处理了,按键部分我当时选取数码管驱动芯片就很明确了,具体可以看下我第一篇给大家推荐的那款芯片,很实用啊。那么对于扫描不需要做过多的处理,只需要直接读取就可以了,这个就没什么好说的了。只是I2C相关的读写函数要仔细研读手册了。

    接下来看下我的处理,也是状态机模式,整个网络之间的关系通过结构体全局变量实现。逻辑关系清晰。

    image07.pngimage08.png

        框架出来了,就是具体逻辑关系了,有短按和长按,这个长按只针对停止键,短按就是常规抽奖模式的开始和停止了,那么停止键在短按情况下,要判断当前模式是转盘转动模式还是设置模式,如果是转动模式就是进入停止模式(显示当前号码,蜂鸣器唱歌),如果是设置模式(配置抽奖号码总数),号码加1;启动键短按的处理,也是要判断当前模式是停止模式还是设置模式,如果是停止模式则进入转动模式,如果是设置模式,号码减1;还有一个长按停止键了,当前模式是停止模式,长按则进入设置模式,如果当前是设置模式那么就进入停止模式。长按的处理就是进入和退出设置模式。按键处理就这些需要实现的功能。

    最后就是一个蜂鸣器的模块处理,由于蜂鸣器我做了唱歌的功能,涉及到频率问题,所以我放在中断中完成(也是经过多次调试)。蜂鸣器唱歌要分析谱子,调调,真的有点音乐人的感觉了,通过计算低音,中音,高音的频率先计算配置好,然后要有曲子的分析,查表配置周期(可以用定时器的时钟分频模式)实现唱歌。这里学问太深,有兴趣的可以深挖一下,还是通过蜂鸣器模式来进入相应的状态,比如一声响,两声响,唱歌。这个都是可以自由分配的。

       到这里抽奖程序设计主体思路就这样实现了,整个DIY的产品就完成了。下面就是成品啦。

    image09.png

           纵观看下,功能不难,其实实现起来真的没你想的那么简单,逻辑关系要确定好,手册要研读好。有兴趣的话可以自己动手实践下,每个实践过程都会有很大收获的,后续会分享我的程序实现的视频过程,会更细致些。每个项目不论大小都会经历不同的坎坷啊。当你遇到不同的问题的时候慢慢解决了才是经验的积累过程。这个抽奖DIY小产品就完成了,大家可以看下我的实现有没有需要改进的地方呢?随时欢迎交流啊,或者有更好玩的产品一起探讨实现啊,每个都有每个的特点,都能学到不一样的知识点。后面我会陆续做出更多的小产品,每一个都会有侧重点,或者可以给我启发或建议一起完成你的想法啊,感谢大家对我的持续关注,还希望能给出更多的意见和建议















    收藏 0 回复 0 浏览 99
×
黄忠