編集履歴一覧に戻る
keiske-hongyoのアイコン画像

keiske-hongyo が 2021年12月26日12時58分26秒 に編集

コメント無し

記事種類の変更

+

セットアップや使用方法

ライセンスの変更

+

(GPL-3.0+) GNU General Public License, version 3

本文の変更

## 1  初めに

-

 マイコンを使用したものを作るときに、状態など表示させたいときにキャラクタ液晶を使うことが多いと思います。しかし、Seeed Xaioのような小型のマイコンはピン数に制限があり、キャラクタ液晶のように多くのピン数を使うと液晶制御以外何もできなくなります。そこで、LCDの制御で利用するピン数を少なくするために74HC595を使用した液晶表示回路と制御プログラムの作成に取り組んでみました。

+

 マイコンを使用したものを作るときに、状態など表示させたいときにキャラクタ液晶を使うことが多いと思います。しかし、Seeed Xiaoのような小型のマイコンはピン数に制限があり、キャラクタ液晶のように多くのピン数を使うと液晶制御以外何もできなくなります。そこで、LCDの制御で利用するピン数を少なくするために74HC595を使用した液晶表示回路と制御プログラムの作成に取り組んでみました。

## 2 使用部品と回路について ### 2.1 使用部品  今回の回路には表1に示す部品を使用しました。 |使用部品|名称|備考| |---|---|---| |マイコン|Seeeduino Xiao|| |LCD|SD1602HULB-XA-G-G|16文字x2行| |IC|74HC595|シフトレジスタ(シリアルイン-パラレルアウト)| |抵抗|200Ω|バックライト用| |半固定抵抗|20kΩ|明るさ調整用| ### 2.2 回路について  回路図を下に示します。 ![LCD制御回路図](https://camo.elchika.com/85c6bbec778b225f1675092656852672cf193e44/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f33646164353039642d616133622d343132302d616433622d6638623565376137366139332f64653332323230362d376362632d346630632d396362332d303430373961633938356333/)  今回の回路に74HC595を使用しています。74HC595はシリアル入力からパラレル出力に変換できるシフトレジスタ回路のロジックICです。私も出力が多く必要なときに、よく利用しています。Enableピンだけは、LCDのレジスタ等の書き込みで使用するので別のピンにして制御するようにしました。  また、LCDのデータは4ビットモードで使用するようにしています。 ## 3 使用するマイコンとプログラムについて

-

 今回使用するマイコンはSeeed Xaioを使用します。また、プログラム言語としてtinygoを使用します。もし、tinygoの開発環境がわからない時は、[前回公開したもの](https://elchika.com/article/70406aa9-0997-4b9e-a714-87ba21d7b0c9/)を参考にしてください。

+

 今回使用するマイコンはSeeed Xiaoを使用します。また、プログラム言語としてtinygoを使用します。もし、tinygoの開発環境がわからない時は、[前回公開したもの](https://elchika.com/article/70406aa9-0997-4b9e-a714-87ba21d7b0c9/)を参考にしてください。

今回のディレクトリは下の図のようになります。 ![ディレクトリ構成](https://camo.elchika.com/575305e5778f9b068066f0acabaeb90651e1c707/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f33646164353039642d616133622d343132302d616433622d6638623565376137366139332f61316231306465642d356137612d346238392d623739372d646331323430313435626533/)  まず、始めに作業用のフォルダを作成し、Visual Studio Codeからフォルダを開いてください。今回はLCDとしています。  次に自作モジュールを使うので作業用のフォルダの中に各モジュールをフォルダを作成します。ShiftOutが74HC595の制御モジュール用、Lcd_74hc959がキャラクタ液晶用のフォルダです。その中に各モジュールのプログラムを作成します。ShiftOut.goは74HC595の制御プログラムで、lcd_74hc595.goとregister.goがLCD制御関係のプログラムとレジスタの定義ファイルになります。作業用のディレクトリにあるmain.goが動作テストプログラムです。  最後に自作モジュールで作成して、プログラムを行うので下に示すコマンドで、go.modファイルを作成します。最後のLCDはフォルダ名なので、作成したフォルダに合わせて変更してください。 ```cmd:go.modの作成 go mod init LCD go mod tidy ``` 各プログラムは次のようになります。 ```golang:ShiftOut.go(74HC595制御プログラム) package ShiftOut import ( "machine" ) type ShiftOut struct { ser machine.Pin // データ入力ピン rclk machine.Pin // ラッチ srclk machine.Pin // シフトレジスタクロック } // New -> 74HC595 初期化関数 /* (74HC595) Serial Data -> ser RCK -> rclk Shift register Clock -> srclk */ func New(ser machine.Pin, rclk machine.Pin, srclk machine.Pin) ShiftOut { /* 構造体の宣言 */ shft := ShiftOut{} /* 構造体に格納 */ shft.ser = ser shft.rclk = rclk shft.srclk = srclk /* 各ピンの設定 */ shft.ser.Configure(machine.PinConfig{Mode: machine.PinOutput}) shft.rclk.Configure(machine.PinConfig{Mode: machine.PinOutput}) shft.srclk.Configure(machine.PinConfig{Mode: machine.PinOutput}) return shft } // OutPutData /* 8bitデータ出力関数 */ /* OutPutData(出力データ) */ func (shft *ShiftOut) OutPutData(outdata uint8) { // データ出力 shft.rclk.Low() // 送信中はラッチをLowに設定 /* 出力データ設定処理 */ for i := 0; i < 8; i++ { // 出力データの確認 if (outdata & (1 << i)) != 0x00 { shft.ser.High() // 1 -> High } else { shft.ser.Low() // 0 -> Low } // データ書き込み shft.srclk.High() shft.srclk.Low() } shft.rclk.High() // 送信中はラッチをLowに設定 } ``` ```golang:lcd_74hc595.go(LCD制御プログラム) package Lcd_74hc595 import ( "LCD/ShiftOut" "machine" "time" ) type Lcd struct { shft ShiftOut.ShiftOut enable machine.Pin col uint8 // 列数 row uint8 // 行数 } func New(col uint8,row uint8, shft ShiftOut.ShiftOut, en machine.Pin) Lcd { lcd := Lcd{} lcd.shft = shft lcd.enable = en lcd.col = col lcd.row = row return lcd } // lcd初期化関数 func (l *Lcd) Init() { Command(l.shft, l.enable, 0x03) time.Sleep(40 * time.Millisecond) Command(l.shft, l.enable, 0x03) time.Sleep(5 * time.Millisecond) Command(l.shft, l.enable, 0x03) time.Sleep(5 * time.Millisecond) Command(l.shft, l.enable, 0x02) time.Sleep(5 * time.Millisecond) Command(l.shft, l.enable,LCD_FUNCTIONSET | LCD_4BITMODE | LCD_2LINE | LCD_5x8DOTS) Command(l.shft, l.enable,LCD_DISPLAYCONTROL | LCD_DISPLAYOFF) Command(l.shft, l.enable,LCD_CLEARDISPLAY) time.Sleep(40 * time.Millisecond) Command(l.shft, l.enable,LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT) Command(l.shft, l.enable, LCD_DISPLAYCONTROL | LCD_DISPLAYON) time.Sleep(40 * time.Millisecond) } /* 液晶に1文字出力 */ func (l *Lcd) Print(s string) { for _, c := range s { outputchar(l.shft, l.enable, uint8(c)) } } /* 液晶クリア */ func (l *Lcd) Clear() { Command(l.shft, l.enable,LCD_CLEARDISPLAY) } /* 液晶クリア */ func (l *Lcd) Home() { Command(l.shft, l.enable,LCD_RETURNHOME) } /* 液晶クリア */ func (l *Lcd) Locate(col uint8 ,row uint8) { var offset uint8 if row >= (l.row - 1) { offset = 0x40 } else { offset = 0x00 } Command(l.shft, l.enable,LCD_SETDDRAMADDR | (offset + col)) } // Enable func pluseEnable(en machine.Pin) { en.Low() time.Sleep(1 * time.Microsecond) en.High() time.Sleep(1 * time.Microsecond) en.Low() time.Sleep(1 * time.Microsecond) } // コマンド処理 func Command(s ShiftOut.ShiftOut, en machine.Pin, data uint8) { s.OutPutData(rs_low + (data>>4)&0x0f) pluseEnable(en) s.OutPutData(rs_low + (data)&0x0f) pluseEnable(en) } // 表示処理 func outputchar(s ShiftOut.ShiftOut, en machine.Pin, data uint8) { s.OutPutData(rs_high + (data>>4)&0x0f) pluseEnable(en) s.OutPutData(rs_high + (data)&0x0f) pluseEnable(en) } ``` ```golang:register.go(LCDレジスタ定義ファイル) package Lcd_74hc595 const ( rs_low = 0x00 rs_high = 0x10 LCD_CLEARDISPLAY = 0x01 LCD_RETURNHOME = 0x02 LCD_ENTRYMODESET = 0x04 LCD_DISPLAYCONTROL = 0x08 LCD_CURSORSHIFT = 0x10 LCD_FUNCTIONSET = 0x20 LCD_SETCGRAMADDR = 0x40 LCD_SETDDRAMADDR = 0x80 LCD_ENTRYRIGHT = 0x00 LCD_ENTRYLEFT = 0x02 LCD_ENTRYSHIFTINCREMENT = 0x01 LCD_ENTRYSHIFTDECREMENT = 0x00 LCD_DISPLAYON = 0x04 LCD_DISPLAYOFF = 0x00 LCD_CURSORON = 0x02 LCD_CURSOROFF = 0x00 LCD_BLINKON = 0x01 LCD_BLINKOFF = 0x00 LCD_DISPLAYMOVE = 0x08 LCD_CURSORMOVE = 0x00 LCD_MOVERIGHT = 0x04 LCD_MOVELEFT = 0x00 LCD_8BITMODE = 0x10 LCD_4BITMODE = 0x00 LCD_2LINE = 0x08 LCD_1LINE = 0x00 LCD_5x10DOTS = 0x04 LCD_5x8DOTS = 0x00 ) ``` ```golang:main.go(サンプルプログラム) package main import ( "LCD/Lcd_74hc595" "LCD/ShiftOut" "machine" ) func main() { // Enableピンの設定 enable := machine.D6 enable.Configure(machine.PinConfig{Mode: machine.PinOutput}) // シフトレジスタのの設定 // Ser -> D9 RCLK-> D8 SCLK->D7 shout := ShiftOut.New(machine.D9, machine.D8, machine.D7) lcd := Lcd_74hc595.New(16, 2, shout, enable) lcd.Init() // LCD初期化 lcd.Home() // LCDのカーソルをHome(col=0,row=0)に設定 lcd.Print("Hello World") // 文字出力 lcd.Locate(0, 1) // LCDのカーソルをHome(col=0,row=1)に設定 lcd.Print("Hello TinyGo!") /* 無限ループ */ for { } } ``` ## 4 最後に   74HC595を使用したキャラクタLCDの制御に取り組んでみました。キャラクタLCDはマイコン関係ではよく利用する部品だと思います。この投稿がみなさんの何かの参考になればいいかなぁと思っています。また、tinygoのプログラムにも興味を持っていただけたらうれしいです。  今回は自作モジュールの作成して、活用したり、レシーバを使ったりしているので、プログラムが少し難しいかと思います。他のサイトでGolangについて、調べながらやって見てください。また、Micropython用のプログラムを作成も使用と思っています。完成したら紹介します。