【dsPIC33FJ128MC802】UARTのDMA転送を使ってみる。受信
◆dsPIC33FJ128MC802でUARTのDMA転送を使ってみます。
参考
前回のUARTの記事にDMA機能を追加します。
・UARTリファレンスマニュアル:DS70188D
・DMAリファレンスマニュアル:DS70182Bを参考にしました。
仕様
・送信仕様:1秒毎に’a’を送信させます。
・受信仕様:ワンショットモードで10byteDMA受信したら割り込んで最初の1byteをエコーバックさせます。
ワンショットモードの設定
今回はチャンネル0を使用します。
準備:転送用バッファを用意します。
unsigned int rex_buf[10]__attribute__((space(dma)));
ワンショットモード
チャンネル許可ビットCHENの設定
DMA0CONbits.CHEN = 1;
“1"の場合:チャンネル0が有効になります。
“0"の場合:チャンネル0が無効になります。
動作モードビットMODE<1:0>の設定
DMA0CONbits.MODE = 0b01;
"01″の場合:ワンショット転送となります。
DMA転送が終わると自動的にDMA0CONbits.CHENが0になります。
再度DMA転送を利用したい場合は1にすると出来ます。
転送するデータのサイズビットSIZEの設定
DMA0CONbits.SIZE = 0;
"0″の場合:wordサイズ(2byte)
"1″の場合:byteサイズ
転送方向ビットDIRの設定
DMA0CONbits.DIR = 0;
"0″の場合:RAM←Peripheralに転送されます。
"1″の場合:RAM→Peripheralに転送されます。
UART受信のDMA転送になるので"0″に設定します。
転送カウントレジスタDMA0CNTの設定
DMA0CNT = 9;
10byte転送したいので9にします。
割り込み要求レジスタIRQSELの設定
DMA0REQbits.IRQSEL = 0b0001011;
DMA転送の割り込み要求先のperipheralを選択します。
"00001011″の場合:UART1の受信です。
IRQSEL<6-0> | peripheral | function |
0000000 | INT0 | 外部割込み0 |
0000001 | IC1 | 入力キャプチャ1 |
0000010 | OC1 | 出力コンペア1 |
0000101 | IC2 | 入力キャプチャ2 |
0000110 | OC2 | 出力コンペア2 |
0000111 | TMR2 | タイマー2 |
0001000 | TMR3 | タイマー3 |
0001010 | SPI1 | SPI1転送完了 |
0001011 | UART1RX | UART1受信 |
0001100 | UART1TX | UART1送信 |
0001101 | ADC1 | ADC1変換終了 |
0011110 | UART2RX | UART2受信 |
0011111 | UART2TX | UART2送信 |
0100001 | SPI2 | SPI2転送完了 |
0100010 | ECAN1RX | ECAN受信準備OK |
0101101 | PMP | PMPマスターデータ転送 |
0111100 | DCI | CODEC転送完了 |
1000110 | ECAN1TX | ECAN送信要求 |
1001110 | DAC1(right) | 右データ出力 |
1001111 | DAC1(left) | 左データ出力 |
Peripheralアドレスの指示
DMA0PAD = (volatile unsigned int)&U1RXREG;
volatileとは・・・最適化をさせない。
UART受信レジスタU1RXREGを指定します。
DMA転送開始アドレスの指示
DMA0STA = __builtin_dmaoffset(rex_buf);
転送用バッファーを指定します。
割り込み受信時の処理・・・
割り込み時点でバッファーに文字が入ってますので取り出してください。
1byte目を読む場合・・・
ex)data = rex_buf[0];
ソース
リファレンスマニュアルDS70182のpage21に記載のプログラムを参照しました。
//========================================================= // TEST //========================================================= //== ヘッダファイル ============================================ #include <p33fj128mc802.h> #include <stdio.h> //== define =========================================================== #define SB1602_RE LATBbits.LATB7 #define debug_pin LATBbits.LATB6 //== 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 //== MyTimer ===================================================================== void delay_us(unsigned int usec); //Timer1を利用したusec関数 void delay_ms(unsigned int msec); //msec関数 //== StringBox =================================================================== char rev_data[4]; //uart_rex //== 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設定 ========================================================= //Port_set RPINR18bits.U1RXR = 15; //RP15_U1RX TRISBbits.TRISB15 = 1; //U1RX_input RPOR7bits.RP14R = 3; //U1TX_RP14 U1MODE = 0x0000; //初期クリア U1MODEbits.UARTEN = 1; //15_UART有効 U1MODEbits.RTSMD = 1; //11_単方向モード U1MODEbits.BRGH = 0; //3_低速 U1STA = 0x0000; //初期クリア //U1STAbits.URXISEL = 0B11; //4ByteReceive_Interrupt U1STAbits.UTXEN = 1; //10_TX_enable U1BRG = 257; //低速,ビットレート:9600bps U1BRG=(Fcy/(16*9600))-1 //== CN_Initialize =================================================== //== DMA_UART ======================================================== DMA0CON = 0x0000; //clear //DMA0CONbits.SIZE = 1; //14_byte DMA0CONbits.MODE = 0b01; //1-0_OneShot DMA0CNT = 9; //10byte DMA0REQbits.IRQSEL = 0b0001011; //UART1_RX DMA0PAD = (volatile unsigned int)&U1RXREG; //peripheral_address DMA0STA = __builtin_dmaoffset(rex_buf); //DMA_start_address //== 前処理 ====================================================== DMA0CONbits.CHEN = 1; //DMA0_enable IEC0bits.DMA0IE = 1; //DMA0_interrupt_enable //== while文 =========================================================== while(1) { while(U1STAbits.UTXBF); U1TXREG = 'a'; 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 //== DMA0_Interrupt ========================================================================= void __attribute__((interrupt,auto_psv)) _DMA0Interrupt(void) { IFS0bits.DMA0IF = 0; //Flag_OFF DMA0CONbits.CHEN = 1; //DMA0_reset_enable //== DebugFlag ============================================================= while(U1STAbits.UTXBF); //Buffer_empty U1TXREG = rex_buf[0]; //first_byte debug_pin = !debug_pin; }//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) //======================================================================== //=================================================================================
ディスカッション
コメント一覧
まだ、コメントがありません