【dsPIC33FJ128MC802】UARTを使ってみる。送受信

2021年2月19日


◆dsPIC33FJ128MC802でUARTを使ってみます。

参考

PIC32MXで作ったプログラムを移植します。普通順序的には逆ですね。
リファレンスマニュアル:DS70188Dが参考になります。

ボーレートの設定

ボーレートは9600bpsに設定します。
70188Dのpage10の式通りに・・・
ボーレート:9600bpsの場合(低速モードBRGH=0)
 U1BRG = (Fcy/(16×ボーレート)-1)
  = (39.61MHz/16×9600)-1
  = 257

ポート割り当て

 UART受信のポート割り当て

  PPSでRB15をUART受信に割り当てます。
  RB15を入力設定にします。

RPINR18bits.U1RXR = 15;
TRISBbits.TRISB15 = 1;

 UART送信のポート割り当て

 PPS機能を使いRB14をUART送信に割り当てます。

RPOR7bits.RP14R = 3;

UART受信割込み設定

 ①「IEC0bits.U1RXIE = 1;」受信割り込み
 ②「IPC2bits.U1RXIP = 6;」優先レベル6(適当です。)

UART送信の処理

 ①ステータスの送信バッファをチェック
 while(U1STAbits.UTXBF);
 ②送信レジスターU1TXREGにデータを入れる。
 U1TXREG = 'a’;

受信の処理

 割り込み時点でバッファーに文字が入ってますので取り出してください。
 ①ステータスの受信バッファをチェック
 while(!U1STAbits.URXDA);
 ②受信レジスターを読む。for文使って4byte退避します。
 rev_data[i] = U1RXREG;

ソース

・送信仕様:1秒毎に1byteのキャラクター’a’を送信させます。
・受信仕様:4byte受信したら割り込んで最初の1byteをエコーバックさせます。

//=========================================================
//  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
//== uart ========================================================================
char U1RXstring(void);        //receive_string
void U1TXstring(char *string, unsigned char count);   //tex_string
//== Sb1602_LCD用プロトタイプ =========================================================
void sb1602_init(void);                     //sb1602初期化
void sb1602_cmd_write(unsigned char data);    //sb1602コマンド書き込み
void sb1602_data_write(unsigned char data);      //sb1602データ書き込み
//== sb1602文字列書き込み(配列 + 行目 + 出力数) =======================================
void sb1602_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 sute_byte[70];
unsigned char bmp_byte[200];
char rev_data[4];        //uart_rex
char string_box[16] = "neko()";
unsigned int adc_tex0[16];
unsigned int adc_tex1[16];
//== 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
//== ADC_10 ================================================================
//== 前処理 ======================================================
IEC0bits.U1RXIE = 1;            //UART受信割り込み許可
IPC2bits.U1RXIP = 6;            //優先レベル1
//== while文 ===========================================================
while(1)
{
while(U1STAbits.UTXBF);
U1TXREG = 'a';      //デバック
delay_ms(1000);
//LATAbits.LATA3 = !LATAbits.LATA3;
}//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
//== U1RXInterrupt =========================================================
void __attribute__((interrupt,no_auto_psv)) _U1RXInterrupt(void)
{
IFS0bits.U1RXIF = 0;                          //Interrup_Flag_Clear
//== Framing&OverRun Error Check=================================
if(U1STAbits.OERR || U1STAbits.FERR)    //OERR_or_FERR
{
U1STA &= 0xFFF0;    //??PERR_FERR_OERR_URXDA????
//UART1_RESET
U1MODEbits.UARTEN = 0;  //UART1_Disable
U1MODEbits.UARTEN = 1;  //UART1_Enable
}//if(U1STAbits.OERR || U1STAbits.FERR)
//== UART_REV ==============================================================
//*rev_data = U1RXstring();        //UARTReceiveFunction
U1RXstring();        //UARTReceiveFunction
//== DebugFlag =============================================================
while(U1STAbits.UTXBF);     //Buffer_empty
U1TXREG = rev_data[0];
debug_pin = !debug_pin;
}//void __attribute__((interrupt,no_auto_psv)) _U1RXInterrupt(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)
//=================================================================================

ハイパーターミナルの様子

uart実行画面

回路図

UARTテスト

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