AmazonでI2Cで操作できるLCDモジュールが650円で売ってます。
I2C対応のLCDモジュールでは一番安いのでは?
ArduinoではLiquidCrystal_I2Cというライブラリを使用すれば簡単に動かせます。
今回はこれをPICで動かしました。
PICはPIC24FV32KA302を使用して、MPLABXでコードを書きます。
やりかた
New Projectから空のプロジェクトを作成します。
まずは、MCCを使用してI2C周りの設定を行います。
MCCを開いたら、Device ResourcesからI2C→I2C1[PIC24/dsPIC33/PIC32MM .......]を選択し、Project Resourcesに追加します。
I2Cの詳しい設定はだいたいデフォルトでよかったはず。
一応動いたときのスクショ
ModeはMasterで100kHzね。
Pin ModuleはWPUにチェック。
そしたらProject Resources欄のGenerateをクリックして設定完了。
コード
動いたコードから切り貼りしたので抜けとかあるかも
文句くれればすぐ直す
多分誰もやんないし大丈夫でしょ
LCD.h
#include <stdio.h> #include <stdlib.h> #include <xc.h> // commands #define LCD_CLEARDISPLAY 0x01 #define LCD_RETURNHOME 0x02 #define LCD_ENTRYMODESET 0x04 #define LCD_DISPLAYCONTROL 0x08 #define LCD_CURSORSHIFT 0x10 #define LCD_FUNCTIONSET 0x20 #define LCD_SETCGRAMADDR 0x40 #define LCD_SETDDRAMADDR 0x80 // flags for display entry mode #define LCD_ENTRYRIGHT 0x00 #define LCD_ENTRYLEFT 0x02 #define LCD_ENTRYSHIFTINCREMENT 0x01 #define LCD_ENTRYSHIFTDECREMENT 0x00 // flags for display on/off control #define LCD_DISPLAYON 0x04 #define LCD_DISPLAYOFF 0x00 #define LCD_CURSORON 0x02 #define LCD_CURSOROFF 0x00 #define LCD_BLINKON 0x01 #define LCD_BLINKOFF 0x00 // flags for display/cursor shift #define LCD_DISPLAYMOVE 0x08 #define LCD_CURSORMOVE 0x00 #define LCD_MOVERIGHT 0x04 #define LCD_MOVELEFT 0x00 // flags for function set #define LCD_8BITMODE 0x10 #define LCD_4BITMODE 0x00 #define LCD_2LINE 0x08 #define LCD_1LINE 0x00 #define LCD_5x10DOTS 0x04 #define LCD_5x8DOTS 0x00 // flags for backlight control #define LCD_BACKLIGHT 0x08 #define LCD_NOBACKLIGHT 0x00 #define En 0b00000100 // Enable bit #define Rw 0b00000010 // Read/Write bit #define Rs 0b00000001 // Register select bit #define LCD_ADD 0x27 void LCD_Init(); void begin(uint8_t cols, uint8_t lines, uint8_t dotsize); void display(); void clear(); void home(); void noBacklight(); void backlight(); void setCursor(uint8_t col, uint8_t row); size_t print(const uint8_t *buffer, size_t size); void command(uint8_t value); void send(uint8_t value, uint8_t mode); void write4bits(uint8_t value); void expanderWrite(uint8_t _data); void pulseEnable(uint8_t _data); void printIIC(uint8_t value); inline size_t write(uint8_t value);
LCD.c
#include <stdio.h> #include <stdlib.h> #include <xc.h> #include "LCD.h" #include "defined.h" #include "typedefs.h" #include "mcc_generated_files/i2c1.h" #define FCY 2000000UL #include <libpic30.h> #include "mcc_generated_files/system.h" uint8_t _Addr; uint8_t _displayfunction; uint8_t _displaycontrol; uint8_t _displaymode; uint8_t _numlines; uint8_t _cols; uint8_t _rows; uint8_t _backlightval; I2C1_MESSAGE_STATUS status; void LCD_Init(){ //LCD???? _Addr = LCD_ADD; _cols = 16; _rows = 2; _backlightval = LCD_NOBACKLIGHT; _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; begin(_cols, _rows, LCD_5x8DOTS); } void begin(uint8_t cols, uint8_t lines, uint8_t dotsize) { if (lines > 1) { _displayfunction |= LCD_2LINE; } _numlines = lines; if ((dotsize != 0) && (lines == 1)) { _displayfunction |= LCD_5x10DOTS; } __delay_ms(50); expanderWrite(_backlightval); // backlight off __delay_ms(1000); //put the LCD into 4 bit mode // this is according to the hitachi HD44780 datasheet // figure 24, pg 46 write4bits(0x03 << 4); __delay_us(4500); write4bits(0x03 << 4); __delay_us(4500); write4bits(0x03 << 4); __delay_us(150); write4bits(0x02 << 4); command(LCD_FUNCTIONSET | _displayfunction); _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; display(); clear(); _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; command(LCD_ENTRYMODESET | _displaymode); home(); } void display() { _displaycontrol |= LCD_DISPLAYON; command(LCD_DISPLAYCONTROL | _displaycontrol); } void clear(){ command(LCD_CLEARDISPLAY);// clear display, set cursor position to zero __delay_us(2000); // this command takes a long time! } void home(){ command(LCD_RETURNHOME); // set cursor position to zero __delay_us(2000); // this command takes a long time! } void noBacklight() { _backlightval=LCD_NOBACKLIGHT; expanderWrite(0); } void backlight() { _backlightval=LCD_BACKLIGHT; expanderWrite(0); } void setCursor(uint8_t col, uint8_t row){ int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; if ( row > _numlines ) { row = _numlines-1; // we count rows starting w/0 } command(LCD_SETDDRAMADDR | (col + row_offsets[row])); } size_t print(const uint8_t *buffer, size_t size){ size_t n = 0; while (size--) { if (write(*buffer++)) n++; else break; } return n; } void command(uint8_t value) { send(value, 0); } void send(uint8_t value, uint8_t mode) { uint8_t highnib=value&0xf0; uint8_t lownib=(value<<4)&0xf0; write4bits((highnib)|mode); write4bits((lownib)|mode); } void write4bits(uint8_t value) { expanderWrite(value); __delay_ms(1); pulseEnable(value); __delay_ms(1); } uint8_t writeBuffer[3] = {}; void pulseEnable(uint8_t _data){ expanderWrite((uint8_t)(_data | 0b00000100)); // En high __delay_us(100); //on 1us, sent wrong value... expanderWrite((uint8_t)_data & (~En)); // En __delay_us(100); //on 1us, sent wrong value... } void expanderWrite(uint8_t _data){ writeBuffer[0] = (uint8_t)((_data) | _backlightval); I2C1_MasterWrite(writeBuffer, 1, LCD_ADD, &status); } inline size_t write(uint8_t value){ send(value, Rs); return 1; }
メイン
main.c
#include <stdio.h> #include <stdlib.h> #include <xc.h> #include "LCD.h" #include "mcc_generated_files/i2c1.h" #define FCY 2000000UL #include <libpic30.h> #include "mcc_generated_files/system.h" int main(void) { I2C1_Initialize(); LCD_Init(); backlight(); setCursor(0, 0); print("Hello", 5); setCursor(0, 1); print("World", 5); return 1; }