【dsPIC33FJ128MC802】FIFOメモリAL422を使ってみる。

2021年2月18日

◆dsPIC33FJ128MC802でFIFOメモリのAL422を使ってみます。
昨年流行ったOV7670+FIFOカメラモジュールのメモリにはAL422が使われていました。
読み込み作業と書き込み作業を別々に行える利点がありますね。
PICの内蔵RAMだけでは不十分なのでAL422を外付けRAMとして今後利用したいと思います。
FIFOとは:先入れ先出し

参考

データーシートを参考にしました。

読み込み方法

制御ピン名<6:0>PINFunction
/RRST21ReadReset
RCK20ReadClock
/RE24ReadEnable
/OE22OutputEnable
DO7~DO015-18,25-28DataOutput

128byte捨て読みが必要。

 全ての作業の前に128byte捨て読みが必要見たいです。
 page15のReadOperationに記載があります。
 128byte捨て読まないと失敗します。実験では半日取られました。

アドレスリセットAddressReset

 0番地から読む為にアドレスリセットを行います。
 RRST:LOWの時にRCKの立ち上がりでリセットされます。
 通常はRRSTはHIGHにしておきます。
 詳細は下のタイミングチャートにて・・・

データリード

 RRST:HIGHで
 RCKが立ち上がり時にはDOはセットされているようです。
 私は立ち上がり直前のデータを採用しました。
deac160d.png

書き込み方法

制御ピン名<6:0>PINFunction
/WRST8WriteReset
WCK9WriteClock
/WE5WriteEnable
DI7~DI01-4,11-14DataInput

アドレスリセットAddressReset

 0番地から書き込む為にアドレスリセットを行います。
 WRST:LOWの時にWCK立ち上がりでアドレスリセットとなります。
 通常はWRSTはHIGHにしておきます。
 詳細は下のタイミングチャートにて・・・

データライト

 WRST:HIGHで
 WCK立ち上がり時にDIにセットしておく必要があります。
b052a3fb.png

ソース

 仕様:
 PORTAから書き込み(書き込んだら加算)
 PORTBから読み込みといった具合です。
 ①捨て読み128byte
 ②書き込み128byte
 ③読み込み128byte
 ④LCDに読み込んだ最初の10byteを書き込む
 繰り返し②~④

//=========================================================
//  TEST
//=========================================================
//== ヘッダファイル ============================================
#include <p33fj128mc802.h>
#include <stdio.h>
//== define =============================================================
#define SB1602_RE LATBbits.LATB10
#define WCK         LATBbits.LATB11
#define   WRST      LATBbits.LATB12
#define   RCK      LATBbits.LATB13
#define   RRST      LATBbits.LATB14
#define bit_0  LATBbits.LATA0
#define bit_1  LATBbits.LATA1
#define bit_2  LATBbits.LATA2
//== 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 ================================================
//== Sb1602_LCD用プロトタイプ =========================================================
void sb1602_init(void);                     //sb1602初期化
void sb1602_write(unsigned flag, unsigned char data);  //(flag:0:command/1:data)
//== sb1602文字列書き込み(配列 + 行目 + 出力数) =======================================
void sb1602_string_write(char *data, char line, unsigned char count);
//== DRAM_write ==================================================================
void dram_line_write(void);
void dram_line_read(char *data);
void dram_sute_read(void);
//== 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";
char test_box2[130] = "xxxxxxxxxx";
//== 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設定 ============================================================
I2C1CON = 0x0000;   //初期クリア
I2C1CONbits.I2CEN = 1;    //15_I2C_ENABLE
I2C1BRG = 0x18b;            //100kHz
//== 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
//== 前処理 =====================================================
WCK = 1;
WRST = 1;
RCK   = 1;
RRST = 1;
PORTA = 0;
TRISBbits.TRISB0 = 1;  //
TRISBbits.TRISB1 = 1;  //
TRISBbits.TRISB2 = 1;  //
sb1602_init();        //LCD初期化
sb1602_string_write(test_box,1,9);
sb1602_string_write(test_box2,2,10);
delay_ms(1000);
//== ram_clean ======
dram_sute_read();
//== while文 ===========================================================
while(1)
{
//sb1602_string_write(test_box,2,9);
dram_line_write();
dram_line_read(test_box2);
sb1602_string_write(test_box,1,9);
sb1602_string_write(test_box2,2,16);
//sb1602_string_write(rev_data,2,4);
test_box[0] = test_box[0]+1;
delay_ms(1000);
}//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
//== dram_line_write ======================================================
void dram_line_write(void)
{
//== address rest ===
WRST = 0;
WCK = 0;
WCK = 1;
WRST = 1;
//== data 1 ==
PORTA = 0;
unsigned char i;
for(i=0; i<128; i++)
{
WCK = 0;
//data_set
WCK = 1;
PORTA++;
}
//== end ========
}//dram_line_write
//== dram_line_read ======================================================
void dram_line_read(char *data)
{
//== start ======================
RRST = 0;
RCK = 0;
RCK = 1;
RRST = 1;
//================================
unsigned char i;
for(i=0; i<128; i++)
{
RCK = 0;
data[i] = 0x30 + PORTB;
RCK = 1;
//data[i] = (PORTB & 0b00000111) + 0x30;
//data[i] = 0x30 + PORTB;
}
//== end =======================
}//dram_line_read
//== dram_sute_read ======================================================
void dram_sute_read()
{
//== start ======================
RRST = 0;
RCK = 0;
RCK = 1;
RRST = 1;
//================================
unsigned char i;
for(i=0; i<128; i++)
{
RCK = 0;
RCK = 1;
asm("nop");
}
//== end =======================
}//dram_sute_read
//== SB1602 initialize ===================================================
void sb1602_init(void)
{
delay_ms(100);        //40msec
SB1602_RE = 0;
delay_ms(300);
SB1602_RE = 1;        //RESET
delay_ms(300);
sb1602_write(0,0x38);  //cmd_Function
delay_ms(1);                //1msec
sb1602_write(0,0x39);  //cmd_拡張Function
delay_ms(1);                //1msec
sb1602_write(0,0x14);  //cmd_Internal_OSC
delay_ms(1);                //1msec
sb1602_write(0,0x7F);  //cmd_Contrast
delay_ms(1);                //1msec
sb1602_write(0,0x5f);  //cmd_PowerIconContrast
delay_ms(1);                //1msec
sb1602_write(0,0x6a);  //cmd_FollowerControl(RightNibble:3.0V_b/3.3V_a)
delay_ms(250);        //200msec
sb1602_write(0,0x0C);  //cmd_DisplayOn
delay_ms(1);                //1msec
sb1602_write(0,0x01);  //cmd_ClearDisplay
delay_ms(1);                //1msec
}//sb1602_init(void)
//== SB1602 Write ====================================================
void sb1602_write(unsigned flag, unsigned char data)
{
//StartBIT
while(I2C1CONbits.SEN || I2C1CONbits.PEN || I2C1CONbits.RCEN || I2C1CONbits.ACKEN || I2C1STATbits.TRSTAT);
I2C1CONbits.SEN = 1;            //StartBIT
while(I2C1CONbits.SEN);         //Start待ち
//address
I2C1TRN = 0x7c;               //ADDRESS
while(I2C1STATbits.TBF);        //送信待ち
while(I2C1STATbits.ACKSTAT);    //ACK_CHECK
//mode_select
while(I2C1CONbits.SEN || I2C1CONbits.PEN || I2C1CONbits.RCEN || I2C1CONbits.ACKEN || I2C1STATbits.TRSTAT);
//command_mode
if(flag == 0)
{I2C1TRN = 0x00;}  //control/RS=0
//data_mode
else
{I2C1TRN = 0x40;}  //data/RS=1
while(I2C1STATbits.TBF);        //送信待ち
while(I2C1STATbits.ACKSTAT);    //ACK_CHECK
//data
while(I2C1CONbits.SEN || I2C1CONbits.PEN || I2C1CONbits.RCEN || I2C1CONbits.ACKEN || I2C1STATbits.TRSTAT);
I2C1TRN = data;               //送信データ
while(I2C1STATbits.TBF);        //送信待ち
while(I2C1STATbits.ACKSTAT);    //ACK_CHECK
//StopBIT
while(I2C1CONbits.SEN || I2C1CONbits.PEN || I2C1CONbits.RCEN || I2C1CONbits.ACKEN || I2C1STATbits.TRSTAT);
I2C1CONbits.PEN = 1;            //StopBIT
while(I2C1CONbits.PEN);         //Stop待ち
}//void sb1602_data_write(unsigned char data)
//== SC1602 String_Write ====================================================
void sb1602_string_write(char *data, char line, unsigned char count)
{
if(line == 1)  //cmd_1行目
{sb1602_write(0,0x80);}
else if(line == 2)  //cmd_2行目
{sb1602_write(0,0xC0);}
unsigned int i;
for(i=0; i<count; i++)
{
sb1602_write(1,data[i]);    //data_write
}//for(i=0; i<count; i++)
}//void sb1602_string_write(unsigned char *data, unsigned char count)
//========================================================================
//=================================================================================

回路図

入力、出力ともに3bit用意しました。
0~7まで数えることが出来ます。
b29d0200.png

よろしければバナーをクリックお願いします!