又一个 Atom Arduino 闪烁器
在试验 Atom 时,我制作了一个最小示例,让我的旧 Arduino Uno 周期性闪烁其 LED。
虽然外面有很多示例(其中一些甚至能用!)但我不想引入对 Arduino 库的任何依赖。除了使构建更困难(即使 arscons 相当不错)外,它还增加了对象大小,而 Arduino 只支持有限的处理器范围。我需要灵活性以便在 ATTiny45 等控制器上使用代码
大多数示例没有注释,因此对初学者来说难以理解。虽然我认为 Atom 在概念上比 Copilot 显著更容易理解,但经典的嵌入式 C 程序员可能需要带注释的源代码才能完全理解 Atom。
此外,我使用 QuasiQuotation 文章中描述的技术来提高内联 C 代码的可读性。此外,我禁用了断言和规则覆盖等功能
Blink.hs
{-# LANGUAGE QuasiQuotes #-}
{-|
ATMega328P 的极简 Atom 重置示例。
假设 LED 在 PB5 上(例如 Arduino Uno)。
不需要 Arduino 库。
编译示例:
@
runghc Blink.hs
avr-gcc -o Blink.elf -Os -Wall -mmcu=atmega328p -DF_CPU=16000000L blink.c
avr-objcopy -O ihex -R .eeprom Blink.elf Blink.hex
@
-}
module Blink (main) where
import StringEmbed
import Language.Atom
-- | 我们的主 Atom 程序。
-- 周期性闪烁 LED
blink :: Atom ()
blink = do
-- 声明一个局部状态变量
-- 控制 LED 是否打开或关闭
on <- bool "on" True
-- 每 50000 次调用 blink() ...
period 50000 $ atom "blinkOn" $ do
-- 反转 LED 状态
on <== not_ (value on)
-- 并将新状态写入 PORTB
call "showLED"
-- | 将在 atom 代码之前插入的 C 代码
cHeader :: String
cHeader = [embedStr|
#include <avr/io.h>
#include <util/delay.h>
static inline void showLED(void);
|]
-- | 将在 atom 代码之后插入的 C 代码
cFooter :: String
cFooter = [embedStr|
//LED:PB5
#define LED_PIN (1<<5)
//设置/重置 LED
static inline void showLED() {
if(state.blink.on) {
PORTB |= LED_PIN;
} else {
PORTB &= ~(LED_PIN);
}
}
int main (void) {
//设置 LED 引脚为 OUTPUT
DDRB |= LED_PIN;
while(1) {
blink();
}
return 0; //永远不会到达
}
|]
main :: IO ()
main = do
let code _ _ _ = (cHeader, cFooter)
let cfg = defaults {cCode = code,
cRuleCoverage = False,
cAssert = False}
(schedule, _, _, _, _) <- compile "blink" cfg blink
putStrLn $ reportSchedule scheduleIf this post helped you, please consider buying me a coffee or donating via PayPal to support research & publishing of new posts on TechOverflow