FrontPage > マイクロコントローラ > AVRの覚書

キャラクタLCDへの表示

ATmega328PへキャラクタLCDを接続し、文字列を表示してみる。

  • 使用するLCDはSC2004CBWB-XA-GB(秋月電子で購入)
  • LCDは付属の説明書に従って、基盤裏面のジャンパーポイント「J2」を半田ショートし、
    パターン「R8」に付属の抵抗2本を並列に半田付けしておく。

1. 回路図

マイコン周りの回路はATmega328Pテスト用ボード参照。

  • 図のようにマイコンと接続する。LCDはデータ長4bitモードで使用する。
  • ディスプレイのコントラスト調整用に可変抵抗を接続する。
    AVR_LCD_回路図.png

2. プログラム

  • ヘッダファイル
    (lcd.h)
    #ifndef LCD_H_INCLUDED
    #define LCD_H_INCLUDED
    
    // Command Instruction code定義
    #define LCD_CLEAR			0b00000001
    #define LCD_RTN_HOME		0b00000010
    
    #define LCD_ENTRY			0b00000100
    #define LCD_ENTRY_ID_DEC	0b0000
    #define LCD_ENTRY_ID_INC	0b0010
    #define LCD_ENTRY_S_NO		0b0000
    #define LCD_ENTRY_S_YES		0b0001
    
    #define LCD_DISPLAY			0b00001000
    #define LCD_DISP_OFF		0b0000
    #define LCD_DISP_ON			0b0100
    #define LCD_DISP_CUR_OFF	0b0000
    #define LCD_DISP_CUR_ON		0b0010
    #define LCD_DISP_BLK_OFF	0b0000
    #define LCD_DISP_BLK_ON		0b0001
    
    #define LCD_FUNCTION_DL_8	0b00110000
    #define LCD_FUNCTION_DL_4	0b00100000
    #define LCD_FUNCTION		LCD_FUNCTION_DL_4	// データ長4bitで使用
    #define LCD_FUNCTION_N_1	0b0000
    #define LCD_FUNCTION_N_2	0b1000
    #define LCD_FUNCTION_F_5x8	0b0000
    #define LCD_FUNCTION_F_5x11	0b0100
    
    #define LCD_DD_ADDR			0b10000000
    
    // 接続情報
    #define LCD_PORT_CTRL	PORTD	// E,RS,R/W信号に使用するポートを指定
    #define LCD_PORT_DATA	PORTD	// データーポートを指定
    #define LCD_DDR_CTRL	DDRD	// E,RS,R/W信号に使用するポートのDDR
    #define LCD_DDR_DATA	DDRD	// データーポートのDDR
    #define	LCD_BIT_E		0b01000000	// Enableビット指定
    #define LCD_BIT_RS		0b00100000	// Register Selectビット指定
    #define LCD_BIT_RW		0b00010000	// R/Wビット指定
    #define LCD_BIT_DATA	0b00001111	// データビット指定
    
    // Register Select
    #define LCD_RS_CTRL	~LCD_BIT_RS
    #define LCD_RS_DATA	LCD_BIT_RS
    
    // LCDに対するデータ出力
    void lcd_write_(unsigned char, unsigned char);
    
    // LCDに対するデータ出力(4bit長用)
    void lcd_write(unsigned char, unsigned char);
    
    // LCDデータ長4bit指定
    void lcd_setDL4Bit();
    
    // LCD Entry Mode
    void lcd_entryMode(unsigned char);
    
    // LCD Display Set
    void lcd_display(unsigned char);
    
    // LCD Clear Display
    void lcd_clear();
    
    // LCD Function Set
    void lcd_setFunction(unsigned char);
    
    // カーソル移動
    void lcd_moveCursor(unsigned char, unsigned char);
    
    // LCD初期化
    void lcd_init();
    
    // LCD 文字列表示
    void lcd_print(char*);
    
    // 数値を表示する(2Byte)
    void lcd_printInt(unsigned int);
    
    // 数値を表示する(1Byte)
    void lcd_printByte(unsigned char);
    
    #endif // LCD_H_INCLUDED
    

  • LCD表示用ソース
    (lcd.c)
    #ifndef F_CPU
    #define F_CPU 16000000UL	// 動作周波数に16MHzを指定
    #endif
    
    #include <avr/io.h>
    #include <util/delay.h>
    #include "lcd.h"
    
    // LCD 行に対応するDDRAM開始アドレス
    const unsigned char lcd_ddram_addr_row[] = {0x0, 0x40, 0x14, 0x54};
    
    /************************************************************************/
    /* LCDに対するデータ出力                                                */
    /************************************************************************/
    void lcd_write_(unsigned char rs, unsigned char data) {
    	// R/W -> W
    	LCD_PORT_CTRL &= ~LCD_BIT_RW;
    	
    	// RSをセット
    	if (rs == LCD_RS_DATA) {
    		LCD_PORT_CTRL |= rs;
    	} else {
    		LCD_PORT_CTRL &= rs;
    	}
    	
    	// E -> H
    	LCD_PORT_CTRL |= LCD_BIT_E;
    	
    	// データ出力
    	LCD_PORT_DATA = (LCD_PORT_DATA & ~LCD_BIT_DATA) | (data & LCD_BIT_DATA);
    
    	// E -> L
    	LCD_PORT_CTRL &= ~LCD_BIT_E;
    }
    
    /************************************************************************/
    /* LCDに対するデータ出力(4bit長)                                        */
    /************************************************************************/
    void lcd_write(unsigned char rs, unsigned char data) {
    	lcd_write_(rs, data >> 4);
    	_delay_us(50);
    	lcd_write_(rs, data);
    }
    
    /************************************************************************/
    /* LCDデータ長4bit指定                                                  */
    /************************************************************************/
    void lcd_setDL4Bit() {
    	// 4bit mode
    
    	lcd_write_(LCD_RS_CTRL, LCD_FUNCTION_DL_8 >> 4);
    	_delay_ms(5);
    	lcd_write_(LCD_RS_CTRL, LCD_FUNCTION_DL_8 >> 4);
    	_delay_us(150);
    	
    	lcd_write_(LCD_RS_CTRL, LCD_FUNCTION_DL_8 >> 4);
    	_delay_us(50);
    
    	lcd_write_(LCD_RS_CTRL, LCD_FUNCTION_DL_4 >> 4);
    	_delay_us(50);
    }
    
    /************************************************************************/
    /* LCD Entry Mode                                                       */
    /************************************************************************/
    void lcd_entryMode(unsigned char data) {
    	lcd_write(LCD_RS_CTRL, LCD_ENTRY | data);
    	_delay_us(50);
    }
    
    /************************************************************************/
    /* LCD Display Set                                                      */
    /************************************************************************/
    void lcd_display(unsigned char data) {
    	lcd_write(LCD_RS_CTRL, LCD_DISPLAY | data);
    	_delay_us(50);
    }
    
    /************************************************************************/
    /* LCD Clear Display                                                    */
    /************************************************************************/
    void lcd_clear() {
    	lcd_write(LCD_RS_CTRL, LCD_CLEAR);
    	_delay_ms(5);
    }
    
    /************************************************************************/
    /* LCD Function Set                                                     */
    /************************************************************************/
    void lcd_setFunction(unsigned char data) {
    
    	lcd_write(LCD_RS_CTRL, LCD_FUNCTION | data);
    	_delay_us(50);
    }
    
    /************************************************************************/
    /* カーソル移動                                                         */
    /************************************************************************/
    void lcd_moveCursor(unsigned char col, unsigned char row) {
    	unsigned char addr = lcd_ddram_addr_row[row] + col;
    	lcd_write(LCD_RS_CTRL, LCD_DD_ADDR | addr);
    	_delay_us(50);
    }
    
    /************************************************************************
     * LCD初期化
     * 4bit Mode
     ************************************************************************/
    void lcd_init() {
    	// LCDで使用するポートのビットを出力に指定
    	LCD_DDR_CTRL = LCD_DDR_CTRL | LCD_BIT_E | LCD_BIT_RS | LCD_BIT_RW;
    	LCD_DDR_DATA = LCD_DDR_CTRL | LCD_BIT_DATA;
    	_delay_ms(50);
    
    	// データ長4bit指定
    	lcd_setDL4Bit();
    	// Functionセット display line = 2, font = 5x8dots
    	lcd_setFunction(LCD_FUNCTION_N_2 | LCD_FUNCTION_F_5x8);
    	// Displayセット 
    	lcd_display(LCD_DISP_ON | LCD_DISP_CUR_OFF | LCD_DISP_BLK_OFF);
    	// Clear Display
    	lcd_clear();
    	// Entry Mode カーソル移動方向 = Increment, Display shift = disable
    	lcd_entryMode(LCD_ENTRY_ID_INC | LCD_ENTRY_S_NO);
    }
    
    /************************************************************************/
    /* LCD 文字列出力                                                       */
    /************************************************************************/
    void lcd_print(char* str) {
    	for (int i = 0; str[i]; i++) {
    		lcd_write(LCD_RS_DATA, str[i]);
    		_delay_us(50);
    	}
    }
    // 数字に対応するキャラクタコード
    char lcd_numChars[] = {"0123456789ABCDEF"};
    /************************************************************************/
    /* 数値を表示する(2Byte)                                                */
    /************************************************************************/
    void lcd_printInt(unsigned int num) {
    		lcd_printByte(num >> 8);
    		lcd_printByte(num & 0x00FF);
    }
    /************************************************************************/
    /* 数値を表示する(1Byte)                                                */
    /************************************************************************/
    void lcd_printByte(unsigned char byte) {
    	lcd_write(LCD_RS_DATA, lcd_numChars[byte >> 4]);
    	_delay_us(50);
    	lcd_write(LCD_RS_DATA, lcd_numChars[byte & 0x0F]);
    	_delay_us(50);
    }
    

  • メイン
    (LCD_test.c)
    #ifndef F_CPU
    #define F_CPU 16000000UL	// 動作周波数に16MHzを指定
    #endif
    
    #include <avr/io.h>
    #include <util/delay.h>
    #include "lcd.h"
    
    
    /************************************************************************/
    /* Main                                                                 */
    /************************************************************************/
    int main(void)
    {
    	lcd_init();
    	lcd_print("Hello");
    	
    	lcd_moveCursor(0,1);
    	lcd_print("LCD");
    
    	lcd_moveCursor(0,2);
    	lcd_print("World !");
    	
    	lcd_moveCursor(0,3);
    	lcd_printByte(0b11111111);
     
        while(1)
        {
            //TODO:: Please write your application code 
        }
    }
    

3. ヒューズビット設定

今回は外部クロック16MHzを分周なしで使用するので、Atmel Studioの
Device Programming画面のFuses設定より、「SUT_CKSEL」に
「EXTXOSC_8MHZ_XX_16KCK_14CK_65MS」を選択。

4. 実行結果

AVR_LCD.jpg





添付ファイル: fileAVR_LCD.jpg 250件 [詳細] fileAVR_LCD_回路図.png 354件 [詳細]

トップ   編集 凍結解除 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2015-07-10 (金) 01:47:08 (833d)