日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Go語言在極小硬件上的運(yùn)用(二)

在本文的 第一部分 的結(jié)尾,我承諾要寫關(guān)于接口的內(nèi)容。我不想在這里寫有關(guān)接口或完整或簡短的講義。相反,我將展示一個(gè)簡單的示例,來說明如何定義和使用接口,以及如何利用無處不在的 io.Writer 接口。還有一些關(guān)于反射reflection和半主機(jī)semihosting的內(nèi)容。

目前創(chuàng)新互聯(lián)已為近1000家的企業(yè)提供了網(wǎng)站建設(shè)、域名、虛擬主機(jī)、網(wǎng)站改版維護(hù)、企業(yè)網(wǎng)站設(shè)計(jì)、平樂網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。

STM32F030F4P6

接口是 Go 語言的重要組成部分。如果你想了解更多有關(guān)它們的信息,我建議你閱讀《高效的 Go 編程》 和 Russ Cox 的文章。

并發(fā) Blinky – 回顧

當(dāng)你閱讀前面示例的代碼時(shí),你可能會(huì)注意到一中打開或關(guān)閉 LED 的反直覺方式。 Set 方法用于關(guān)閉 LED,Clear 方法用于打開 LED。這是由于在 漏極開路配置open-drain configuration 下驅(qū)動(dòng)了 LED。我們可以做些什么來減少代碼的混亂?讓我們用 On 和 Off 方法來定義 LED 類型:

 
 
 
 
  1. type LED struct {
  2. pin gpio.Pin
  3. }
  4.  
  5. func (led LED) On() {
  6. led.pin.Clear()
  7. }
  8.  
  9. func (led LED) Off() {
  10. led.pin.Set()
  11. }

現(xiàn)在我們可以簡單地調(diào)用 led.On() 和 led.Off(),這不會(huì)再引起任何疑惑了。

在前面的所有示例中,我都嘗試使用相同的 漏極開路配置open-drain configuration來避免代碼復(fù)雜化。但是在最后一個(gè)示例中,對(duì)于我來說,將第三個(gè) LED 連接到 GND 和 PA3 引腳之間并將 PA3 配置為推挽模式push-pull mode會(huì)更容易。下一個(gè)示例將使用以此方式連接的 LED。

但是我們的新 LED 類型不支持推挽配置,實(shí)際上,我們應(yīng)該將其稱為 OpenDrainLED,并定義另一個(gè)類型 PushPullLED

 
 
 
 
  1. type PushPullLED struct {
  2. pin gpio.Pin
  3. }
  4.  
  5. func (led PushPullLED) On() {
  6. led.pin.Set()
  7. }
  8.  
  9. func (led PushPullLED) Off() {
  10. led.pin.Clear()
  11. }

請(qǐng)注意,這兩種類型都具有相同的方法,它們的工作方式也相同。如果在 LED 上運(yùn)行的代碼可以同時(shí)使用這兩種類型,而不必注意當(dāng)前使用的是哪種類型,那就太好了。 接口類型可以提供幫助:

 
 
 
 
  1. package main
  2.  
  3. import (
  4. "delay"
  5.  
  6. "stm32/hal/gpio"
  7. "stm32/hal/system"
  8. "stm32/hal/system/timer/systick"
  9. )
  10.  
  11. type LED interface {
  12. On()
  13. Off()
  14. }
  15.  
  16. type PushPullLED struct{ pin gpio.Pin }
  17.  
  18. func (led PushPullLED) On() {
  19. led.pin.Set()
  20. }
  21.  
  22. func (led PushPullLED) Off() {
  23. led.pin.Clear()
  24. }
  25.  
  26. func MakePushPullLED(pin gpio.Pin) PushPullLED {
  27. pin.Setup(&gpio.Config{Mode: gpio.Out, Driver: gpio.PushPull})
  28. return PushPullLED{pin}
  29. }
  30.  
  31. type OpenDrainLED struct{ pin gpio.Pin }
  32.  
  33. func (led OpenDrainLED) On() {
  34. led.pin.Clear()
  35. }
  36.  
  37. func (led OpenDrainLED) Off() {
  38. led.pin.Set()
  39. }
  40.  
  41. func MakeOpenDrainLED(pin gpio.Pin) OpenDrainLED {
  42. pin.Setup(&gpio.Config{Mode: gpio.Out, Driver: gpio.OpenDrain})
  43. return OpenDrainLED{pin}
  44. }
  45.  
  46. var led1, led2 LED
  47.  
  48. func init() {
  49. system.SetupPLL(8, 1, 48/8)
  50. systick.Setup(2e6)
  51.  
  52. gpio.A.EnableClock(false)
  53. led1 = MakeOpenDrainLED(gpio.A.Pin(4))
  54. led2 = MakePushPullLED(gpio.A.Pin(3))
  55. }
  56.  
  57. func blinky(led LED, period int) {
  58. for {
  59. led.On()
  60. delay.Millisec(100)
  61. led.Off()
  62. delay.Millisec(period - 100)
  63. }
  64. }
  65.  
  66. func main() {
  67. go blinky(led1, 500)
  68. blinky(led2, 1000)
  69. }
  70.  

我們定義了 LED 接口,它有兩個(gè)方法: On 和 Off。 PushPullLED 和 OpenDrainLED 類型代表兩種驅(qū)動(dòng) LED 的方式。我們還定義了兩個(gè)用作構(gòu)造函數(shù)的 Make*LED 函數(shù)。這兩種類型都實(shí)現(xiàn)了 LED 接口,因此可以將這些類型的值賦給 LED 類型的變量:

 
 
 
 
  1. led1 = MakeOpenDrainLED(gpio.A.Pin(4))
  2. led2 = MakePushPullLED(gpio.A.Pin(3))

在這種情況下,可賦值性assignability在編譯時(shí)檢查。賦值后,led1 變量包含一個(gè) OpenDrainLED{gpio.A.Pin(4)},以及一個(gè)指向 OpenDrainLED 類型的方法集的指針。 led1.On() 調(diào)用大致對(duì)應(yīng)于以下 C 代碼:

 
 
 
 
  1. led1.methods->On(led1.value)

如你所見,如果僅考慮函數(shù)調(diào)用的開銷,這是相當(dāng)廉價(jià)的抽象。

但是,對(duì)接口的任何賦值都會(huì)導(dǎo)致包含有關(guān)已賦值類型的大量信息。對(duì)于由許多其他類型組成的復(fù)雜類型,可能會(huì)有很多信息:

 
 
 
 
  1. $ egc
  2. $ arm-none-eabi-size cortexm0.elf
  3. text data bss dec hex filename
  4. 10356 196 212 10764 2a0c cortexm0.elf

如果我們不使用 反射,可以通過避免包含類型和結(jié)構(gòu)字段的名稱來節(jié)省一些字節(jié):

 
 
 
 
  1. $ egc -nf -nt
  2. $ arm-none-eabi-size cortexm0.elf
  3. text data bss dec hex filename
  4. 10312 196 212 10720 29e0 cortexm0.elf

生成的二進(jìn)制文件仍然包含一些有關(guān)類型的必要信息和關(guān)于所有導(dǎo)出方法(帶有名稱)的完整信息。在運(yùn)行時(shí),主要是當(dāng)你將存儲(chǔ)在接口變量中的一個(gè)值賦值給任何其他變量時(shí),需要此信息來檢查可賦值性。

我們還可以通過重新編譯所導(dǎo)入的包來刪除它們的類型和字段名稱:

 
 
 
 
  1. $ cd $HOME/emgo
  2. $ ./clean.sh
  3. $ cd $HOME/firstemgo
  4. $ egc -nf -nt
  5. $ arm-none-eabi-size cortexm0.elf
  6. text data bss dec hex filename
  7. 10272 196 212 10680 29b8 cortexm0.elf

讓我們加載這個(gè)程序,看看它是否按預(yù)期工作。這一次我們將使用 st-flash 命令:

 
 
 
 
  1. $ arm-none-eabi-objcopy -O binary cortexm0.elf cortexm0.bin
  2. $ st-flash write cortexm0.bin 0x8000000
  3. st-flash 1.4.0-33-gd76e3c7
  4. 2018-04-10T22:04:34 INFO usb.c: -- exit_dfu_mode
  5. 2018-04-10T22:04:34 INFO common.c: Loading device parameters....
  6. 2018-04-10T22:04:34 INFO common.c: Device connected is: F0 small device, id 0x10006444
  7. 2018-04-10T22:04:34 INFO common.c: SRAM size: 0x1000 bytes (4 KiB), Flash: 0x4000 bytes (16 KiB) in pages of 1024 bytes
  8. 2018-04-10T22:04:34 INFO common.c: Attempting to write 10468 (0x28e4) bytes to stm32 address: 134217728 (0x8000000)
  9. Flash page at addr: 0x08002800 erased
  10. 2018-04-10T22:04:34 INFO common.c: Finished erasing 11 pages of 1024 (0x400) bytes
  11. 2018-04-10T22:04:34 INFO common.c: Starting Flash write for VL/F0/F3/F1_XL core id
  12. 2018-04-10T22:04:34 INFO flash_loader.c: Successfully loaded flash loader in sram
  13. 11/11 pages written
  14. 2018-04-10T22:04:35 INFO common.c: Starting verification of write complete
  15. 2018-04-10T22:04:35 INFO common.c: Flash written and verified! jolly good!
  16.  

我沒有將 NRST 信號(hào)連接到編程器,因此無法使用 -reset 選項(xiàng),必須按下復(fù)位按鈕才能運(yùn)行程序。

Interfaces

看來,st-flash 與此板配合使用有點(diǎn)不可靠(通常需要復(fù)位 ST-LINK 加密狗)。此外,當(dāng)前版本不會(huì)通過 SWD 發(fā)出復(fù)位命令(僅使用 NRST 信號(hào))。軟件復(fù)位是不現(xiàn)實(shí)的,但是它通常是有效的,缺少它會(huì)將會(huì)帶來不便。對(duì)于板卡程序員board-programmer 來說 OpenOCD 工作得更好。

UART

UART(通用異步收發(fā)傳輸器Universal Aynchronous Receiver-Transmitter)仍然是當(dāng)今微控制器最重要的外設(shè)之一。它的優(yōu)點(diǎn)是以下屬性的獨(dú)特組合:

  • 相對(duì)較高的速度,
  • 僅兩條信號(hào)線(在 半雙工half-duplex 通信的情況下甚至一條),
  • 角色對(duì)稱,
  • 關(guān)于新數(shù)據(jù)的 同步帶內(nèi)信令synchronous in-band signaling(起始位),
  • 在傳輸 字words 內(nèi)的精確計(jì)時(shí)。

這使得最初用于傳輸由 7-9 位的字組成的異步消息的 UART,也被用于有效地實(shí)現(xiàn)各種其他物理協(xié)議,例如被 WS28xx LEDs 或 1-wire 設(shè)備使用的協(xié)議。

但是,我們將以其通常的角色使用 UART:從程序中打印文本消息。

 
 
 
 
  1. package main
  2.  
  3. import (
  4. "io"
  5. "rtos"
  6.  
  7. "stm32/hal/dma"
  8. "stm32/hal/gpio"
  9. "stm32/hal/irq"
  10. "stm32/hal/system"
  11. "stm32/hal/system/timer/systick"
  12. "stm32/hal/usart"
  13. )
  14.  
  15. var tts *usart.Driver
  16.  
  17. func init() {
  18. system.SetupPLL(8, 1, 48/8)
  19. systick.Setup(2e6)
  20.  
  21. gpio.A.EnableClock(true)
  22. tx := gpio.A.Pin(9)
  23.  
  24. tx.Setup(&gpio.Config{Mode: gpio.Alt})
  25. tx.SetAltFunc(gpio.USART1_AF1)
  26. d := dma.DMA1
  27. d.EnableClock(true)
  28. tts = usart.NewDriver(usart.USART1, d.Channel(2, 0), nil, nil)
  29. tts.Periph().EnableClock(true)
  30. tts.Periph().SetBaudRate(115200)
  31. tts.Periph().Enable()
  32. tts.EnableTx()
  33.  
  34. rtos.IRQ(irq.USART1).Enable()
  35. rtos.IRQ(irq.DMA1_Channel2_3).Enable()
  36. }
  37.  
  38. func main() {
  39. io.WriteString(tts, "Hello, World!\r\n")
  40. }
  41.  
  42. func ttsISR() {
  43. tts.ISR()
  44. }
  45.  
  46. func ttsDMAISR() {
  47. tts.TxDMAISR()
  48. }
  49.  
  50. //c:__attribute__((section(".ISRs")))
  51. var ISRs = [...]func(){
  52. irq.USART1: ttsISR,
  53. irq.DMA1_Channel2_3: ttsDMAISR,
  54. }
  55.  

你會(huì)發(fā)現(xiàn)此代碼可能有些復(fù)雜,但目前 STM32 HAL 中沒有更簡單的 UART 驅(qū)動(dòng)程序(在某些情況下,簡單的輪詢驅(qū)動(dòng)程序可能會(huì)很有用)。 usart.Driver 是使用 DMA 和中斷來減輕 CPU 負(fù)擔(dān)的高效驅(qū)動(dòng)程序。

STM32 USART 外設(shè)提供傳統(tǒng)的 UART 及其同步版本。要將其用作輸出,我們必須將其 Tx 信號(hào)連接到正確的 GPIO 引腳:

 
 
 
 
  1. tx.Setup(&gpio.Config{Mode: gpio.Alt})
  2. tx.SetAltFunc(gpio.USART1_AF1)

在 Tx-only 模式下配置 usart.Driver (rxdma 和 rxbuf 設(shè)置為 nil):

 
 
 
 
  1. tts = usart.NewDriver(usart.USART1, d.Channel(2, 0), nil, nil)

我們使用它的 WriteString 方法來打印這句名言。讓我們清理所有內(nèi)容并編譯該程序:

 
 
 
 
  1. $ cd $HOME/emgo
  2. $ ./clean.sh
  3. $ cd $HOME/firstemgo
  4. $ egc
  5. $ arm-none-eabi-size cortexm0.elf
  6. text data bss dec hex filename
  7. 12728 236 176 13140 3354 cortexm0.elf

要查看某些內(nèi)容,你需要在 PC 中使用 UART 外設(shè)。

請(qǐng)勿使用 RS232 端口或 USB 轉(zhuǎn) RS232 轉(zhuǎn)換器!

STM32 系列使用 3.3V 邏輯,但是 RS232 可以產(chǎn)生 -15 V ~ +15 V 的電壓,這可能會(huì)損壞你的 MCU。你需要使用 3.3V 邏輯的 USB 轉(zhuǎn) UART 轉(zhuǎn)換器。流行的轉(zhuǎn)換器基于 FT232 或 CP2102 芯片。

UART

你還需要一些終端仿真程序(我更喜歡 picocom)。刷新新圖像,運(yùn)行終端仿真器,然后按幾次復(fù)位按鈕:

 
 
 
 
  1. $ openocd -d0 -f interface/stlink.cfg -f target/stm32f0x.cfg -c 'init; program cortexm0.elf; reset run; exit'
  2. Open On-Chip Debugger 0.10.0+dev-00319-g8f1f912a (2018-03-07-19:20)
  3. Licensed under GNU GPL v2
  4. For bug reports, read
  5. http://openocd.org/doc/doxygen/bugs.html
  6. debug_level: 0
  7. adapter speed: 1000 kHz
  8. adapter_nsrst_delay: 100
  9. none separate
  10. adapter speed: 950 kHz
  11. target halted due to debug-request, current mode: Thread
  12. xPSR: 0xc1000000 pc: 0x080016f4 msp: 0x20000a20
  13. adapter speed: 4000 kHz
  14. ** Programming Started **
  15. auto erase enabled
  16. target halted due to breakpoint, current mode: Thread
  17. xPSR: 0x61000000 pc: 0x2000003a msp: 0x20000a20
  18. wrote 13312 bytes from file cortexm0.elf in 1.020185s (12.743 KiB/s)
  19. ** Programming Finished **
  20. adapter speed: 950 kHz
  21. $
  22. $ picocom -b 115200 /dev/ttyUSB0
  23. picocom v3.1
  24.  
  25. port is : /dev/ttyUSB0
  26. flowcontrol : none
  27. baudrate is : 115200
  28. parity is : none
  29. databits are : 8
  30. stopbits are : 1
  31. escape is : C-a
  32. local echo is : no
  33. noinit is : no
  34. noreset is : no
  35. hangup is : no
  36. nolock is : no
  37. send_cmd is : sz -vv
  38. receive_cmd is : rz -vv -E
  39. imap is :
  40. omap is :
  41. emap is : crcrlf,delbs,
  42. logfile is : none
  43. initstring : none
  44. exit_after is : not set
  45. exit is : no
  46.  
  47. Type [C-a] [C-h] to see available commands
  48. Terminal ready
  49. Hello, World!
  50. Hello, World!
  51. Hello, World!

每次按下復(fù)位按鈕都會(huì)產(chǎn)生新的 “Hello,World!”行。一切都在按預(yù)期進(jìn)行。

要查看此 MCU 的 雙向bi-directional UART 代碼,請(qǐng)查看 此示例。

io.Writer 接口

io.Writer 接口可能是 Go 中第二種最常用的接口類型,僅次于 error 接口。其定義如下所示:

 
 
 
 
  1. type Writer interface {
  2. Write(p []byte) (n int, err error)
  3. }

usart.Driver 實(shí)現(xiàn)了 io.Writer,因此我們可以替換:

 
 
 
 
  1. tts.WriteString("Hello, World!\r\n")

 
 
 
 
  1. io.WriteString(tts, "Hello, World!\r\n")

此外,你需要將 io 包添加到 import 部分。

io.WriteString 函數(shù)的聲明如下所示:

 
 
 
 
  1. func WriteString(w Writer, s string) (n int, err error)

如你所見,io.WriteString 允許使用實(shí)現(xiàn)了 io.Writer 接口的任何類型來編寫字符串。在內(nèi)部,它檢查基礎(chǔ)類型是否具有 WriteString 方法,并使用該方法代替 Write(如果可用)。

讓我們編譯修改后的程序:

 
 
 
 
  1. $ egc
  2. $ arm-none-eabi-size cortexm0.elf
  3. text data bss dec hex filename
  4. 15456 320 248 16024 3e98 cortexm0.elf

如你所見,io.WriteString 導(dǎo)致二進(jìn)制文件的大小顯著增加:15776-12964 = 2812 字節(jié)。 Flash 上沒有太多空間了。是什么引起了這么大規(guī)模的增長?

使用這個(gè)命令:

 
 
 
 
  1. arm-none-eabi-nm --print-size --size-sort --radix=d cortexm0.elf

我們可以打印兩種情況下按其大小排序的所有符號(hào)。通過過濾和分析獲得的數(shù)據(jù)(awkdiff),我們可以找到大約 80 個(gè)新符號(hào)。最大的十個(gè)如下所示:

 
 
 
 
  1. > 00000062 T stm32$hal$usart$Driver$DisableRx
  2. > 00000072 T stm32$hal$usart$Driver$RxDMAISR
  3. > 00000076 T internal$Type$Implements
  4. > 00000080 T stm32$hal$usart$Driver$EnableRx
  5. > 00000084 t errors$New
  6. > 00000096 R $8$stm32$hal$usart$Driver$$
  7. > 00000100 T stm32$hal$usart$Error$Error
  8. > 00000360 T io$WriteString
  9. > 00000660 T stm32$hal$usart$Driver$Read

因此,即使我們不使用 usart.Driver.Read 方法,但它被編譯進(jìn)來了,與 DisableRx、RxDMAISREnableRx 以及上面未提及的其他方法一樣。不幸的是,如果你為接口賦值了一些內(nèi)容,就需要它的完整方法集(包含所有依賴項(xiàng))。對(duì)于使用大多數(shù)方法的大型程序來說,這不是問題。但是對(duì)于我們這種極簡的情況而言,這是一個(gè)巨大的負(fù)擔(dān)。

我們已經(jīng)接近 MCU 的極限,但讓我們嘗試打印一些數(shù)字(你需要在 import 部分中用 strconv 替換 io 包):

 
 
 
 
  1. func main() {
  2. a := 12
  3. b := -123
  4.  
  5. tts.WriteString("a = ")
  6. strconv.WriteInt(tts, a, 10, 0, 0)
  7. tts.WriteString("\r\n")
  8. tts.WriteString("b = ")
  9. strconv.WriteInt(tts, b, 10, 0, 0)
  10. tts.WriteString("\r\n")
  11.  
  12. tts.WriteString("hex(a) = ")
  13. strconv.WriteInt(tts, a, 16, 0, 0)
  14. tts.WriteString("\r\n")
  15. tts.WriteString("hex(b) = ")
  16. strconv.WriteInt(tts, b, 16, 0, 0)
  17. tts.WriteString("\r\n")
  18. }

與使用 io.WriteString 函數(shù)的情況一樣,strconv.WriteInt 的第一個(gè)參數(shù)的類型為 io.Writer

 
 
 
 
  1. $ egc
  2. /usr/local/arm/bin/arm-none-eabi-ld: /home/michal/firstemgo/cortexm0.elf section `.rodata' will not fit in region `Flash'
  3. /usr/local/arm/bin/arm-none-eabi-ld: region `Flash' overflowed by 692 bytes
  4. exit status 1

這一次我們的空間超出的不多。讓我們?cè)囍喴幌掠嘘P(guān)類型的信息:

 
 
 
 
  1. $ cd $HOME/emgo
  2. $ ./clean.sh
  3. $ cd $HOME/firstemgo
  4. $ egc -nf -nt
  5. $ arm-none-eabi-size cortexm0.elf
  6. text data bss dec hex filename
  7. 15876 316 320 16512 4080 cortexm0.elf

很接近,但很合適。讓我們加載并運(yùn)行此代碼:

 
 
 
 
  1. a = 12
  2. b = -123
  3. hex(a) = c
  4. hex(b) = -7b

Emgo 中的 strconv 包與 Go 中的原型有很大的不同。它旨在直接用于寫入格式化的數(shù)字,并且在許多情況下可以替換沉重的 fmt 包。 這就是為什么函數(shù)名稱以 Write 而不是 Format 開頭,并具有額外的兩個(gè)參數(shù)的原因。 以下是其用法示例:

 
 
 
 
  1. func main() {
  2. b := -123
  3. strconv.WriteInt(tts, b, 10, 0, 0)
  4. tts.WriteString("\r\n")
  5. strconv.WriteInt(tts, b, 10, 6, ' ')
  6. tts.WriteString("\r\n")
  7. strconv.WriteInt(tts, b, 10, 6, '0')
  8. tts.WriteString("\r\n")
  9. strconv.WriteInt(tts, b, 10, 6, '.')
  10. tts.WriteString("\r\n")
  11. strconv.WriteInt(tts, b, 10, -6, ' ')
  12. tts.WriteString("\r\n")
  13. strconv.WriteInt(tts, b, 10, -6, '0')
  14. tts.WriteString("\r\n")
  15. strconv.WriteInt(tts, b, 10, -6, '.')
  16. tts.WriteString("\r\n")
  17. }

下面是它的輸出:

 
 
 
 
  1. -123
  2. -123
  3. -00123
  4. ..-123
  5. -123
  6. -123
  7. -123..

Unix 流 和 莫爾斯電碼Morse code

由于大多數(shù)寫入的函數(shù)都使用 io.Writer 而不是具體類型(例如 C 中的 FILE ),因此我們獲得了類似于 Unix 流stream 的功能。在 Unix 中,我們可以輕松地組合簡單的命令來執(zhí)行更大的任務(wù)。例如,我們可以通過以下方式將文本寫入文件:

 
 
 
 
  1. echo "Hello, World!" > file.txt

> 操作符將前面命令的輸出流寫入文件。還有 | 操作符,用于連接相鄰命令的輸出流和輸入流。

多虧了流,我們可以輕松地轉(zhuǎn)換/過濾任何命令的輸出。例如,要將所有字母轉(zhuǎn)換為大寫,我們可以通過 tr 命令過濾 echo 的輸出:

 
 
 
 
  1. echo "Hello, World!" | tr a-z A-Z > file.txt

為了顯示 io.Writer 和 Unix 流之間的類比,讓我們編寫以下代碼:

 
 
 
 
  1. io.WriteString(tts, "Hello, World!\r\n")

采用以下偽 unix 形式:

 
 
 
 
  1. io.WriteString "Hello, World!" | usart.Driver usart.USART1

下一個(gè)示例將顯示如何執(zhí)行此操作:

 
 
 
 
  1. io.WriteString "Hello, World!" | MorseWriter | usart.Driver usart.USART1

讓我們來創(chuàng)建一個(gè)簡單的編碼器,它使用莫爾斯電碼對(duì)寫入的文本進(jìn)行編碼:

 
 
 
 
  1. type MorseWriter struct {
  2. W io.Writer
  3. }
  4.  
  5. func (w *MorseWriter) Write(s []byte) (int, error) {
  6. var buf [8]byte
  7. for n, c := range s {
  8. switch {
  9. case c == '\n':
  10. c = ' ' // Replace new lines with spaces.
  11. case 'a' <= c && c <= 'z':
  12. c -= 'a' - 'A' // Convert to upper case.
  13. }
  14. if c < ' ' || 'Z' < c {
  15. continue // c is outside ASCII [' ', 'Z']
  16. }
  17. var symbol morseSymbol
  18. if c == ' ' {
  19. symbol.length = 1
  20. buf[0] = ' '
  21. } else {
  22. symbol = morseSymbols[c-'!']
  23. for i := uint(0); i < uint(symbol.length); i++ {
  24. if (symbol.code>>i)&1 != 0 {
  25. buf[i] = '-'
  26. } else {
  27. buf[i] = '.'
  28. }
  29. }
  30. }
  31. buf[symbol.length] = ' '
  32. if _, err := w.W.Write(buf[:symbol.length+1]); err != nil {
  33. return n, err
  34. }
  35. }
  36. return len(s), nil
  37. }
  38.  
  39. type morseSymbol struct {
  40. code, length byte
  41. }
  42.  
  43. //emgo:const
  44. var morseSymbols = [...]morseSymbol{
  45. {1<<0 | 1<<1 | 1<<2, 4}, // ! ---.
  46. {1<<1 | 1<<4, 6}, // " .-..-.
  47. {}, // #
  48. {1<<3 | 1<<6, 7}, // $ ...-..-
  49.  
  50. // Some code omitted...
  51.  
  52. {1<<0 | 1<<3, 4}, // X -..-
  53. {1<<0 | 1<<2 | 1<<3, 4}, // Y -.--
  54. {1<<0 | 1<<1, 4}, // Z --..
  55. }

你可以在 這里 找到完整的 
分享標(biāo)題:Go語言在極小硬件上的運(yùn)用(二)
文章地址:http://www.dlmjj.cn/article/ccsjgde.html