使用 Python 和 C 设置和编程 Raspberry Pi






4.80/5 (16投票s)
引言
本文旨在帮助初学者入门树莓派的开发环境搭建以及使用 Python 和 C 语言进行编程。
今天我们将涵盖以下关于树莓派、Python 和 C 的内容。
编程树莓派
文件管理器
网页浏览器
文本编辑器
Shell
命令行
提示与技巧
文件与文件系统
树莓派与 Python
Python 的 Hello World
方法 1
方法二
更多的 Python 知识
Python 中的函数
关键词
条件关键词
循环关键词
内置函数关键词
类、模块相关关键词
错误处理关键词
设置编程环境
安装 VIM
安装 Python
安装 RPi.GPIO
调试最佳实践
C 语言编程
安装 BCM2835 – C
安装 Wiring Pi
C 语言的光感应程序
背景
之前有一篇关于树莓派本身设置的文章,对树莓派的概述有助于您更好地开始本文的学习。以下是链接。
Raspberry Pi 入门,使用 Raspbian OS
要开始设置和运行您的树莓派,请参阅以下关于首次设置树莓派的文章。
您的树莓派设置完成后,并且已启动到 LXDE(我们 Raspian 的轻量级 GUI)之后。
让我们快速浏览一下操作系统中我们将用于编程设备的一些重要内容。
文件管理器
这是一个文件浏览器/管理器,相当于 Windows 操作系统上的 Windows 资源管理器。文件管理器位于“附件”菜单下,可以帮助您在不使用命令行的情况下移动文件。文件管理器允许我们使用图标和文件夹浏览文件系统,与其他具有 GUI 的操作系统类似。
网页浏览器
默认的网页浏览器是 Midori,它设计轻巧,适用于处理能力有限的小型处理器。像 Chrome、IE、Safari 这样的常用浏览器太笨重了,因为它们在后台执行很多我们现在可能忽略的工作。由于其大小,我们无法期望在这些浏览器上获得所有功能。
例如
- Midori 无法运行 Flash。
- Midori 无法运行 Java 插件
- Midori 不支持所有 HTML5 标签,例如没有视频支持
- Raspbian OS 提供的另一个浏览器选项是 Netsurf。
文本编辑器
Leafpad 是我们 Raspian OS 的记事本,Leafpad 是默认的文本编辑器。像 VIM 和 emacs 这样的传统编辑器可以稍后安装,因为它们不预装。
Shell
我们在 Pi 上执行的大多数任务都来自命令行。我们使用 LXTerminal 程序从命令行运行命令。LXTerminal 提供对 shell(也称为命令行)的访问。Raspbian OS 上的默认 shell 是** Bourne Again Shell,简称 BASH**。
**但是**,我们可以使用 chsh 命令更改 shell。
命令行
提示与技巧
**如前**所述,我们在使用 Pi 时将广泛使用命令行。默认情况下,通过 LXTerminal 程序访问命令行。有两个重要的技巧可以使我们在命令行工作时更加轻松。
自动完成:很多时候,我们只需输入命令或文件名的几个字母,然后按 Tab 键,这会让 shell 知道我们正在要求 shell 自动完成我们的文本。Shell 会尝试根据当前上下文(例如当前目录或经常使用的目录如 /bin 和 /usr/bin 中的程序)自动完成字符串。
命令历史:这是另一个技巧,我们可以重用之前运行过的命令。要做到这一点,我们需要使用向上箭头键浏览我们之前的命令,最新的命令会首先出现。如果您在一个很长的命令中犯了一个小错误并需要纠正它,这特别有用,使用历史记录您将无需重新输入整个命令。
文件与文件系统
下面列出了一些文件系统中常用的目录。其中大部分遵循 Linux 结构,有些是 Pi 特有的。/sys 包含 Pi 上的所有硬件,可以从该目录访问。
Directory(目录) |
描述 |
---|---|
/boot |
用于 Linux 内核和其他启动/运行 Pi 所需软件包的文件夹 |
/bin |
Raspbian 相关二进制文件,包括运行 OS GUI 所需的文件 |
/dev |
这是一个虚拟目录,用于访问所有连接的设备,包括存储设备 |
/etc |
将加密密码等杂项配置文件放在此处 |
/home |
这类似于“我的文档”,每个用户名都会在此目录下获得一个单独的目录 |
/lib |
Lib= 库,各种应用程序所需的代码 |
/lost+found |
系统崩溃时文件碎片转储会存储在此处 |
/media |
用于 USB 和 CD 等可移动存储驱动器的目录 |
/mnt |
用于手动挂载外部硬盘驱动器和类似存储设备的目录 |
/opt |
可选软件目录,任何不属于 OS 的应用程序都会放在这里 |
/proc |
另一个虚拟目录,包含有关正在运行的进程(程序)的信息 |
/selinux |
最初由我们亲爱的 NSA 开发的安全实用程序,这些与安全增强型 Linux 相关 |
/sbin |
通常由 root/超级用户使用的系统维护二进制文件 |
/sys |
操作系统文件 |
/tmp |
临时文件 |
/usr |
用于存储用户可访问的程序 |
/var |
程序可以用于持久化数据的虚拟目录 |
我们总能在命令行提示符之前看到当前目录。在 Linux 中,~ 用于表示我们的主目录,因此当我们首次打开命令行时,我们会看到以下内容。
pi@raspberrypi ~ $
文本的含义如下
文本 |
描述 |
---|---|
pi |
我的用户名后跟一个 @ 符号 |
raspberrypi |
设备或计算机的名称。默认名称是 Raspberry pi |
~ |
shell 的当前工作目录。正如我们之前看到的,~ 代表主目录,默认情况下我们在主目录中开始命令行。 |
$ |
$ 是 shell 提示符,我们的所有命令都会显示在此之后。要执行命令,在输入命令后按 Enter 键或 Return 键。 |
让我们来看看如何在您的树莓派上使用 C 和 Python 进行编程。
树莓派与 Python
**Python** 被认为是最好的入门编程语言之一,因为它对任何初学者都易于理解和清晰。由于 Python 开发者社区不断壮大,总会有人能在您需要时提供帮助。
Python 是一种解释型语言。这意味着我们无需在运行前编译代码,因为程序会直接执行,无需编译为机器语言。这类语言编程速度更快。解释型语言还有一些隐藏的好处,例如无需声明变量类型。例如,我们不必明确告知程序我的变量是字符串还是数字或列表,这些都将在执行期间由解释器确定。
Python 解释器可以通过两种不同的方式调用
- 我们可以将 Python 解释器作为交互式 shell 运行,在其中执行单个命令
- 我们也可以作为命令行程序运行,以执行用 Python 编写的独立脚本。
Raspian OS 上的 Python IDE 称为 IDLE。请参见下图,了解如何找到它。
Python 的 Hello World
正如我们之前所见,程序可以通过两种方式用 Python 运行或执行。让我们用这两种方式来写“Hello world”。
方法 1
- 通过单击桌面上的图标或程序菜单中的图标来打开 IDLE3
- 加载 IDE 可能需要一些时间
- IDE 加载后,它会加载一个 Python shell 窗口。
- 在 Python shell 窗口中,输入以下命令
-
Print (“Hello World”)
-
- 按 Enter 键,您将看到 Hello World 打印在下方
方法二
- 通过单击桌面上的图标或程序菜单中的图标来打开 IDLE3
- 加载 IDE 可能需要一些时间
- IDE 加载后,它会加载一个 Python shell 窗口。
- 在 Python shell 窗口中,从文件菜单中单击新建窗口
- 在新窗口中输入以下代码
-
Print (“Hello World”)
-
- 将文件另存为 HelloWorld.py
- 现在打开 LX 终端并输入以下命令来执行文件中的程序
-
Python HelloWorld.py
-
更多的 Python 知识
我们中的一些人来自 Arduino 世界,习惯了编写 setup 和 loop 函数并称之为 sketches。
在 Python 中,我们将 sketches 称为脚本,下面是如何在 Python 中编写 Setup 和 loop。
#Setup part initNum = 0 #repeating loop While True: initNum=initNum+1 if((initNum%2)==0): print(n)
上面的程序只是不断打印所有偶数。要从 IDLE 运行此程序,您可以选择“运行”菜单中的“运行模块”,然后保存文件,下面是关于此的图片。
您可以按 Control + C 来停止 shell 中无限运行的程序。
如果您注意到上面的程序,我们没有使用花括号,而是使用空格来分隔代码块。每个空格是 4 个空格,在 IDLE 中按 TAB 键会插入 4 个空格。
Python 中的函数
如前所述,空格在 Python 中起着重要作用,因为它是一种高度结构化的语言,空格起着决定性作用。空格用于将代码块与主程序分开,形成函数,这些函数可以从程序中的任何位置调用。
下面是一个将相同程序编写为函数并从 main 调用函数的示例。
#global var declaration i=0 #Define Setup function def setup(): global i i = 100 #Define the loop function def loop(): global i i = i + 1 if((i%2)==0): print(i) #Main program setup() while True: loop()
正如您在上面看到的,我们处理事情的方式有些不同,让我们逐一看看。
- 我们在定义函数之前就将 I 声明为我们的全局变量。
- 定义 setup 函数但未执行它
- 再次定义 loop 函数但未执行
- 在这两个函数中,我们通过在变量名前键入 global 关键字来访问全局变量,这将避免创建同名的局部变量,其作用域仅限于函数内部。
- 程序的主体然后调用 setup() 函数一次,并在无限的 While 循环中调用 loop() 函数。
关键词
条件关键词
条件语句中使用的关键词及其简要说明如下:
条件语句 |
描述 |
---|---|
if |
用于确定将执行哪些语句。 |
else |
是可选的。else 关键字后面的语句将被执行, |
elif |
代表 else if。 如果第一个测试评估为 False, |
not |
否定布尔值 |
或 |
至少必须满足一个条件。 |
和 |
布尔表达式中的所有条件都必须满足 |
is |
测试对象身份 |
TRUE |
布尔 True 值 |
FALSE |
布尔 False 值 |
循环关键词
循环中使用的关键词及其简要说明如下:
循环 |
描述 |
---|---|
for |
按顺序迭代集合中的项目 |
while |
控制程序流程 |
break |
如有必要,中断(循环)周期 |
为 |
如果我们想给模块一个不同的别名 |
continue |
用于中断当前周期,而不跳出整个周期。 |
内置函数关键词
内置函数名称的关键词及其简要说明如下:
内置函数 |
描述 |
---|---|
|
打印到控制台 |
pass |
什么也不做 |
del |
删除对象 |
类、模块相关关键词
与类、模块相关的关键词及其简要说明如下:
类、模块和函数 |
描述 |
---|---|
类 |
用于创建新的用户定义对象 |
def |
用于创建新的用户定义函数 |
global |
访问函数外部定义的变量 |
lambda |
创建一个新的匿名函数 |
exec |
动态执行 Python 代码 |
yield |
与生成器一起使用 |
import |
将其他模块导入 Python 脚本 |
return |
退出函数并返回值 |
from |
用于从模块导入特定变量、类或函数 |
错误处理关键词
与错误处理相关的关键词及其简要说明如下。
错误处理 |
描述 |
---|---|
try |
指定异常处理程序 |
except |
捕获异常并执行代码 |
finally |
始终在最后执行。用于清理资源。 |
raise |
创建用户定义的异常 |
assert |
用于调试目的 |
设置编程环境
安装 VIM
我们大多数人都熟悉 Vi 编辑器。VIM 编辑器只是 Vi 的一个扩展版本,它具有与 Vi 编辑器类似的功能,但具有许多额外的功能和改进。
以下是安装 vim 的命令
sudo apt-get install vim
要编辑文件,我们需要一个像下面这样的命令
vim mynewProgram.py
Vim 还带有一个 GUI 版本,可以单独安装。该版本打开在一个新窗口中,并支持鼠标。
sudo apt-get install vim-gnome
安装 Python
在大多数情况下,您可能已经在 Pi 上安装了最新版本的 Python。但如果没有,以下是安装或更新 Python 的命令。
sudo apt-get install python-dev
安装 RPi.GPIO
RPi.GPIO 模块是一个 Python 模块,可以在 Python 安装后安装,它为我们提供了访问 Pi 上的通用输入输出(GPIO)引脚的方法。
以下是安装或更新该模块的命令。
$sudo apt-get install python-rpi.gpio
Python 调试
一旦我们开始编写程序,我们肯定会在某个时候遇到麻烦,并且需要调试程序以找到根本原因。
IDLE 交互模式是处理这种情况的最佳工具。Debug 菜单提供了多种工具来分析我们的代码/程序,并且还提供了逐行执行选项,可以在程序每一步查看变量,就像在任何其他高级语言和 IDE 中一样。
错误类型
错误类型 |
描述 |
---|---|
语法错误 |
:最常见的错误是语法错误,也是最容易修复的。这些通常是输入错误或误解的关键词。 |
语义错误 |
:这些是逻辑错误,意味着程序结构良好但未按预期工作。这些通常更难跟踪,我们的 IDLE 调试器将帮助我们逐步执行程序并找到根本原因。 |
就像良好的编程一样,良好的调试技能非常重要,需要多年的实践和经验。但是,以下是一些最佳实践,可以帮助我们在 Pi 上的 Python 中调试程序。
调试最佳实践
- 经常使用 print() 函数来显示给定控制流中的程序执行点
- 在程序执行期间使用 _print()+ 打印变量值
- 确保正确放置了空格
- 解释器报告的行之前可能存在语法错误,因此当报告语法错误时,我们需要回溯并检查语法错误。
- 确保全局变量和局部变量及其用法
- 如果使用了括号,请确保它们匹配
- 如果您不确定运算顺序,请使用括号强制执行运算顺序。
- 例如:5 + 8 * 3 与 (5+8) * 3 不同
C 语言编程
安装 **BCM2835 – C**
一个用于树莓派的 C 库,可以从以下链接下载
http://www.airspayce.com/mikem/bcm2835/
以下是 airspyace 关于该库的引用说明。
“这是一个用于树莓派(RPi)的 C 库。它提供了对 Broadcom BCM 2835 芯片上 GPIO 和其他 IO 函数的访问,允许访问 RPi 板上 26 引脚 IDE 插头的 GPIO 引脚,以便您可以控制各种外部设备并与之接口。
它提供了读取数字输入和设置数字输出、使用 SPI 和 I2C 以及访问系统计时器的功能。通过轮询支持引脚事件检测(不支持中断)。
它兼容 C++,并作为头文件和非共享库安装在任何基于 Linux 的发行版上(但显然除了在树莓派或另一块带有 BCM 2835 的板子上使用外,没有其他用途)。”
以下是安装步骤。按顺序逐一执行每个命令
从网站获取 tar 文件
wget http://www.airspayce.com/mikem/bcm2835/bcm2835-1.35.tar.gz
解压或解压您的库
tar xvzf bcm2835-1.35.tar.gz
切换到解压后的目录
cd bcm2835-1.35
运行 configure 命令
./configure
构建库
Make
检查编译
sudo make check
安装库
sudo make install
要测试安装,您可以运行以下程序,使板上的 LED 每 500 毫秒闪烁一次。
#include <bcm2835.h> #define MY_PIN RPI_GPIO_P1_11 BOOLEAN main(int argc, char **argv) { if (!bcm2835_init()) return FALSE; bcm2835_gpio_fsel(MY_PIN, BCM2835_GPIO_FSEL_OUTP); while (1=1) { bcm2835_gpio_write(MY_PIN, HIGH); bcm2835_delay(700); bcm2835_gpio_write(MY_PIN, LOW); bcm2835_delay(700); } bcm2835_close(); return TRUE; }
然后编译代码
gcc -o blink blink.c -lbcm2835
现在以管理员身份运行代码
sudo ./blink
安装 Wiring Pi
以下是 WiringPi 开源项目的链接以及关于该项目的引述文本
**WiringPi** 是一个用 C 编写的 GPIO 访问库,用于**树莓派**中使用的 BCM2835。它是在 **GNU LGPLv3** 许可下发布的,并且可以从 C 和 C++ 以及许多其他语言(带有适当的包装器,请参阅下文)使用。它设计得对于使用过 Arduino “wiring” 系统的人来说很熟悉1。安装 WiringPi 的步骤
sudo apt-get update sudo apt-get upgrade apt-get install git-core git clone git://git.drogon.net/wiringPi cd wiringPi git pull origin cd wiringPi ./build
测试 wiringPi 是否安装成功。
gpio -v gpio readall
C 语言光感应程序
以下是一个读取光强度并在屏幕上打印出来的程序。
#include <wiringPi.h> #include <stdio.h> #define G_1 0 #define G_2 1 #define G_3 2 typedef unsigned char gchar; gchar get_Result(void) { gchar i; gchar dat1=0, dat2=0; digitalWrite(G_1, 0); digitalWrite(G_2,0); digitalWrite(G_3,1); delayMicroseconds(2); digitalWrite(G_2,1); delayMicroseconds(2); digitalWrite(G_2,0); digitalWrite(G_3,1); delayMicroseconds(2); digitalWrite(G_2,1); delayMicroseconds(2); digitalWrite(G_2,0); digitalWrite(G_3,0); delayMicroseconds(2); digitalWrite(G_2,1); digitalWrite(G_3,1); delayMicroseconds(2); digitalWrite(G_2,0); digitalWrite(G_3,1); delayMicroseconds(2); for(i=0;i<8;i++) { digitalWrite(G_2,1); delayMicroseconds(2); digitalWrite(G_2,0); delayMicroseconds(2); pinMode(G_3, INPUT); dat1=dat1<<1 | digitalRead(G_3); } for(i=0;i<8;i++) { dat2 = dat2 | ((gchar)(digitalRead(G_3))<<i); digitalWrite(G_2,1); delayMicroseconds(2); digitalWrite(G_2,0); delayMicroseconds(2); } digitalWrite(G_1,1); if(dat1==dat2) { return dat1 ; } else return 0; } int main(void) { gchar rawValue; gchar calculate_Value; if(wiringPiSetup() == -1){ printf("Failure with calling a wiringPi method!"); return 1; } pinMode(G_1, OUTPUT); pinMode(G_2, OUTPUT); while(1){ pinMode(G_3, OUTPUT); rawValue = get_Result(); calculate_Value = 210 - rawValue; printf("Current calculate_Valueination : %d\n", calculate_Value); delay(500); } return 0; }
以下是我面包板上的连接。
既然我们已经了解了如何用 Python 和 C 编程设备,请告诉我您最喜欢哪种以及原因,并在评论区告诉我。