又一个 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|
//LEDPB5
#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 schedule

Check out similar posts by category: Allgemein, Embedded