PICマイコンの使い方

PICマイコンの8bitマイコンから32bitマイコンまで使いこなすぞ! 周辺機能やアセンブラ、C言語を使いこなすぞ。ARMには負けないぞ! 頼みの綱はPIC32MZだ!たのしみだなー

液晶モジュール

【dsPIC33FJ128MC802】秋月LCDキャラクタモジュールSD1602を使ってみる。(8bitモード)


◆dsPIC33FJ128MC802で秋月LCDキャラクタモジュールを8bitモードで使ってみます。



1)パーツ
超小型LCDキャラクタディスプレイモジュール(16×2行バックライト・オレンジ)
ブレッドボードで実験がしやすい1列ピン仕様です。
電源は5V仕様ですがInputVoltage:HIGH=2.2Vなので、3.3VのdsPICでも直でつなげそうです。

2)接続













LCD_SD1602dsPICmemo
4_RSRB8Command/Data
5_R/WRB9Read/Write
6_ERB10ENABLE
7_DB0RB0DATAbit0
8_DB1RB1DATAbit1
9_DB2RB2DATAbit2
10_DB3RB3DATAbit3
11_DB4RB4DATAbit4
12_DB5RB5DATAbit5
13_DB6RB6DATAbit6
14_DB7RB7DATAbit7

データ転送にポートBの下位をつかいました。

3)イニシャライズ
仕様書通りに設定しました。ソースではwaitは適当にしちゃいました。
仕様書で2回目のFunction後は100sとなってますが、おそらく100msの間違え!?












STEPMEMOCode
1wait15ms---
2FunctionSET0x30
3wait4.1ms---
4FunctionSET0x30
5wait100ms---
6FunctionSET0x30
78BitMode0x38
8Entry0x06
9Clear0x01
10DisplayON0x0C


4)ビジーフラグのチェック
LCDにコマンド/データを書き込んだ後
次の書き込みが可能か否かを判断するために
ビジーフラグをチェックする必要があります。
ビジーフラグチェックの代わりに100μsecほど待ってもokです。





RSRD/WRDB7DB6DB5DB4DB3DB2DB1DB0
01:RDBF---------------------

■フロー
1)DB7に接続したピンを入力に切り替える。
2)コマンドモード
3)リードモード
4)Eanbleをパタパタ
5)DB7の出力をチェックする。
・DB7:0になるまで2~5を繰り返す。
終わったら
6)DB7に接続したピンを出力に切り替える。

ビジーフラグのチェックには「do-while文」で実現しました。


5)ソース
ためしに文字列を表示してみました。
//=========================================================
// TEST
//=========================================================
//== ヘッダファイル ============================================
#include <p33fj128mc802.h>
#include <stdio.h>

//== define =============================================================
#define SD1602_RS LATBbits.LATB8
#define SD1602_RW LATBbits.LATB9
#define SD1602_E LATBbits.LATB10
//== configuration ======================================================
_FBS(BSS_NO_FLASH //No Boot program Flash segment
& BWRP_WRPROTECT_OFF); //Boot Segment may be written
_FGS(GSS_OFF //User program memory is not code-protected
& GWRP_OFF); //User program memory is not write-protected
_FOSCSEL(FNOSC_FRCPLL //Internal Fast RC (FRC) w/ PLL
& IESO_OFF); //Start-up device with user-selected oscillator source
_FOSC(FCKSM_CSDCMD //Both Clock Switching and Fail-Safe Clock Monitor are disabled
& IOL1WAY_ON // Allow Only One Re-configuration
& OSCIOFNC_ON //OSC2 pin has digital I/O function
& POSCMD_NONE); //Primary Oscillator Disabled
_FWDT(FWDTEN_OFF); //Watchdog timer enabled/disabled by user software
_FPOR(FPWRT_PWR128 //PowerOnReset_128ms
& ALTI2C_OFF); //I2C mapped to SDA1/SCL1 pins
_FICD(JTAGEN_OFF //JTAG is Disabled
& ICS_PGD1); //Communicate on PGC1/EMUC1 and PGD1/EMUD1
//== interrupt_function_prototype ================================================
void __attribute__((interrupt,no_auto_psv)) _U1RXInterrupt(void); //UART_RX_Interrupt
void __attribute__((interrupt,auto_psv)) _DMA0Interrupt(void); //DMA0_Interrupt
//== DMA_UART ====================================================================
unsigned int rex_buf[10]__attribute__((space(dma))); //10byte
//== UART ========================================================================
char U1RXstring(void); //receive_string
void U1TXstring(char *string, unsigned char count); //tex_string
//== SD1602LCD用プロトタイプ =========================================================
void sd1602_init(void); //sd1602初期化
void sd1602_cmd_write(unsigned char data); //sd1602コマンド書き込み
void sd1602_data_write(unsigned char data); //sd1602データ書き込み
//== sd1602文字列書き込み(配列 + 行目 + 出力数) =======================================
void sd1602_string_write(char *data, char line, unsigned char count);

//== MyTimer =====================================================================
void delay_us(unsigned int usec); //Timer1を利用したusec関数
void delay_ms(unsigned int msec); //msec関数
//== StringBox ===================================================================
unsigned char akiLCD_RAM[48][200];
char rev_data[4]; //uart_rex
char test_box[10] = "test_mode";
//== original_struct ======================================================
struct{
unsigned pwm_out : 1;
unsigned fan : 1;
unsigned lamp : 1;
}st_flag;
//== main ==================================================================
int main(void)
{
//== クロックの設定 ======================================================
//== Fcy=Fosc/2=7.37M*((PLLFBD+2)/(N2*N1))/2=39.61MHz ================
PLLFBDbits.PLLDIV = 41; //M=PLLFBD+2
CLKDIVbits.PLLPOST = 0; //N2=2
CLKDIVbits.PLLPRE = 0; //N1=2
OSCTUN = 0; //TuneFRC:7.37MHz
RCONbits.SWDTEN = 0; //Disable Watch Dog
while(OSCCONbits.LOCK != 1); //wait for PLL Lock
//== AD切り替え ==========================================================
AD1PCFGL = 0xffff; //全digital
//=== TRISA ===========================================================
TRISA = 0x0000; //initial_
//== TRISB =============================================================
TRISB = 0x0000; //input:
//== i2c設定 ============================================================
//== TIMER1設定 =========================================================
T1CONbits.TON = 0; //15_Timer1_OFF
T1CONbits.TSIDL = 1; //13_アイドルモード:Sleep中は停止
T1CONbits.TGATE = 0; //6_ゲート積算時間:OFF
T1CONbits.TCKPS = 0B00; //5-4_PS1:1
T1CONbits.TCS = 0; //2_クロックソース:内部
IEC0bits.T1IE = 0; //割り込み拒否
IPC0bits.T1IP = 0; //優先レベル0
//== UART1設定 =========================================================
//== CN_Initialize ===================================================
//== DMA_UART ========================================================
//== 前処理 ======================================================
sd1602_init(); //LCD初期化
sd1602_cmd_write(0x80);
//== while文 ===========================================================
while(1)
{
sd1602_string_write(test_box,2,9);
sd1602_string_write(test_box,1,9);
delay_ms(100);
}//while(1)
}//int main(void)


//== delay_us関数 =================================================================
void delay_us(unsigned int usec)
{
TMR1 = 0; //TMR1=0
T1CONbits.TON = 1; //Timer1_start
PR1 = 39; //PR1値:((目的値1usec)/(1サイクル:0.0025usec*PS)-1)=39
unsigned int i;
for(i=0; i<usec; i++)
{ //タイマーフラグ待ち
while(!IFS0bits.T1IF); //Timer1割り込みフラグチェック(IFS0bits.T1IF==0)
IFS0bits.T1IF = 0; //割り込みフラグ下ろす
}//for(i=0; i<usec; i++)
}//void delay_usec();
//== delay_ms関数 ==================================================================
void delay_ms(unsigned int msec)
{
unsigned int i;
for(i=0; i<msec; i++)
{
delay_us(1000); //call:1000usec
}//for
}//void delay_ms
//== SD1602 initialize ===================================================
void sd1602_init(void)
{
delay_ms(100); //100msec
sd1602_cmd_write(0x30); //Function_set
delay_ms(10); //4.1msec
sd1602_cmd_write(0x30); //Function_set
delay_ms(100); //100msec
sd1602_cmd_write(0x30); //Function_set
delay_ms(10);
sd1602_cmd_write(0x38); //N=1:2line
delay_ms(10);
sd1602_cmd_write(0x06); //EntryMode
delay_ms(1);
sd1602_cmd_write(0x01); //ClearDisplay
delay_ms(10);
sd1602_cmd_write(0x0c); //DisplayOn
delay_ms(1);
} //sd1602_init(void)
//== SD1602 Command Write ===================================================
void sd1602_cmd_write(unsigned char data)
{
PORTB = data; //data_out
SD1602_RS = 0; //command_mode
delay_us(10);
SD1602_RW = 0; //write
SD1602_E = 1; //enable_toggle
delay_us(10);
SD1602_E = 0;
//busy_check
TRISBbits.TRISB7 = 1; //input
do{
SD1602_RS = 0; //command_mode
SD1602_RW = 1; //read_mode
SD1602_E = 1;
delay_us(10);
SD1602_E = 0;
}while(PORTBbits.RB7 == 0);
SD1602_RW = 0;
TRISBbits.TRISB7 = 0; //output
delay_us(10);
}//void sd1602_cmd_write(unsigned char data)
//== SD1602 Data_Write ====================================================
void sd1602_data_write(unsigned char data)
{
PORTB = data; //data_out
SD1602_RS = 1; //data_mode
delay_us(10);
SD1602_RW = 0; //write
SD1602_E = 1; //enable_toggle
delay_us(10);
SD1602_E = 0;
//busy_check
TRISBbits.TRISB7 = 1; //input
do{
SD1602_RS = 0; //command_mode
SD1602_RW = 1; //read_mode
SD1602_E = 1;
delay_us(10);
SD1602_E = 0;
}while(PORTBbits.RB7 == 0);
SD1602_RW = 0;
TRISBbits.TRISB7 = 0; //output
delay_us(10);
}//void sd1602_data_write(unsigned char data)
//== SD1602 String_Write ====================================================
void sd1602_string_write(char *data, char line, unsigned char count)
{
if(line == 1) //1行目
{sd1602_cmd_write(0x80);}
else if(line == 2) //2行目
{sd1602_cmd_write(0xC0);}
unsigned int i;
for(i=0; i<count; i++)
{
sd1602_data_write(data[i]);
}//for(i=0; i<count; i++)
}//void sd1602_string_write(unsigned char *data, unsigned char count)
//========================================================================

//=================================================================================



6)実験の様子
LEDをつかわなかったので暗くてわかんない。
写真

7)回路図
a3da4246.png

【PIC24FJ64GA002】秋月300円液晶(LTA042B010F)をつかってみる。


◆PIC24FJ64GA002で秋月300円液晶をつかってみます。今回は単色のチャレンジです。



0)参考サイト
なる研
さんで各ポート、タイミングチャートを勉強させてもらいました。

1)色設定とポート
PORTBを全部使えば16ビットカラーに出来るんですが
ポートの節約のため256色8ビットにしました。
今回はPORTBの下位8ビットを下記の表のように接続しました。












機能LTA042B010FPIC24FJ64GA002
赤2R5_22RB7_16
赤1R4_23RB6_15
赤0R3_24RB5_14
緑2G5_15RB4_11
緑1G4_16RB3_7
緑0G3_17RB2_6
青2B5_8RB1_5
青1B4_9RB0_4


2)タイムチャート
CLKが立下りのときにサンプリングされるので
CLK=1のときに色をセットしておいて、CLK=0にするだけです。

3)実行中はこちら
73c2da65.jpg


4)プログラムの例
赤色をセットしてクロックをパタパタだけです。
プログラムの例はこちら↓

//=========================================================
// TEST
//=========================================================
//== ヘッダファイル ============================================
#include <p24FJ64GA002.h>
#include <stdio.h>
//== define ===========================================================
#define akiLCD_CLK PORTAbits.RA2
#define akiLCD_HS PORTAbits.RA3
#define akiLCD_VS PORTAbits.RA4
//== configuration ======================================================
_CONFIG1( JTAGEN_OFF //JTAGポート:OFF
& GCP_OFF //汎用セグメントプログラムメモリコード保護:OFF
& GWRP_OFF //汎用セグメントフラッシュメモリ書き込み保護:OFF
& BKBUG_OFF //バックグラウンドデバッカ:OFF
& COE_OFF //クリップオンエミュレート:OFF
& ICS_PGx1 //ICDピン選択:PGC1、PGD1を選択
& FWDTEN_OFF) //WDT:OFF
//== 8MHz×PLL4=32MHz =================================================================
_CONFIG2( IESO_OFF //2段階起動:OFF
& FNOSC_FRCPLL //発振選択:内部発振、PLL使用
& FCKSM_CSDCMD //クロック切り替え、モニタ:切り替えOFF、モニタOFF
& OSCIOFNC_ON //OSCOピン:ON→IO OFF→Fosc/2
& IOL1WAY_OFF //RPレジスタプロテクト:OFF
& I2C1SEL_PRI //I2C1ピン:主選択
& POSCMOD_NONE) //主発振:無効
//== function_prototype =================================================================

//== MyTimer =====================================================================
void delay_us(unsigned int usec); //Timer1を利用したusec関数
void delay_ms(unsigned int msec); //msec関数


//== main ==================================================================
int main(void)
{
//== クロックの設定 ========================================================
CLKDIV = 0; //PLL設定 1:1
//== AD切り替え ==========================================================
AD1PCFG = 0xffff; //全digital
//=== TRISA ===========================================================
TRISA = 0x0000; //initial_
//== TRISB =============================================================
TRISB = 0x0000; //input:
//TRISBbits.TRISB3 = 1; //SD_WE
//TRISBbits.TRISB4 = 1; //SD_CD
//TRISBbits.TRISB6 = 1; //SDI
//== SPI設定 ============================================================
//RPOR5bits.RP10R = 7; //SDO1:RP10
//RPOR5bits.RP11R = 8; //SCK1OUT:RP11
//RPINR20bits.SDI1R = 6; //SDI:RP6
//== TIMER1設定 =========================================================
T1CONbits.TON = 0; //Timer1_OFF
T1CONbits.TSIDL = 1; //アイドルモード:Sleep中は停止
T1CONbits.TGATE = 0; //ゲート積算時間:OFF
T1CONbits.TCKPS = 0B00; //PS1:1
T1CONbits.TCS = 0; //クロックソース:内部
IEC0bits.T1IE = 0; //割り込み拒否
IPC0bits.T1IP = 0; //優先レベル0
//== 割り込み許可 =========================================================
//== 前処理 =============================================================
delay_ms(200);
akiLCD_HS = 0;
akiLCD_VS = 0;
//== while文 ===========================================================
while(1)
{
akiLCD_CLK = 1;
PORTB = 0b11100000; //RED
akiLCD_CLK = 0;
}//while
}//int main(void)
//== CN_Interrupt =========================================================================

間違ってたらゴメンね!

5)回路図はこちら
バックライト用に負電源が必要なので、これまた秋月のLT1054を使いました。
電解コンデンサ2つで負電圧(電源電圧のマイナス版)を作れるので楽です。
e7064089.png

【PIC24FJ64GA002】NOKIA3300-LCDモジュールを使ってみる。


◆aitendoで買ったNokia3300-LCDをPIC24FJ64GA002で動かしてみました。昇圧回路のパーツが付属されていなかったので10pinには9Vを加えました。



1)9BITソフトSPI
 データシートP14を参考にしました。
 9bitシリアルインターフェースは
 CE、SDA、SCLの3線式となります。
 ポートが無いD/Cはデータの前に付け加えるといった仕様です。
 なので9回パタパタさせればOKです。
 コマンド送信のソフトSPIを記載します。
  Nokia3300_CE = 0;
  asm("nop");
  Nokia3300_SDI = 0;//command_mode
  Nokia3300_SCL = 0;//pata
  asm("nop");//←実際は必要なかった。
  Nokia3300_SCL = 1;//pata
  asm("nop");
  char i;
  for(i=0; i<8; i++)
   {
   SRbits.C = 0;//キャリアクリア
   data = data << 1;//MSB取り出し×8回
   if(SRbits.C ==0 )
    {Nokia3300_SDI = 0;}//if(SRbits.C ==0 )
   else{Nokia3300_SDI = 1;}//else(SRbits.C ==0 )
   Nokia3300_SCL = 0;
   asm("nop");
   Nokia3300_SCL = 1;
   asm("nop");
   }//for(i=0; i<8; i++)
   Nokia3300_CE = 1;
   asm("nop");
 (dataはunsigned charです。)
2)LCD初期化
 色々な方のプログラムを参考に8bitmodeで組みましたが
 何度送信しても赤と青が逆転してしまいました。
 こちらはRRRGGGBBで送ってるのに受けてはBBGGGRRRってなってるぽいです。
 適切かどうかはわかりませんが対策として・・・
 コマンドDATCTLのParameter2を"1"に変更しました。。。よくわかんないけど辻褄が合いました。
カメラモジュールOV7670と接続したいです。
間違ってたらゴメンね!
↓回路図はこちら
4d51542c.jpg



【PIC24FJ64GA002】I2C低電圧キャラクタ液晶モジュールを使ってみる。(ストロベリーリナックスのLCD)





■ストロベリーリナックスのI2CLCDをPIC24FJ64GA002で動かしてみました。
1)I2Cのハードウエア制御の設定
 データシートのpage146を参照に・・・
 I2C1CONの15ビット目のI2CENを'1'にするとI2CがENABLEになります。
 I2C1CONbits.I2CEN = 1;
 I2C1STATはステータスレジスタです。
2)ボーレートの設定
 データシートのpage145のEQUATION15-1を参照に・・・
 I2CxBRG={FCY/FSCL-FCY/107}-1
 FOSC=32MHzで設定したとすると・・・
 ⇒FCY=FOSC/2=16MHzとなります。
 FSCL=100kHzで使いたいとすると・・・
 ⇒I2C1BRG = 157.4 四捨五入して↓
 ⇒⇒I2C1BRG = 157;
 データシートのpage145-TABLE15-1の値と同じになりました。
3)LCDの初期化
 LCDコントローラ【ST7032i】のデータシートpage34を参照に・・・
 コントラストとFollowerを少しいじりました。
 コントラストは上位2bit(C5、C4)だけPower/ICONと同じ場所です。







レジスタDB7DB6DB5DB4DB3DB2DB1DB0設定値
ContrastSet0111C3C2C1C001111111
Power/contrast0101IONBONC5C401011111
FollowerControl0110FONR2R1R001101010

 (ド嵌りしましたが)LCDのアドレスは7bitで'0111110'と書かれているので⇒'3E'としてしまいそうになりますが、
 さらにLSB「write=0」を付け加える必要があるので⇒'01111100’⇒'7C'です。
4)プログラム
 Microchip_PIC24F_Peripheral_Library.chmを参照にすればプログラムは構築出来ます。
 でもi2c.hを使うとすべて「xxx();」で出来てしまうので↑資料(英文)を読みながら自分なりにトライしました。
 ■「StartI2C1();」⇒「I2C1CONbits.SEN = 1;」
 ■「IdleI2C1();」⇒I2C1CONのStartConditionEnableBIT=SEN、StopCondetionEnableBIT=PEN、ReceiveEnableBIT=RCEN、AcknowledgeSequenceEnable=ACKEN、I2C1STATのTransmitStatusBIT=TRSTAT、計5bitのクリア待ちなようです。
 while(I2C1CONbits.SEN || I2C1CONbits.PEN || I2C1CONbits.RCEN || I2C1CONbits.ACKEN || I2C1STATbits.TRSTAT);
 ■「StopI2C1();」⇒「I2C1CONbits.PEN = 1;」
間違ってたらゴメンね
↓回路図はこちら
fce82c00.jpg




【dsPIC30F3012】OLED表示テスト(ALO-095BWNN-J9)



dsPIC30F3012を使ったOLED:ALO-095BWNN-J9の
表示テストを行いました。左の画像はRGBの順番に
フルスクリーンで切り替えたときの画像です。
OLEDとはSPIで通信します。書き込み後に数usec
待たないとダメでした。dsPICの処理速度に比べて
OLEDの処理速度が遅いのがネックになりそうです。

白を表示するとかなり電流食うので
気をつける必要がありますね。当たり前か





↓動画はこちら

★主要パーツの購入先は
■秋月電商:
 ・dsPIC30F3012
 ・双方向ロジックレベル変換モジュール
■aitendo
 ・OLEDとキャリーボードの2点セット[OLED-2P-095BWNN-SPI]
ギャラリー
  • 【PIC24F08KL200】PIC24F08KL200でsprintfを使う
  • 【PIC24F08KL200】PIC24F08KL200でsprintfを使う
  • 【PIC24F08KL200】PIC24F08KL200でsprintfを使う
  • 【PIC24F08KL200】PIC24F08KL200でsprintfを使う
  • 【PIC24F08KL200】PIC24F08KL200でsprintfを使う
  • 【PIC24F04KA200】PIC24F04KA200ではsprintfが使えない件
  • 【PIC24F04KA200】PIC24F04KA200ではsprintfが使えない件
  • 【PIC24F04KA200】PIC24F04KA200ではsprintfが使えない件
  • 【PIC24F04KA200】PIC24F04KA200ではsprintfが使えない件
メッセージはこちちらからお願いします。

名前
メール
本文
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

ブログパーツ
  • SEOブログパーツ
にほんブログ村 その他趣味ブログ 電子工作へ
にほんブログ村
アクセスカウンタ
アクセスランキング