0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PIC32MX370F512F 64pin (2) オシレータ設定、割り込み、シリアル通信

Last updated at Posted at 2024-10-19

記事内容は、後日も随時更新していきます。

24/10/22 シリアル通信の受信コードのバグ改良。URXDAビットのチェックを追加。
24/11/08 オシレータ設定は、コンフィグで80Mhzに設定されている内容に改変

IMG_5016.JPG

オシレータ設定

内蔵オシレータ8Mhzを使用して、システムクロックを80MHzに設定します。
データシートオシレータ1.png

まず、コンフィグレーションビットで、電源オン時に、SYSCLK=80Mhz で起動させています。
ソフトウェアでも、SYSCLKを変更できるので、PLLODIV=2を、PLLODIV=1にして、SYSCLK=80Mhzに設定することもできます。
同時に、ペリフェラルに供給されるクロックPBCLKも80Mhzにしたいので、PBDIVビットを1にしています。
オシレータレジスタは、ロックが掛かっているので、SYSKEYレジスタを使って、ロックを解除しています。
コンフィグレーション設定画面.png

コンフィグレーションビットSYSCLK=40Mhz
// DEVCFG3
#pragma config USERID = 0xFFFF          // Enter Hexadecimal value (Enter Hexadecimal value)
#pragma config FSRSSEL = PRIORITY_7     // Shadow Register Set Priority Select (SRS Priority 7)
#pragma config PMDL1WAY = OFF           // Peripheral Module Disable Configuration (Allow multiple reconfigurations)
#pragma config IOL1WAY = OFF            // Peripheral Pin Select Configuration (Allow multiple reconfigurations)

// DEVCFG2
#pragma config FPLLIDIV = DIV_2         // PLL Input Divider (2x Divider)
#pragma config FPLLMUL = MUL_20         // PLL Multiplier (20x Multiplier)
#pragma config FPLLODIV = DIV_2         // System PLL Output Clock Divider (PLL Divide by 2)

// DEVCFG1
#pragma config FNOSC = FRCPLL           // Oscillator Selection Bits (Fast RC Osc with PLL)
#pragma config FSOSCEN = OFF            // Secondary Oscillator Enable (Disabled)
#pragma config IESO = OFF               // Internal/External Switch Over (Disabled)
#pragma config POSCMOD = OFF            // Primary Oscillator Configuration (Primary osc disabled)
#pragma config OSCIOFNC = OFF           // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FPBDIV = DIV_1           // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/1)
#pragma config FCKSM = CSECMD           // Clock Switching and Monitor Selection (Clock Switch Enable, FSCM Disabled)
....<>
オシレータ設定SYSCLK=40Mhz→80Mhz
//oscillator init---------------------------------
    SYSKEY = 0x0;           // ensure OSCCON is locked
    SYSKEY = 0xAA996655;    // Write Key1 to SYSKEY
    SYSKEY = 0x556699AA;    // Write Key2 to SYSKEY
    //PLL Output Divisor bits
    OSCCONbits.PLLODIV=0b000;   //000 = PLL output divided by 1
    //PeripheralBusClock diviser.
    OSCCONbits.PBDIV=0b00;  //SYSCLK divided by1
    SYSKEY = 0x0;           // ensure OSCCON is locked

割込み許可 CP0 Statusレジスタ IEビット

セクション 2. M4K® コア搭載デバイス用 CPU DS61113E_JP - p.2-26
CP0_Statusレジスタ.png

MIPS内コプロセッサCP0 Statusレジスタのビット0:IE をセットすると割込み許可になります。

CP0Statusレジスタで割込み許可
tmp_CP0_Status=_CP0_GET_STATUS();
    tmp_CP0_Status|=0x00000001;//CP0.STATUS.IE=1で割り込み許可
    _CP0_SET_STATUS(tmp_CP0_Status);

USART設定

PPSで、
RC13:U1TX
RC14:U1RX
に設定しています。

USART PPS
//PPS
    SYSKEY = 0x0; // ensure OSCCON is locked
    SYSKEY = 0xAA996655; // Write Key1 to SYSKEY
    SYSKEY = 0x556699AA; // Write Key2 to SYSKEY

    RPC13Rbits.RPC13R=0b0011; //RPC13:U1TX
    U1RXR=0b0111;             //RPC14:U1RX
    
    SYSKEY = 0x0; // ensure OSCCON is locked

USART 標準入出力関数

_mon_putc関数.png

printf文が使えるように、_mon_putcを実装しました。

_mon_putc関数
/**
 * 32-Bit Language Tools Libraries P.38
 * Description: Writes a character to stdout.
 * printf文で使用。
 * @param c 出力1文字
 */
void _mon_putc (char c)
{
    while (U1STAbits.UTXBF); //Wait till transmission is complete
    U1TXREG = c;
}

受信時の動作

URXDAフラグがクリアの時にも、割り込みが発生している。ここで躓いた。

受信割り込み処理
void __ISR(_UART_1_VECTOR,IPL1AUTO) ISR_UART1(void)
{
    if( IFS1bits.U1RXIF==1)
    {
        IFS1bits.U1RXIF=0;
        if(U1STAbits.URXDA)//←これがないと、正しく受信しない。
        {
            do{
                rxU1.ch=U1RXREG;
                rxU1.buf[rxU1.length]=rxU1.ch;
                rxU1.length++;
                if(rxU1.length>=RXUSART_BUFFER_SIZE)
                {
                    rxU1.length=0;
                }
            }while(U1STAbits.URXDA);  
            if(rxU1.ch==0x0a && rxU1.length>=3)//0x0a:'\n'
            {
                //rxUsart.buf[rxUsart.length-2]='\0';//\a\n終端文字FromPC
                rxU1.buf[rxU1.length-2]=0x00;//\a\n終端文字FromPC
                rxU1.completed=true;  
                IEC1bits.U1RXIE=0;
            } 
        }
    }
}

コード<オシレータ設定、Timer1割り込み、シリアル通信送受信、受信割り込み>

main.c


// PIC32MX370F512H Configuration Bit Settings

// 'C' source line config statements

// DEVCFG3
#pragma config USERID = 0xFFFF          // Enter Hexadecimal value (Enter Hexadecimal value)
#pragma config FSRSSEL = PRIORITY_7     // Shadow Register Set Priority Select (SRS Priority 7)
#pragma config PMDL1WAY = OFF           // Peripheral Module Disable Configuration (Allow multiple reconfigurations)
#pragma config IOL1WAY = OFF            // Peripheral Pin Select Configuration (Allow multiple reconfigurations)

// DEVCFG2
#pragma config FPLLIDIV = DIV_2         // PLL Input Divider (2x Divider)
#pragma config FPLLMUL = MUL_20         // PLL Multiplier (20x Multiplier)
#pragma config FPLLODIV = DIV_2         // System PLL Output Clock Divider (PLL Divide by 1)

// DEVCFG1
#pragma config FNOSC = FRCPLL           // Oscillator Selection Bits (Fast RC Osc with PLL)
#pragma config FSOSCEN = OFF            // Secondary Oscillator Enable (Disabled)
#pragma config IESO = OFF               // Internal/External Switch Over (Disabled)
#pragma config POSCMOD = OFF            // Primary Oscillator Configuration (Primary osc disabled)
#pragma config OSCIOFNC = OFF           // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FPBDIV = DIV_1           // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/1)
#pragma config FCKSM = CSECMD           // Clock Switching and Monitor Selection (Clock Switch Enable, FSCM Disabled)
#pragma config WDTPS = PS1048576        // Watchdog Timer Postscaler (1:1048576)
#pragma config WINDIS = OFF             // Watchdog Timer Window Enable (Watchdog Timer is in Non-Window Mode)
#pragma config FWDTEN = OFF             // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
#pragma config FWDTWINSZ = WINSZ_25     // Watchdog Timer Window Size (Window Size is 25%)

// DEVCFG0
#pragma config DEBUG = OFF              // Background Debugger Enable (Debugger is Disabled)
#pragma config JTAGEN = OFF             // JTAG Enable (JTAG Disabled)
#pragma config ICESEL = ICS_PGx2        // ICE/ICD Comm Channel Select (Communicate on PGEC2/PGED2)
#pragma config PWP = OFF                // Program Flash Write Protect (Disable)
#pragma config BWP = OFF                // Boot Flash Write Protect bit (Protection Disabled)
#pragma config CP = OFF                 // Code Protect (Protection Disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.



#include <xc.h>
#include <stdio.h>

#include <cp0defs.h> 
#include <sys/attribs.h>
#include "peripheral.h"


void portInit(void)
{
    TRISB=0x0000;
    TRISC=0x0000;
    TRISD=0x0000;
    TRISE=0x0000;
    TRISF=0x0000;
    TRISG=0x0000;
    
    ANSELB=0x0000;
    ANSELC=0x0000;
    ANSELD=0x0000;
    ANSELE=0x0000;
    ANSELF=0x0000;
    ANSELG=0x0000;
    
    PORTB=0x0000;
    PORTC=0x0000;
    PORTD=0x0000;
    PORTE=0x0000;
    PORTF=0x0000;
    PORTG=0x0000;
}

void main(void) 
{
    uint32_t address;
    unsigned int tmp_CP0_Status; // Temporary register for CP0 reg storing 
    
    //oscillator init---------------------------------
    SYSKEY = 0x0;           // ensure OSCCON is locked
    SYSKEY = 0xAA996655;    // Write Key1 to SYSKEY
    SYSKEY = 0x556699AA;    // Write Key2 to SYSKEY
    //PLL Output Divisor bits
    OSCCONbits.PLLODIV=0b000;   //000 = PLL output divided by 1
    //PeripheralBusClock diviser.
    OSCCONbits.PBDIV=0b00;  //SYSCLK divided by1
    SYSKEY = 0x0;           // ensure OSCCON is locked
    
    //port init---------------------------------------
    portInit();
    
    //peripheral initializing-------------------------
    timer1Init();
    usartInit();
    __delay_ms(10);//これを入れないとazが出力されない。
    putchar('a');putchar('z');
    //interrupt initializing-------------------------
    printf("\nPIC32MX370F512HT\n");
    
    //割り込み関連
    address=_CP0_GET_EBASE();//例外ベクタアドレス
    printf("EBASE=%lx\n",address);
    INTCONbits.MVEC=1;
    tmp_CP0_Status=_CP0_GET_STATUS();
    tmp_CP0_Status|=0x00000001;//CP0.STATUS.IE=1で割り込み許可
    _CP0_SET_STATUS(tmp_CP0_Status);
    // __builtin_enable_interrupts();
   
  
    while(1)
    {
        if(rxU1.completed)
        {
            rxU1.completed=false;
            printf("len:");
            printf("%d %s\r",rxU1.length, rxU1.buf);            
            rxU1.length=0;
            IFS1bits.U1RXIF=0;
            IEC1bits.U1RXIE=1;
        }
    }
    
    
    return;
}



Peripheral.h


#ifndef PERIPHERAL_H
#define	PERIPHERAL_H

#ifdef	__cplusplus
extern "C" {
#endif
#include <xc.h>
#include <cp0defs.h> 
#include <sys/attribs.h>
#include <stdio.h>
#include <stdbool.h>
    
#define SYSCLK      80000000L		// System clock 40Mhz
#define CTCLK		(SYSCLK / 2)    // CoreTimerCLK SystemClock/2
#define CTus 		(CTCLK / 1000000)	// us delay unit Term
#define CTms     	(CTCLK / 1000)	// ms delay unit Term

#define High 1
#define Low  0
    

//USART-----------------------------------    
#define BAUDRATE 115200
#define SET_SPBRG_DATA  (((unsigned int)((SYSCLK/4)/BAUDRATE))-1)
#define SET_SPBRG_DATA1 (((unsigned int)((SYSCLK/16)/BAUDRATE))-1)    

#define RXUSART_BUFFER_SIZE 50
typedef struct
{
    uint8_t buf[RXUSART_BUFFER_SIZE];
    uint8_t length;
    uint8_t completed;
    uint8_t ch;
}_rxUsart;
extern volatile _rxUsart rxU1;

extern void usartInit(void);
extern uint8_t getch(void);
extern void myUsartPrint(uint8_t *txBuf, uint8_t _length);    
    
//Timer-----------------------------------------------
    typedef struct{
        uint32_t cnt;
        bool fg;
    }_tm;
    extern _tm tm1;
    extern void timer1Init(void);


//Delay------------------------------------------------    
extern void __delay_ms(long _ms);
extern void __delay_us(long _us);
    
    
    
    
#ifdef	__cplusplus
}
#endif

#endif	/* PERIPHERAL_H */


Peripheral.c
#include "peripheral.h"


//USART---------------------------------------------------
//USART受信用構造体
volatile _rxUsart rxU1;

/**
 * usart初期化関数
 */
void usartInit(void)
{
    //1.ボーレート設定115200
    U1BRG=SET_SPBRG_DATA1;
    //2.Serial mode setting
    U1RXREG=0x0000;
    U1TXREG=0x0000;
    U1MODEbits.PDSEL=0b00;//8bits no parity
    U1MODEbits.STSEL=1;//1stopbits
    //PPS
    SYSKEY = 0x0; // ensure OSCCON is locked
    SYSKEY = 0xAA996655; // Write Key1 to SYSKEY
    SYSKEY = 0x556699AA; // Write Key2 to SYSKEY

    RPC13Rbits.RPC13R=0b0011; //RPC13:U1TX
    U1RXR=0b0111;             //RPC14:U1RX
    
    SYSKEY = 0x0; // ensure OSCCON is locked
    
    //Rx interrupt
    IFS1bits.U1RXIF=0;
    IPC7bits.U1IP=1;
    IPC7bits.U1IS=1;
    IEC1bits.U1RXIE=1;
    U1STAbits.URXISEL=0b00;//not empty
   
    //IO direction change
    TRISC=0x0000;
    TRISCbits.TRISC14=1; //Input For U1RX.
    
    rxU1.length=0;
    //4.Serial port enabled
    U1STAbits.URXEN=1;
    U1STAbits.UTXEN=1;
    U1MODEbits.ON=1;
}

/**
 * 32-Bit Language Tools Libraries P.38
 * Description: Writes a character to stdout.
 * printf文で使用。
 * @param c 出力1文字
 */
void _mon_putc (char c)
{
    while (U1STAbits.UTXBF); //Wait till transmission is complete
    U1TXREG = c;
}

/**
 * usart 文字入力受信関数
 * @return 受信文字
 */
uint8_t getch(void)
{
    while(!U1STAbits.URXDA)
            return U1RXREG;
}

//タイマー------------------------------------------
_tm tm1;

/**
 *Timer1初期化 
 */
void timer1Init(void)
{
    T1CON=0x00;
    TMR1=0x0000;
    //PR1=0x1388;//PBCLK=40Mhz
    PR1=0x2710;//PBCLK=80Mhz
    T1CONbits.TCKPS=0b01; //1:8
    T1CONbits.ON=1;
    IFS0bits.T1IF=0;
    IPC1bits.T1IP=1;
    IPC1bits.T1IS=0;
    IEC0bits.T1IE=1;
}

//ディレイ--------------------------------------------
/**
 * __delay_ms
 * @param _ms
 */
void __delay_ms(long _ms)
{
    long count;
    count=_ms*CTms;
    _CP0_SET_COUNT(0);
    while(_CP0_GET_COUNT()<=count);
}

/**
 * __delay_us
 * @param _us
 */
void __delay_us(long _us)
{
    long count;
    count=_us*CTus;
    _CP0_SET_COUNT(0);
    while(_CP0_GET_COUNT()<=count);
}

Interrupt.h

#ifndef INTERRUPT_H
#define	INTERRUPT_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <xc.h>
#include <cp0defs.h> 
#include <sys/attribs.h>
#include <sys/attribs.h>
#include "peripheral.h"
     
extern   void __ISR(_TIMER_1_VECTOR) ISR_Timer1(void);
extern   void __ISR(_UART_1_VECTOR) ISR_UART1(void);
#ifdef	__cplusplus
}
#endif

#endif	/* INTERRUPT_H */


Interrupt.c
#include "interrupt.h"


void __ISR(_TIMER_1_VECTOR,IPL1AUTO) ISR_Timer1(void)
{
    IFS0bits.T1IF=0;
    tm1.cnt++;
    if(tm1.cnt==500)
    {
        tm1.cnt=0;
        LATBbits.LATB0=~LATBbits.LATB0;
    } 
}

void __ISR(_UART_1_VECTOR,IPL1AUTO) ISR_UART1(void)
{
    if( IFS1bits.U1RXIF==1)
    {
        IFS1bits.U1RXIF=0;
        if(U1STAbits.URXDA)
        {
            do{
                rxU1.ch=U1RXREG;
                rxU1.buf[rxU1.length]=rxU1.ch;
                rxU1.length++;
                if(rxU1.length>=RXUSART_BUFFER_SIZE)
                {
                    rxU1.length=0;
                }
            }while(U1STAbits.URXDA);  
            if(rxU1.ch==0x0a && rxU1.length>=3)//0x0a:'\n'
            {
                //rxUsart.buf[rxUsart.length-2]='\0';//\a\n終端文字FromPC
                rxU1.buf[rxU1.length-2]=0x00;//\a\n終端文字FromPC
                rxU1.completed=true;  
                IEC1bits.U1RXIE=0;
            } 
        }
    }
}



0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?