【PIC32MX220F032B】UARTを使ってみる。その2:受信

2021年2月21日

◆PIC32MX220F032BでUARTをつかってみます。今回は受信割り込みにチャレンジです。

レジスタ設定

データシートDS61168DのPage179~を参照しました。
割り込みの場合は、U1STAレジスタの「URXISEL」bitを下記の中から選定する必要があります。
・0b11:ReServed
・0b10:6byte受信で割り込みフラグが立つ
・0b01:4byte受信で割り込みフラグが立つ
・0b00:1byte受信で割り込みフラグが立つ
1byteだと汎用性が乏しいので「0b01:4byte」にしました。
マスター(PC)からはコマンドとデータが一緒に送れますね。
あとIEC1レジスタの「U1RXIE」bitを1にするのもお忘れなく

ポート設定

データーシートDS61168DのPage146を参照しました。
U1RXは、RA2、RB6、RA4、RB13、RB2、RC6、RC1、RC3が割り当て可能です。
PRA2の場合の記述例は、
U1RXR = 0b0000;//右辺はPRA2を示します。
TRISAbits.TRISA2 = 1;//入力にしなきゃだめでした。

UART受信方法

データシートDS61107EのPage21に受信方法が記載されています。
「URXDA=1」の時にU1RXREGレジスターをロードすればいいみたいです。

割込みの有効化

データシートのDS61108Epage15のExample8-2を参照に割り込み有効をしました。
・INTCONbits.MVEC = 1;//Multi_Vector
・asm volatile(“ei"); //Enable_Interrup
上記2行を記述する必要があります。
データシートpage15の最後方の行は間違ってるっぽいです。
誤:ie/正:ei これにはクソ時間取られました。
推測するにstatusビットのIEと混同したのでしょうか?
また「STATUSbits.IE = 1;」は記述不可でした。どうして?
「INTCONSET =  0x800;」とありますが
セットするなら「0x1000」ではないでしょうか?

割込みの設定

DS61168DのPage89にU1RXのベクターアドレスが記載されています。
関数としては一個目はVectorアドレス、2個目はPriorityとなります。
PIC24Fまでの記述方法と異なるので戸惑いました。
また関数のプロトタイプは始めの方に記載しなくてもいいみたい・・・

ソース

ハイパーターミナルで4回キーを入力するとエコーバックされる仕様です。
プログラムの例はこちら↓

#include <stdio.h>
#include <plib.h>
#include <p32xxxx.h>
#include <stdlib.h>
//== OSC:8MHz SYSCLK:40MHz=(OSC_8*MUL_20)/(PLLI_2*PLLO_2) ====
#pragma config FNOSC=FRCPLL, POSCMOD=OFF, FPLLIDIV=DIV_2
#pragma config FPLLMUL=MUL_20, FPBDIV=DIV_1, FPLLODIV=DIV_2
#pragma config FWDTEN=OFF, ICESEL=ICS_PGx2
//== void ====================================================
void U1TXstring(unsigned char *tex, char count);             //UART_TX_String
unsigned char U1RXstring(void);    //UARTReceiveFunction_return(unsigned char)
//== string ==================================================
unsigned char string_box1[15] = "abcdefg¥r¥n" ;
unsigned char rev_data[] = "----¥r¥n";             //UART_receive_string
//== main ====================================================
int main(void) {
//== OSC =================================================
SYSTEMConfigPerformance(40000000);  //40MHz
//== PORT ================================================
TRISA = 0x00000000;
TRISB = 0x00000000;
ANSELA = 0x00000000;
ANSELB = 0x00000000;
//== T1CON ===============================================
T1CON = 0x00000000;     //Clear
T1CONbits.TON = 0;      //Timer1_OFF
T1CONbits.TSIDL = 1;    //Idelmode:SleepStop
T1CONbits.TGATE = 0;    //Gatetime:OFF
T1CONbits.TCKPS = 0B00; //PS1:1
T1CONbits.TCS = 0;      //ClockSource:INT
IEC0bits.T1IE = 0;      //Interrupt:None
IPC1bits.T1IP = 0;      //InterruptLevel:0
//== UART ================================================
//PORT_SELECT
RPA0R = 0B0001;         //U1TX_RPA0
U1RXR = 0B0000;         //U1RX_RPA2
TRISAbits.TRISA2 = 1;   //U1RX
U1MODE = 0x00000000;        //Clear
U1MODEbits.UARTEN = 1;      //15_UART_Enable
U1MODEbits.RTSMD = 1;       //11_SimplexMode
U1MODEbits.BRGH = 0;        //3_StandardSpeed*16
U1STA = 0x00000000;         //Clear
U1STAbits.UTXEN = 1;        //10_TX_enable
U1STAbits.URXEN = 1;        //12_RX_enable
U1STAbits.URXISEL = 0B01; //4ByteReceive_Interrupt
IEC1bits.U1RXIE = 1;        //U1RX_Interrupt_Enable
IPC8bits.U1IP = 0B110;      //Priority_6
IPC8bits.U1IS = 0B00;       //Sub_0
U1BRG = 259;                //U1BRG=(Fcy/(16*9600))-1
//========================================================
//== Interrupt ENABLE ===========================================
INTCONbits.MVEC   = 1;
asm volatile("ei");
//========================================================
while(1)
{
//delay_ms(200);
//delay_us(1);
}//while(1)
}//int main(void)
//== U1RXInterrupt =========================================================
void __ISR(32, ipl6) U1RXInterrupt(void)    //UARTReceiveInterrupt
{
IFS1bits.U1RXIF = 0;                          //Interrup_Flag_Clear
//== UART_REV ==============================================================
*rev_data = U1RXstring();        //UARTReceiveFunction
U1TXstring(rev_data,6);          //EchoBack
}
//== U1TXstring ==============================================================
void U1TXstring(unsigned char *tex, char count)
{
char i;
for(i=0; i<count; i++)
{
while(U1STAbits.UTXBF);     //Buffer_empty
U1TXREG = tex[i];           //set_Buffer
}//for(i=0; i<count; i++)
}//void U1string(unsigned char *tex, char count)
//== U1RXstring ==============================================================
unsigned char U1RXstring(void)
{
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

回路図

PIC32MXでUART割込み受信

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