From 81532e53e440b87a4ed77b1a8bcb3e7aa2a59ae3 Mon Sep 17 00:00:00 2001 From: Xingyu Wang Date: Tue, 3 Nov 2020 00:07:12 +0800 Subject: [PATCH 1/3] PRF @gxlct008 --- ...0503 Go on very small hardware (Part 3).md | 110 +++++++++--------- 1 file changed, 53 insertions(+), 57 deletions(-) diff --git a/translated/tech/20180503 Go on very small hardware (Part 3).md b/translated/tech/20180503 Go on very small hardware (Part 3).md index 28d5817236..11ef451aa7 100644 --- a/translated/tech/20180503 Go on very small hardware (Part 3).md +++ b/translated/tech/20180503 Go on very small hardware (Part 3).md @@ -1,6 +1,6 @@ [#]: collector: (lujun9972) [#]: translator: (gxlct008) -[#]: reviewer: ( ) +[#]: reviewer: (wxy) [#]: publisher: ( ) [#]: url: ( ) [#]: subject: (Go on very small hardware Part 3) @@ -9,27 +9,31 @@ Go 语言在极小硬件上的运用(三) ====== -[![STM32F030F4P6][1]][2] -在本系列的 [第一][3] 和 [第二][4] 部分中讨论的大多数示例都是以一种或另一种方式闪烁的 LED。起初它可能很有趣,但是一段时间后变得有些无聊。让我们做些更有趣的事情…… +![](https://img.linux.net.cn/data/attachment/album/202010/24/090026to9c9sweyrw9ww37.png) + + +在本系列的 [第一][3] 和 [第二][4] 部分中讨论的大多数示例都是以某种方式闪烁的 LED。起初它可能很有趣,但是一段时间后变得有些无聊。让我们做些更有趣的事情…… …让我们点亮更多的 LED! -### WS281x LEDs +![STM32F030F4P6][1] -[WS281x][5] RGB LED(及其克隆)非常受欢迎。您可以作为单个元素购买、链成长条或组装成矩阵、环或其他形状因子。 +### WS281x LED + +[WS281x][5] RGB LED(及其克隆品)非常受欢迎。你可以以单个元素购买、链成长条或组装成矩阵、环或其他形状。 ![WS2812B][6] -它们可以串联连接,基于这个事实,您可以只用 MCU 的单个引脚就可以控制一个很长的 LED 灯条。不幸的是,它们的内部控制器使用的物理协议不能直接适用于您在 MCU 中可以找到的任何外围设备。您必须使用 位脉冲bit-banging或以特殊方式使用可用的外设。 +它们可以串联连接,基于这个事实,你可以只用 MCU 的单个引脚就可以控制一个很长的 LED 灯条。不幸的是,它们的内部控制器使用的物理协议不能直接适用于你在 MCU 中可以找到的任何外围设备。你必须使用 位脉冲bit-banging或以特殊方式使用可用的外设。 -哪种可用的解决方案最有效取决于同时控制的 LED 灯条数量。如果您必须驱动 4 到 16 个条带,那么最有效的方法是 [使用定时器和 DMA][7](请不要忽略 Martin 文章末尾的链接)。 +哪种可用的解决方案最有效取决于同时控制的 LED 灯条数量。如果你必须驱动 4 到 16 个灯条,那么最有效的方法是 [使用定时器和 DMA][7](请不要忽略这篇文章末尾的链接)。 -如果只需要控制一个或两个条带,请使用可用的 SPI 或 UART 外设。对于 SPI,您只能在发送的一个字节中编码两个 WS281x 位。由于巧妙地使用了起始位和停止位,UART 允许更密集的编码:每发送一个字节 3 位。 +如果只需要控制一个或两个灯条,请使用可用的 SPI 或 UART 外设。对于 SPI,你只能在发送的一个字节中编码两个 WS281x 位。由于巧妙地使用了起始位和停止位,UART 允许更密集的编码:每发送一个字节 3 位。 -我在 [此站点][8] 上找到了有关 UART 协议如何适用于 WS281x 协议的最佳解释。如果您不懂波兰语,这里是 [英文翻译][9]。 +我在 [此站点][8] 上找到了有关 UART 协议如何适用于 WS281x 协议的最佳解释。如果你不懂波兰语,这里是 [英文翻译][9]。 -基于 WS281x 的 LED 仍然是最受欢迎的,但市场上也有 SPI 控制的 LED:[APA102][10],[SK9822][11]。关于它们的三篇有趣的文章在这里:[1][12],[2][13],[3][14] +基于 WS281x 的 LED 仍然是最受欢迎的,但市场上也有 SPI 控制的 LED:[APA102][10]、[SK9822][11]。关于它们的三篇有趣的文章在这里:[1][12]、[2][13]、[3][14]。 ### LED 环 @@ -43,12 +47,11 @@ Go 语言在极小硬件上的运用(三) ![WS2812B][16] -我们的 STM32F030F4P6 MCU 和整个 STM32 F0、F3、F7、L4 系列具有 F1、F4、L1 MCU 不具备的一项重要功能:它可以反转 UART 信号,因此我们可以将环直接连接到 UART TXD 引脚。如果您不知道我们需要这种反转,那么您可能没有读过我上面提到的 [文章][9]。 +我们的 STM32F030F4P6 MCU 和整个 STM32 F0、F3、F7、L4 系列具有 F1、F4、L1 MCU 不具备的一项重要功能:它可以反转 UART 信号,因此我们可以将环直接连接到 UART TXD 引脚。如果你不知道我们需要这种反转,那么你可能没有读过我上面提到的 [文章][9]。 -因此,您不能以这种方式使用流行的 [Blue Pill][17] 或 [STM32F4-DISCOVERY][18]。使用其 SPI 外设或外部反相器。有关使用 SPI 的 NUCLEO-F411RE,请参见 [圣诞树灯][19] 项目作为 UART + 逆变器的示例或 [WS2812示例][20]。 +因此,你不能以这种方式使用流行的 [Blue Pill][17] 或 [STM32F4-DISCOVERY][18]。使用其 SPI 外设或外部反相器。有关使用 SPI 的 NUCLEO-F411RE,请参见 [圣诞树灯][19] 项目作为 UART + 逆变器的示例或 [WS2812示例][20]。 - -顺便说一下,大多数 DISCOVERY 板可能还有一个问题:它们在 VDD = 3V 而不是 3.3V 的情况下工作。 对于高 DI,WS281x 至少要求电源电压 * 0.7。如果是 5V 电源,则为 3.5V;如果是 4.7V 电源,则为 3.3V;可在 DISCOVERY 的 5V 引脚上找到。如您所见,即使在我们的情况下,第一个 LED 的工作电压也低于规格 0.2V。对于 DISCOVERY 板,如果供电 4.7V,它将工作在低于规格的 0.3V 下;如果供电 5V,它将工作在低于规格 0.5V 下。 +顺便说一下,大多数 DISCOVERY 板可能还有一个问题:它们在 VDD = 3V 而不是 3.3V 的情况下工作。 对于高 DI,WS281x 至少要求电源电压 * 0.7。如果是 5V 电源,则为 3.5V;如果是 4.7V 电源,则为 3.3V;可在 DISCOVERY 的 5V 引脚上找到。如你所见,即使在我们的情况下,第一个 LED 的工作电压也低于规格 0.2V。对于 DISCOVERY 板,如果供电 4.7V,它将工作在低于规格的 0.3V 下;如果供电 5V,它将工作在低于规格 0.5V 下。 让我们结束这段冗长的介绍并转到代码: @@ -134,9 +137,9 @@ var ISRs = [...]func(){ } ``` -##### 导入部分 +#### 导入部分 -与前面的示例相比,导入部分中的新内容是 `rand/math` 包和带有 `led/ws281x` 子树的 led 包。 led 包本身包含 `Color` 类型的定义。 `led/ws281x/wsuart` 定义了 `ColorOrder`、`Pixel` 和 `Strip` 类型。 +与前面的示例相比,导入部分中的新内容是 `rand/math` 包和带有 `led/ws281x` 子树的 `led` 包。 `led` 包本身包含 `Color` 类型的定义。 `led/ws281x/wsuart` 定义了 `ColorOrder`、`Pixel` 和 `Strip` 类型。 我想知道如何使用 `image/color` 中的 `Color` 或 `RGBA` 类型,以及如何以它将实现 `image.Image` 接口的方式定义 `Strip`。 但是由于使用了 [gamma 校正][21] 和 大开销的 `color/draw` 包,我以简单的方式结束: @@ -147,13 +150,13 @@ type Strip []Pixel 使用一些有用的方法。然而,这种情况在未来可能会改变。 -##### init 函数 +#### init 函数 `init` 函数没有太多新颖之处。 UART 波特率从 115200 更改为 3000000000/1390 ≈ 2158273,相当于每个 WS2812 位 1390 纳秒。 CR2 寄存器中的 TxInv 位设置为反转 TXD 信号。 -##### main 函数 +#### main 函数 -`XorShift64` 伪随机数生成器用于生成随机颜色。 [XORSHIFT][22] 是目前由 `math/rand` 包实现的唯一算法。您必须使用带有非零参数的 `Seed` 方法显式初始化它。 +`XorShift64` 伪随机数生成器用于生成随机颜色。 [XORSHIFT][22] 是目前由 `math/rand` 包实现的唯一算法。你必须使用带有非零参数的 `Seed` 方法显式初始化它。 `rgb` 变量的类型为 `wsuart.ColorOrder`,并设置为 WS2812 使用的 GRB 颜色顺序(WS2811 使用 RGB 顺序)。然后用于将颜色转换为像素。 @@ -166,9 +169,9 @@ strip.Clear() 其余代码使用随机颜色绘制类似于 “Please Wait…” 微调器的内容。 -条带切片充当帧缓冲区。 `tts.Write(strip.Bytes()` 将帧缓冲区的内容发送到环。 +`strip` 切片充当帧缓冲区。 `tts.Write(strip.Bytes())` 将帧缓冲区的内容发送到环。 -##### 中断 +#### 中断 该程序由处理中断的代码组成,与先前的 [UART 示例][23] 中的代码相同。 @@ -182,27 +185,25 @@ $ arm-none-eabi-size cortexm0.elf $ openocd -d0 -f interface/stlink.cfg -f target/stm32f0x.cfg -c 'init; program cortexm0.elf; reset run; exit' ``` -我跳过了 openocd 输出。下面的视频显示了该程序的工作原理: +我跳过了 `openocd` 的输出。下面的视频显示了该程序的工作原理: 原文中插入视频的代码: - + +![video](https://ziutek.github.io/videos/rgbspinner.mp4) ### 让我们做些有用的事情... -在 [第一部分][3] 的开头,我曾问过:“我们能降到多低,还能做一些有用的事情?”。 我们的 MCU 实际上是一种低端设备(8 比特的人可能会不同意我的看法),但到目前为止,我们还没有做任何有用的事情。 +在 [第一部分][3] 的开头,我曾问过:“Go 能深入到多低层,而还能做一些有用的事情?”。 我们的 MCU 实际上是一种低端设备(8 比特的人可能会不同意我的看法),但到目前为止,我们还没有做任何有用的事情。 所以... 让我们做些有用的事情... 让我们做个时钟! -在互联网上有许多由 RGB LED 构成的时钟示例。让我们用小板子和 RGB 环制作自己的时钟。我们按照下面的描述更改先前的代码。 +在互联网上有许多由 RGB LED 构成的时钟示例。让我们用我们的小板子和 RGB 环制作自己的时钟。我们按照下面的描述更改先前的代码。 -##### 导入部分 +#### 导入部分 删除 `math/rand` 包,然后添加 `stm32/hal/exti`。 -##### 全局变量 +#### 全局变量 添加两个新的全局变量:`btn` 和 `btnev`: @@ -214,9 +215,9 @@ var ( ) ``` -它们将用来处理那些用于设置时钟的 “button”。我们的板子除了重置之外没有其他按钮,但是如果没有它,我们仍然可以通过某种方式进行管理。 +它们将用来处理那些用于设置时钟的 “按钮”。我们的板子除了重置之外没有其他按钮,但是如果没有它,我们仍然可以通过某种方式进行管理。 -##### init 函数 +#### init 函数 将这段代码添加到 `init` 函数: @@ -237,9 +238,9 @@ rtos.IRQ(irq.EXTI4_15).Enable() 我们使用 EXTI 外设来跟踪 PA4 状态。它被配置为在发生任何更改时都会产生中断。 -##### btnWait 函数 +#### btnWait 函数 -定义一个新的辅助功能: +定义一个新的辅助函数: ``` func btnWait(state int, deadline int64) bool { @@ -254,7 +255,7 @@ func btnWait(state int, deadline int64) bool { } ``` -它等待 “button” 引脚上的指定状态,但只等到最后期限出现。这是稍微改进的轮询代码: +它等待 “按钮” 引脚上的指定状态,但只等到最后期限出现。这是稍微改进的轮询代码: ``` for btn.Load() != state { @@ -264,9 +265,9 @@ for btn.Load() != state { } ``` -我们的 `btnWait` 函数不是忙于等待状态或截止日期,而是使用 `rtos.EventFlag` 类型的 `btnev` 变量休眠,直到有事情发生。您当然可以使用通道而不是 `rtos.EventFlag`,但是后者便宜得多。 +我们的 `btnWait` 函数不是忙于等待 `state` 或 `deadline`,而是使用 `rtos.EventFlag` 类型的 `btnev` 变量休眠,直到有事情发生。你当然可以使用通道而不是 `rtos.EventFlag`,但是后者便宜得多。 -##### main 函数 +#### main 函数 我们需要全新的 `main` 函数: @@ -331,11 +332,11 @@ func main() { } ``` -我们使用 `rtos.Nanosec` 函数代替 `time.Now` 来获取当前时间。这样可以节省大量的 Flash,但也使我们的时钟变成了不知道日、月、年的老式设备,最糟糕的是它无法处理夏令时的变化。 +我们使用 `rtos.Nanosec` 函数代替 `time.Now` 来获取当前时间。这样可以节省大量的闪存,但也使我们的时钟变成了不知道日、月、年的老式设备,最糟糕的是它无法处理夏令时的变化。 我们的环有 24 个 LED,因此秒针的显示精度可以达到 2.5 秒。为了不牺牲这种精度并获得流畅的运行效果,我们使用 1/4 秒作为基准间隔。半秒就足够了,但四分之一秒更准确,而且与 16 和 48 个 LED 配合使用也很好。 -红色、绿色和蓝色分别用于时针、分针和秒针。这允许我们使用简单的 `逻辑或操作` 进行颜色混合。我们 `Color.Blend` 方法可以混合任意颜色,但是我们缺少 Flash,所以我们选择最简单的解决方案。 +红色、绿色和蓝色分别用于时针、分针和秒针。这允许我们使用简单的“逻辑或操作”进行颜色混合。我们 `Color.Blend` 方法可以混合任意颜色,但是我们闪存不多,所以我们选择最简单的解决方案。 我们只有在秒针移动时才重画时钟。 @@ -345,9 +346,9 @@ btnWait(0, int64(qs+ds)*25e7) 上面的这行代码等待的正是那一刻,或者是按钮的按下。 -每按一下按钮就会把时钟向前调一调。按住按钮一段时间会产生加速度。 +每按一下按钮就会把时钟向前调一调。按住按钮一段时间会加速调整。 -##### 中断 +#### 中断 定义新的中断处理程序: @@ -363,12 +364,11 @@ func exti4_15ISR() { 并将 `irq.EXTI4_15: exti4_15ISR` 条目添加到 ISR 数组。 -该处理程序(或中断服务程序)处理 EXTI4_15 IRQ。 Cortex-M0 CPU 支持的 IRQ 明显少于其较大的同类兄弟处理器,因此您经常可以看到一个 IRQ 被多个中断源共享。在我们的例子中,一个 IRQ 由 12 个 EXTI 线共享。 +该处理程序(或中断服务程序)处理 EXTI4_15 IRQ。 Cortex-M0 CPU 支持的 IRQ 明显少于其较大的同类兄弟处理器,因此你经常可以看到一个 IRQ 被多个中断源共享。在我们的例子中,一个 IRQ 由 12 个 EXTI 线共享。 -exti4_15ISR 读取所有挂起的位,并从中选择 12 个更高的有效位。接下来,它清除 EXTI 中选中的位并开始处理它们。在我们的例子中,仅检查第 4 位。 `btnev.Signal(1)` 引发 `btnev.Wait(1, deadline)` 唤醒并返回 true。 +exti4_15ISR 读取所有挂起的位,并从中选择 12 个更高的有效位。接下来,它清除 EXTI 中选中的位并开始处理它们。在我们的例子中,仅检查第 4 位。 `btnev.Signal(1)` 引发 `btnev.Wait(1, deadline)` 唤醒并返回 `true`。 - -您可以在 [Github][24] 上找到完整的代码。让我们来编译它: +你可以在 [Github][24] 上找到完整的代码。让我们来编译它: ``` $ egc @@ -377,7 +377,7 @@ $ arm-none-eabi-size cortexm0.elf 15960 240 216 16416 4020 cortexm0.elf ``` -这里所有的改进只有 184 个字节。让我们再次重新构建所有内容,但这次在 typeinfo 中不使用任何类型和字段名: +这里所有的改进只得到 184 个字节。让我们再次重新构建所有内容,但这次在 typeinfo 中不使用任何类型和字段名: ``` $ cd $HOME/emgo @@ -389,26 +389,22 @@ $ arm-none-eabi-size cortexm0.elf 15120 240 216 15576 3cd8 cortexm0.elf ``` -现在,有了千字节的空闲空间,您可以改进一些东西。让我们看看它是如何工作的: +现在,有了千字节的空闲空间,你可以改进一些东西。让我们看看它是如何工作的: -原文中插入视频的代码: - +![video](https://ziutek.github.io/videos/rgbclock.mp4) 我不知道我是怎么精确打到 3:00 的!? -以上就是所有内容!在第 4 部分(本系列的结束)中,我们将尝试在 LCD 上显示一些内容。 +以上就是所有内容!在第 4 部分(本系列的结束)中,我们将尝试在 LCD 上显示一些内容。(LCTT 译注:然而烂尾了,第三篇写于 2018 年,整个博客当年就停更了。) -------------------------------------------------------------------------------- via: https://ziutek.github.io/2018/05/03/go_on_very_small_hardware3.html -作者:[-;Michał Derkacz][a] +作者:[Michał Derkacz][a] 选题:[lujun9972][b] 译者:[gxlct008](https://github.com/gxlct008) -校对:[校对者ID](https://github.com/校对者ID) +校对:[wxy](https://github.com/wxy) 本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出 @@ -416,8 +412,8 @@ via: https://ziutek.github.io/2018/05/03/go_on_very_small_hardware3.html [b]: https://github.com/lujun9972 [1]: https://ziutek.github.io/images/mcu/f030-demo-board/board.jpg [2]: https://ziutek.github.io/2018/05/03/go_on_very_small_hardware3.html -[3]: https://ziutek.github.io/2018/03/30/go_on_very_small_hardware.html -[4]: https://ziutek.github.io/2018/04/14/go_on_very_small_hardware2.html +[3]: https://linux.cn/article-11383-1.html +[4]: https://linux.cn/article-12747-1.html [5]: http://www.world-semi.com/solution/list-4-1.html [6]: https://ziutek.github.io/images/led/ws2812b.jpg [7]: http://www.martinhubacek.cz/arm/improved-stm32-ws2812b-library From b4550919c2bb51194a8723ec25c4c8081d3838b8 Mon Sep 17 00:00:00 2001 From: Xingyu Wang Date: Tue, 3 Nov 2020 00:09:13 +0800 Subject: [PATCH 2/3] PUB @gxlct008 https://linux.cn/article-12782-1.html --- .../20180503 Go on very small hardware (Part 3).md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename {translated/tech => published}/20180503 Go on very small hardware (Part 3).md (99%) diff --git a/translated/tech/20180503 Go on very small hardware (Part 3).md b/published/20180503 Go on very small hardware (Part 3).md similarity index 99% rename from translated/tech/20180503 Go on very small hardware (Part 3).md rename to published/20180503 Go on very small hardware (Part 3).md index 11ef451aa7..ac3c5c9ebc 100644 --- a/translated/tech/20180503 Go on very small hardware (Part 3).md +++ b/published/20180503 Go on very small hardware (Part 3).md @@ -1,8 +1,8 @@ [#]: collector: (lujun9972) [#]: translator: (gxlct008) [#]: reviewer: (wxy) -[#]: publisher: ( ) -[#]: url: ( ) +[#]: publisher: (wxy) +[#]: url: (https://linux.cn/article-12782-1.html) [#]: subject: (Go on very small hardware Part 3) [#]: via: (https://ziutek.github.io/2018/05/03/go_on_very_small_hardware3.html) [#]: author: (Michał Derkacz ) From 9b72fc0e71dafb5855a72cb5c78646e6eb04dd20 Mon Sep 17 00:00:00 2001 From: Xingyu Wang Date: Tue, 3 Nov 2020 00:14:34 +0800 Subject: [PATCH 3/3] PRF --- published/20180503 Go on very small hardware (Part 3).md | 2 -- 1 file changed, 2 deletions(-) diff --git a/published/20180503 Go on very small hardware (Part 3).md b/published/20180503 Go on very small hardware (Part 3).md index ac3c5c9ebc..4fa8c39c6d 100644 --- a/published/20180503 Go on very small hardware (Part 3).md +++ b/published/20180503 Go on very small hardware (Part 3).md @@ -187,8 +187,6 @@ $ openocd -d0 -f interface/stlink.cfg -f target/stm32f0x.cfg -c 'init; program c 我跳过了 `openocd` 的输出。下面的视频显示了该程序的工作原理: -原文中插入视频的代码: - ![video](https://ziutek.github.io/videos/rgbspinner.mp4) ### 让我们做些有用的事情...