您还需要设置程序才能以裸机方式处理raspberry pi 3查看我以前的指导,以了解如何为使用pi裸机设置环境
此项目从开始到结束大概需要3-4个小时。
好我们开始吧!!!!
要构建此模块,我们需要一行6个LED分别连接到GPIO 20-25我们还需要一个连接到GPIO 27的。该指示灯将向我们指示是否已按下按钮最后,我们需要连接按钮按钮嘚一侧将连接到3.3v,另一侧连接到下拉引脚我们将使用GPIO 17连接到按钮。 GPIO 17将成为我们的输入引脚 GPIO 17连接到一个10k欧姆的电阻,该电阻连接到地(GND)我们这样做是为了确保GPIO 17始终设置为低电平。如果不是则该引脚有可能在高点和低点之间放弃,从而给我们带来随机的结果为了避免这种情况,我们可以使用电阻较大的电阻将引脚下拉至0v
在面包板上设置电路是一个简单的过程。请遵循上面的电路图将引线的短边連接到GND,将长边连接到220欧姆电阻对其他5个不同的led重复此操作。这样一来您总共应该连接六个LED。从一端开始将第一个LED的正极连接到GPIO 20,嘫后将下一个引脚连接到GPIO 21依此类推。..最后一个LED应该连接到GPIO 25
对于指示灯led连接led的短端连接到GND,长端连接到220 ohm电阻然后将电阻连接到GPIO 17。
将按鈕连接到试验板我使用的按钮上有四个连接。我们将只使用底部的两个将一端连接到正极轨,另一端连接到10k欧姆电阻将GPIO 17连接到10k电阻。按下按钮时它将GPIO 17连接至将引脚设置为高电平的正极。
将3.3v引脚连接至正极并将GND引脚连接至负极。
最后将正轨和负轨连接在一起以便鈳以使用两侧。
编码部分是从上一个闪烁的项目中已经学到的东西建立的
该项目中的两个新事物是,我们设置了堆栈框架的使用方式鉯便我们可以模拟高级功能,并进行设置使用系统等待特定毫秒数的等待函数
堆栈是一种常见的编程结构。它实际上是一个地址序列鈳用于临时内容。堆栈具有两个基本功能
您可以将项目推入堆栈顶部
也可以将项目从堆栈顶部弹出
可以按不同的版本设置堆栈,但是对於该项目我们将坚持默认配置。当您将某些东西推入堆栈时它会放在顶部。当下一件物品被推入堆栈时新物品将成为顶部,而旧物品将位于其下方希望您以前曾经使用过堆栈,如果没有的话可以在网上找到更多更深入的解释。幸运的是有一个push和pop指令,因此使用堆栈很容易组装
我们将要探索的第二件事是访问系统器,这样我们可以将程序延迟一定的时间
第4步:代码:堆栈/堆栈框架
设置要使用嘚堆栈就像一行代码一样简单。由于链接器的设置方式(kernel.ld)我们在编译时将所有代码插入0x8000之后。因此我们需要将此值移到sp中。
将其添加到代码顶部并使用堆栈应该没问题
现在进入堆栈框架。堆栈框架基本上是当我们预留堆栈的一部分以用于过程调用时这使我们能够實现高级语言(如和C ++)使用的功能。这些语言使用堆栈来跟踪函数调用我们可以在汇编中做同样的事情。
要将函数调用模拟为高级语言我们将保留寄存器我们想通过将它们放置在堆栈上来使用,然后如果需要将其用于变量我们还可以在堆栈中预留本地内存。在函数末尾我们必须破坏堆栈帧并将堆栈重置为以前的状态。
通常如果函数需要返回任何内容,则应将其放在r0中/p》
如果函数接受参数,则应將其放在函数分支的前面
我们通过设置堆栈框架开始该功能。
ldr[r7,#8] @第一个参数与r7的偏移量为#8
然后我们通过清理堆栈框架来结束堆栈框架
此过程使我们无需更改任何寄存器即可调用函数。它还允许在函数内调用函数因为堆栈框架将始终保留lr,因此允许进行多个級别的函数调用
步骤5:代码:系统计时器
要使用系统计时器设置延迟,我将其编写在一个单独的文件中因此也可以在以后的项目中使鼡。为此我们基本上需要访问计时器并获取初始时间戳。一旦有了我们将再次访问时间戳。我们将从最初的时间戳中减去第二个时间戳并将其与所需的值进行比较。
算法非常简单最困难的部分是访问正确的寄存器。
计时器的lo字的偏移量为0x4
计时器的高位字的偏移量为0x8
嘗试编写自己的等待函数!如果需要参考请附上我的代码。
步骤6:代码:获取输入
对于该项目我使用了GPLEV0寄存器。本质上它保持引脚0-31嘚状态。我们正在使用GPIO 17作为输入要将此引脚设置为输入,我们必须访问FSEL1寄存器并清除GPIO 17专用的三位
我们还需要将位20-27设置为输出。
由于我們使用的是输出我们还需要访问ET0寄存器以打开引脚,而GPCLR0寄存器以关闭引脚
由于等待功能以微秒为单位因此您可以使用以下几个值
上面嘚代码设置了我们的代码,因此它可以正常运行
下一步我设置基址的地址和我们将要使用的偏移量。
在这里我设置了一些以后将要使鼡的有用符号。
出于可读性考虑我为寄存器的目的设置了一些符号。
要将此引脚设置为输入首先要获得适当的偏移,然后再加载掩码;最后我将掩码写回到寄存器中。
我做的和输入一样只是使用了不同的偏移量和掩码。
接下来我开始主程序循环。我首先描述我要程序执行的操作
我以一个小的等待值开始循环。
在这里我正在检查引脚17的状态,该函数将返回r0中指定引脚的状态我的所有功能都将茬末尾列出。
我检查返回值然后跳转到一个功能,该功能可以打开指示灯并循环或关闭指示灯
如果按下该按钮它将GPIO17连接到3.3v,因此将其設置为高电平因此,如果按下按钮输入功能将返回1,从而指示器打开并且LED的环路上升从GPIO20到GPIO 26接通。
基本上就是这样接下来,我将介紹在input_loop中调用的函数
步骤7:代码:函数定义
首先,我们有get输入
我的函数有一个参数即GPIO引脚的编号。该功能使用引脚号创建一个掩码来测試GPLEV0中的位 tst执行逻辑“与”并设置标志。如果and返回true则未设置零标志。
接下来我有两个函数可以打开指示器并关闭指示灯。当指示灯打開时该功能将分支并通过GPIO引脚循环。当指示灯熄灭时该功能将通过GPIO引脚分支和向下循环。
前两个功能设置向上或向下循环功能他们呮是确保在循环开始之前将计数器设置为正确的数字。 loop_up和loop_down函数在本质上彼此相同一个循环通过以GPIO 20开头并以GPIO 26结尾的引脚,然后循环通过以GPIO 26開头并以GPIO 20结尾的引脚
循环位置i或j移入r0和然后调用turn_on函数。这会根据传递到r0的数字打开一个引脚然后,循环将等待八分之一秒然后再关閉引脚并递增或递减计数器。
步骤8:将它们放在一起
现在,您已经编写了所有代码文件您需要生成一个二进制kernel.img。我设置了一个简单的makefile将其吐出来。只需下载它然后将第4行的代码变量更改为文件名即可。
如果您无法使代码正常工作请下载并编译我的代码,然后将kernel.img放箌pi上如果可以,那么如果不返回电路步骤并尝试重建电路则代码可能存在问题。
试试把火线和零线对换一下
你对这个回答的评价是
试试把火线和零线对换一下
零线有电压造成的,可能零线接触不良如果把零线接到地线上,马上就好
你对这个回答的评价是?