PIC32MX370F512F事始め
Lチカさせるまでの内容です。PIC16F、PIC18FでTimer,USART,I2C,SPIなどのモジュールを動かした要領で、PIC32MXも動かせると思います。唯一、違うのが、CPUコアがMIPSコアになっているところだけです。実際には、delayマクロをdelay関数として自作するときにCPUコア内部のレジスタにアクセスします。違いは、ここだけで、ペリフェラル機能は、従来のPICマイコンとの違いは、それほどないと感じました。
回路、基板製作





回路は、データシートの推奨回路どうり組めば、問題ないです。基本構成は、リセット回路と、電源ライン、書き込み線の配線ですから、この辺は、従来のPICマイコンと同じ回路になっています。
データシートの推奨回路は、MCLRにRとR1、Cを接続していますが、R1とC(0.1uf)をつけませんでした。つけたほうが無難ですが、付けなくても、動作しています。プルアップの”R”は必要です。
ピン数は64ピンと多いですが、基本回路の電源とリセット回路、書き込み回路は、従来のピックマイコンと同じです。Vcap端子に10uFを接続するのが少し違うところです。
基本回路は、16F、18Fとさほど変わりません。56番ピンのVcapに10uFのコンデンサをつなげます。
VCCは3.3vで駆動しています。
IOは、PORTAがありません。PORTB,C,D,E,F,Gという変則的な構成になっています。17番ピンと18番ピンをプログラム書き込み線として使用しています。
書き込み、デバッグ線は複数あるので、特定の一組を、コンフィグレーションビットで指定します。
32bits PICマイコンですが、中身は、MIPSというCPUコアで動いています。ここが、従来のdsPIC,24F,18F,16Fと違うところです。CPUコアは、別会社が開発して、ペリフェラル機能、たとえば、Timer,PWM,AD変換をMicrochip社が開発しています。
16F、18Fでは、delayマクロを使用してms,us単位で、遅延を発生させることが簡単にできました。
XC32コンパイラでは、delayマクロがありません。 MIPS32コア内にあるCP0レジスタ群の中にある、プロセッサのサイクルカウントレジスタ(CPUクロック2カウントでインクリメント) の経過時間をポーリングして、delay関数を作成します。
SYSTEM CONTROL COPROCESSOR (CP0)
delay_ms, delay_us関数を自作するため、CP0のレジスタ操作が必要になってきます。
データシート セクション 2. M4K® コア搭載デバイス用 CPUDS61113E_JP - p.2-21
レジスタ番号9Countのプロセッササイクル数をポーリングします。
データシート PIC32MX330/350/370/430/450/470 DS60001185F page 37
delayマクロを代替するための、delay関数を作る。
MIP32CPUコアレジスタであるCoProcesserのサイクルカウンタレジスタを読み出すマクロ
_CP0_GET_COUNT()
_CP0_SET_COUNT(value)
の2つを使います。
関数名は、PIC16F,18F,24F,dsPICのコードを流用したいので、__delay_ms、__delay_usとしておきました。
オシレータは80Mhzに設定しています。コンフィグレーションビットで指定しています。
// 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_1 // 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_PGx1 // ICE/ICD Comm Channel Select (Communicate on PGEC1/PGED1)
#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 <cp0defs.h>
#include <sys/attribs.h>
#define SYSCLK 80000000L // System clock 80Mhz
#define CTCLK (SYSCLK / 2) // CoreTimerCLK SystemClock/2
#define CTus (CTCLK / 1000000) // us delay unit Term
#define CTms (CTCLK / 1000) // ms delay unit Term
/**
* __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);
}
void main(void)
{
uint32_t i,j;
TRISB=0x0000;
ANSELB=0x0000;
PORTB=0x0000;
while(1)
{
__delay_ms(500);
LATBbits.LATB0=~LATBbits.LATB0;
}
return;
}
ポートBしか初期化してませんが、本来は、ポートB,C,D,E,F,Gすべて初期化します。