【dsPIC33FJ128MC802】PMPのDMA転送をつかってみる。
◆dsPIC33FJ128MC802でPMPのDMA転送を使ってみます。
最新追記)
aitendoのLCDを使ったDMA転送は
【dsPIC33FJ128MC802】PMP接続のDMA転送(連続転送)でaitendoの液晶を使ってみる。
参考
前回の「UARTのDMA転送」
と
「PMPをつかってみる」
を組み合わせにより作成します。
マイクロチップのリファレンスマニュアルの
①パラレルマスタポートPMPのリファレンスマニュアル:DS70299C
page28:「ダイレクトメモリアクセスDMAのサポート」を参照しました。(ちょっとしか書いてない・・・)
②UARTのリファレンスマニュアル:DS70188D
③DMAのリファレンスマニュアル:DS70182Bを参考にしました。
PMPの設定
Master1に設定します。
PMP設定の詳細はこちらから。
DMAの設定
今回はチャンネル0を使用します。
転送用バッファを用意します。
unsigned int tex_buf[1]__attribute__((space(dma)));
動作モードビットMODE<1:0>の設定
DMA0CONbits.MODE = 0b01;
割り込み要求レジスタIRQSELの設定
DMA0REQbits.IRQSEL = 0b0101101;
DMA転送の割り込み要求先のperipheralを選択します。
"0101101″の場合:PMPマスターデータ転送
転送方向ビットDIRの設定
DMA0CONbits.DIR = 1;
"0″の場合:RAM←Peripheralに転送されます。
"1″の場合:RAM→Peripheralに転送されます。
PMPマスターデータのDMA転送になるので"1″に設定します。
転送カウントレジスタの設定
DMA0CNT = 0;
1byte転送するので0にしました。
Peripheralアドレスの指示
DMA0PAD = (volatile unsigned int)&PMDIN1;
DMA転送開始アドレスの指示
DMA0STA = __builtin_dmaoffset(tex_buf);
DMA転送仕様
・DMA転送:0.5秒毎に文字列をLCDにPMPでDMA転送します。
(変わり映えしないので)動作確認の為に、頭文字だけを毎回インクリメントさせます。
割り込みは使わず
DMAREQレジスタのFORCEビットを1にして強制送信してます。
tex_buf[0] = data; //send_data_set //DMA_data_send DMA0CONbits.CHEN = 1; //DMA0_enable DMA0REQbits.FORCE = 1; //One_times //ここでLCDにはセットしたdataがDMA転送される。
ソース
//========================================================= // TEST //========================================================= //== ヘッダファイル ============================================ #include <p33fj128mc802.h> #include <stdio.h> //== define ============================================================= //== 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 tex_buf[1]__attribute__((space(dma))); //1byte //== UART ======================================================================== char U1RXstring(void); //receive_string void U1TXstring(char *string, unsigned char count); //tex_string //== SD1602LCD用プロトタイプ ========================================================= void sd1602_init(void); //sd1602初期化 void sd1602_write(unsigned flag, unsigned char data); //sd1602コマンド書き込み(flag:command/data) //== 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 =================================================================== 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設定 ========================================================= //== PMP_Initialize =================================================== PMMODE = 0x0000; PMMODEbits.MODE = 0b11; //<9:8>MastarMode_1 PMCON = 0x0000; //== port_select ==== //== R/W:PMRD/PMWR == PMCONbits.PTRDEN = 1; //<8>PMRD/PMWR_enable PMCONbits.RDSP = 1; //<0>PMRD/PMWR //== E:PMENB ======== PMCONbits.PTWREN = 1; //<9>PMWR/PMENB_enable PMCONbits.WRSP = 1; //<1>PMENB //== RS:PMA0 ======== PMAENbits.PTEN0 = 1; //<0>PMA0_enable //== wait == //PMMODEbits.WAITE = 0B01; // PMMODEbits.WAITM = 0B0001; //byre_read:1Tcy PMMODEbits.WAITB = 0B00; //data_hold:1Tcy //== CN_Initialize =================================================== //== DMA_PMP ======================================================== DMA0CON = 0x0000; //clear DMA0CONbits.SIZE = 1; //<14>byte_send DMA0CONbits.DIR = 1; //<13>write_mode DMA0CONbits.MODE = 0b01; //<1-0>one_shot DMA0CNT = 0; //1byte DMA0REQbits.IRQSEL = 0b0101101; //PMP_peripheral DMA0PAD = (volatile unsigned int)&PMDIN1; //peripheral_address DMA0STA = __builtin_dmaoffset(tex_buf); //DMA_start_address //== 前処理 ====================================================== //IPC2bits.U1RXIP = 6; //PriorityLevel_6 //IEC0bits.U1RXIE = 1; //UART_revInterrupt_enable //DMA0CONbits.CHEN = 1; //DMA0_enable //IEC0bits.DMA0IE = 1; //DMA0_interrupt_enable //st_flag.pwm_out = 0; //PWM_OFF PMCONbits.PMPEN = 1; //<15>PMP_enable sd1602_init(); //LCD初期化 sd1602_write(0,0x80); //== while文 =========================================================== while(1) { sd1602_string_write(test_box,2,9); sd1602_string_write(test_box,1,9); test_box[0] = test_box[0]+1; delay_ms(500); }//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 //== DMA0_Interrupt ========================================================================= void __attribute__((interrupt,auto_psv)) _DMA0Interrupt(void) { IFS0bits.DMA0IF = 0; //Flag_OFF //DMA0CONbits.CHEN = 1; //DMA0_reset_enable //== DebugFlag ============================================================= }//void __attribute__((__interrupt__)) _DMA0Interrupt(void) //== U1RXstringGet ============================================================= char U1RXstring(void) { unsigned char i; for(i=0; i<4; i++) //4byteInterrupt { while(!U1STAbits.URXDA); //Buffer_has_data rev_data[i] = U1RXREG; //SET_Buffer }//for(i=0; i<count; i++) return(*rev_data); }//void U1string(unsigned char *tex, char count) //== U1TXstring ============================================================== void U1TXstring(char *string, unsigned char count) { unsigned char i; for(i=0; i<count; i++) { while(U1STAbits.UTXBF); //Buffer_empty U1TXREG = string[i]; //set_Buffer }//for(i=0; i<count; i++) }//void U1string(unsigned char *tex, char count) //== SD1602 initialize =================================================== void sd1602_init(void) { delay_ms(100); //100msec sd1602_write(0,0x30); //command/Function_set delay_ms(10); //4.1msec sd1602_write(0,0x30); //command/Function_set delay_ms(100); //100msec sd1602_write(0,0x30); //command/Function_set delay_ms(10); sd1602_write(0,0x38); //command/N=1:2line delay_ms(10); sd1602_write(0,0x06); //command/EntryMode delay_ms(1); sd1602_write(0,0x01); //command/ClearDisplay delay_ms(10); sd1602_write(0,0x0c); //command/DisplayOn delay_ms(1); } //sd1602_init(void) //== SD1602 Write ==================================================== void sd1602_write(unsigned flag, unsigned char data) { unsigned char sute_yomi; //flag_check if(flag == 0) {PMADDRbits.ADDR0 = 0;} //command_mode else {PMADDRbits.ADDR0 = 1;} //data_mode //PMP while(PMMODEbits.BUSY == 1); //PMP_OK? tex_buf[0] = data; //send_data_set //DMA_data_send DMA0CONbits.CHEN = 1; //DMA0_enable DMA0REQbits.FORCE = 1; //One_times //busy_check TRISBbits.TRISB5 = 1; //PMD7_input do{ while(PMMODEbits.BUSY == 1); PMADDRbits.ADDR0 = 0; //RS=0_command_mode sute_yomi = PMDIN1; //data_in }while(PORTBbits.RB5 == 0); //PMD7_check TRISBbits.TRISB5 = 0; //output delay_us(40); }//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_write(0,0x80);} else if(line == 2) //2行目 {sd1602_write(0,0xC0);} unsigned int i; for(i=0; i<count; i++) { sd1602_write(1,data[i]); //data_mode_write }//for(i=0; i<count; i++) }//void sd1602_string_write(unsigned char *data, unsigned char count) //======================================================================== //=================================================================================
ディスカッション
コメント一覧
まだ、コメントがありません