完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
2个回答
|
|
很多人肯定很疑惑,在嵌入式开发中,为什么写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是可以控制很多硬件的,那这又是怎么实现的了?这个就得谈谈片上互联总线了。 |
|
|
|
只有小组成员才能发言,加入小组>>
695 浏览 0 评论
1106 浏览 1 评论
2473 浏览 5 评论
2808 浏览 9 评论
移植了freeRTOS到STMf103之后显示没有定义的原因?
2646 浏览 6 评论
使用eim外接fpga可是端口一点反应都没有有没有大哥指点一下啊
655浏览 9评论
651浏览 7评论
请教大神怎样去解决iMX6Q在linux3.0.35内核上做AP失败的问题呢
783浏览 6评论
630浏览 5评论
670浏览 5评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 19:51 , Processed in 1.130120 second(s), Total 82, Slave 63 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号