完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
很多人肯定很疑惑,在嵌入式开发中,为什么写c代码,就能够控制硬件。这一切是怎么发生的了,下面我就给大家解剖一下,软件是怎么控制硬件的。
我们从控制8个led为例来说明: 从最简单的开始,如果使用硬件,控制8个led,最简单的方式是什么:直接接上开关。就是以下的图。通过开关控制led管脚输出不同的电平,就能控制led了。但是这个方法很不灵活,我们要手动的去拨动开关,才能改变led状态。 我们将上面电路改一下,把开关的地方换成寄存器,并加一些额外的电路,这样就可以通过使能信号和信号值改变led值输出不同电平,间接的控制led了。而使能信号和信号值我们是可以通过外部给的,就比开关要灵活一些了。 既然,上面有寄存器,我们可以给这个寄存器定义一个地址,当然这个地址目前是可以随意定义的。假设为0x77777777。你可能会有疑问,为什么要给寄存器定义地址了?而且定义的地址为什么是32位了,这个先不着急,听我慢慢道来。 我们继续在前面加电路 这里,多了一个前级电路,前级电路提供两个信号,一个地址,一个数据。在地址信号通路上,有一个电路模块,判断地址是不是0x77777777,是的话,使能信号为1,这样数据不就直接传递给寄存器了。不是的话,使能信号为0。寄存器的输出不变。这样,通过地址和数据就能改变led了。 这里0x77777777是不是很熟悉,这不就是之前定义的寄存器A的地址吗?原来,地址就是用来判断是否产生使能信号的,使能才能使数据能够输入到寄存器中。 到了这里,是不是对软件控制硬件有些眉目了。别着急,我们继续往下走。 既然前级电路只需要提供地址和数据,并且地址是0x77777777,就可以控制寄存器A的值了,而控制了寄存器A,就控制led。那么我们将前级电路换成一个32位CPU。 我们知道,CPU是可以产生3种总线信号的,一种地址总线,一种数据总线,一种控制总线。控制总线我们这里用不到。将地址总线接到地址线上,将数据总线接到数据线上。就是以下的电路: 如果我们让CPU产生地址为0x77777777,然后发出想要写入寄存器A的数据B,那么数据B不就被写入到寄存器A中,这样,不就控制led了。这里知道为什么地址要32位的把,因为CPU是32位的,地址就是32位宽的。之所以定义32位的地址,目的是为了和CPU的地址总线32位宽兼容。 到这里,是不是有豁然开朗的感觉了。我们再继续。 我们知道CPU是要取机器码然后执行的。如果刚好某条机器码,能让地址总线上产生0x77777777,数据总线上产生数据B。那么结果,数据B不就被写入到寄存器A中了。假设CPU是32位risc的CPU,机器码就是32位。那么该机器码应该是如下: 1001 0000 1110 0000 1011 1010 1111 0010(假设) 既然这是一条机器码,那么就应该有一个汇编指令与之对应,假设是 str r0, r1 我们预先将地址0x77777777写入到r0中,数据B写入到r1中,那么上面一条语句执行后,不就将数据B写入到寄存器A中了,不就控制led了。这样不就实现了软件控制了硬件了。既然汇编代码可以控制硬件了,那么高级语言同样也是控制硬件的,只要编译后的汇编代码是以上代码就行了。 整体控制硬件的代码就是 ldr r0, = 0x77777777 ldr r1, =B str [r0], r1 对应的C代码就是 (*(volatile unsigned long *)0x77777777) = B; 使用指针操作,往0x77777777地址的寄存器写入数据B,加入volatile关键字,是防止编译器对操作进行优化。 通过上面的过程,是不是也可以理解,为什么在嵌入式底层驱动开发中,基本都是用C语言,而不用其他高级语言,比如JAVA等。因为这些高级语言没有指针,你就不能控制寄存器,不能控制寄存器了,你当然就控制不了硬件了。C++也很少用,因为底层驱动开发需要高效率代码,不能太复杂,而C++在这方面,比不过C语言。 以上是写入的过程了,如果想要知道led的状态呢?通过读取寄存器A的值,不就知道led的状态了。原理是一样的。只不过数据线要变成两根,一个是负责写,一根负责读。电路图如下: 因为只考虑了一个寄存器,当不选中寄存器A时,读取的数据为全0。 通过,上面的讲述,对软件控制硬件有没有了解一些了。软件控制硬件,本质上,就是通过写代码去修改或读取硬件对应的寄存器的值。这样,就相当于间接的控制了硬件。而硬件的寄存器对于一个处理器来说,都是固定的,都预先定义好了地址。所以在看ARM的数据手册中,可以看到很多寄存器的地址。这些地址的作用,也就是能够让你在写程序的时候,能够正确的往这些寄存器里面写入或读取正确的值,从而控制硬件。 CPU对外看到的都是寄存器,所以硬件设计的时候,就要对硬件的功能设置几个寄存器,然后对这几个寄存器分别定义几个地址,这样CPU才可以去控制这几个寄存器,也就能控制硬件了。定义的寄存器地址位宽是和CPU的地址线位宽是有关系的,如果是一个8位的CPU,也就是经典的C51,地址的宽度就是8位,所以你可以在头文件reg51.c中看到使用sfr定义的地址位宽是8位。在STM32中,CPU是32位的,所以地址的宽度就是32位的,所以你看到STM32数据手册中,寄存器的地址都是32位的,而且是4字节对齐的。 以上,CPU只是控制了一个硬件,led,但是我们知道,CPU是可以控制很多硬件的,那这又是怎么实现的了?这个就得谈谈片上互联总线了。 更多内容欢迎交流 qq:1064191232(李老师) 欢迎大家进入华南地区最大的单片机嵌入式学习群: 138054083。共同交流、学习。 |
|
相关推荐
|
|
只有小组成员才能发言,加入小组>>
「含关键代码」基于AM3352/AM3354/AM3359的Linux开发案例分享
4875 浏览 0 评论
87369 浏览 0 评论
【高手问答】如何做到精通linux技术?资深工程师带你突破难点
4697 浏览 2 评论
3582 浏览 2 评论
解读Linux :先从创建一个文件夹用来存放jdk压缩文件开始
2460 浏览 0 评论
1969浏览 3评论
这是i.mx6ull的关于usb的宏定义,能解释下这些宏定义的意思
1330浏览 1评论
1243浏览 1评论
求解:aarch64交叉编译工具已经安装成功,环境变量已经配置,怎么将系统架构切换为ARM的架构
1310浏览 0评论
电脑和虚拟机可以互ping,电脑和开发板也可以互ping,但是虚拟机和开发板ping不通是什么原因
1216浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-2 02:25 , Processed in 1.499906 second(s), Total 84, Slave 66 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号