piątek, 20 października 2017

Płytka developerska dla 32 bitowego mikrokontrolera PIC32MM0256GPM064


Kiedyś tak czy inaczej trzeba się zmierzyć z 32 bitami a wbrew powszechnym opinią nie samymi ARM-ami świat żyje.Ponieważ przygodę z 16-bitami rozpocząłem w krainie Microchipa, pozostaję mu wierny i tutaj celuję w mój pierwszy wybór w 32-bitach. W/g producenta przejście z 16-bitów na 32 jest całkowicie bezbolesne.Na ruszt postanowiłem wziąć mikrokontroler 32 bitowy z najniższego progu cenowego, z tej serii poniżej 1 USD :)


Do zakupu płytki developerskiej zachęciła mnie oferta promocyjna Microchipa - 20 %. W praktyce oznacza to , że nie płacimy za koszty przesyłki. Płytkę zakupiłem w sklepie Microchipa - Microchip Direct. Przesyłka dotarła po 3 dniach, jak głoszą dokumenty z oddziału w Irlandii . No fajnie od rudzielców jeszcze nie miałem żadnej pamiątki :)  Na razie jestem na etapie rozpakowywania paczuszki i cieszenia się jak dziecko z prezentu :). Opakowanie koreluje z wybarwieniem płytki , ślicznusie, czerwoniutkie z logo Microchipa.
Co na pokładzie płytki :
- mikrokontroler PIC32MM0256GPM064,
- programator/debugger ekwiwalent PICKIT-a
- 3 x switch + potencjometr 10k + dioda RGB + 2 x LED
- dwa porty mikroBUS dla modułów firmy Mikroelektronika (ok 390 profesjonalnych modułów)
- pole dla drobnych urządzeń prototypowych.

Płytka  posiada od spodu dosyć spore 4 gumowe dystanse, nie porysujemy stołu używając jej, drobne usprawnienie ale cieszy.

Do programowania PIC32MM potrzebujemy doinstalować do MPLABX IDE  kompilator dla 32-bitowców. Mamy tutaj do wyboru dwa kompilatory jeden standardowy XC32 a drugi do programowania w języku C i C++  XC32++.
Oba kompilatory są bezpłatne. tu warto nadmienić, że kompilator XC32++ nie ma żadnych ograniczeń co do optymalizacji kodu więc jest to ciekawa gratka dla programistów języka C++.

Pod tym linkiem ściągniemy kompilator standardowy XC32kompilator XC32 
a pod tym linkiem kompilator XC32 i licencję do XC32++ Licencja XC32++ jest dostępna po krótkiej rejestracji i podaniu swojego adresu MAC.

Ponieważ moją standardową platformą programistyczną jest Linux dlatego opiszę instalację kompilatora w tym systemie, dla windowsa każda małpa potrafi to zrobić :)

1. pobieramy plik kompilatora np.  
    xc32-v1.44-full-install-linux-installer.run
2. odpalamy konsolę w Linuxie
3. logujemy się na konto root-a
4. wybieramy ścieżkę do pobranego pliku np.   
    cd /home/user/Pobrane 
5. wpisujemy w konsoli  :
    chmod u+x xc32-v1.44-full-install-linux-installer.run
5. wpisujemy w konsoli  :
   ./xc32-v1.44-full-install-linux-installer.run
6.Rusza instalacja okienkowa kompilatora tu już nie ma problemu.

MPLABX- IDE wykryje automatycznie nasz doinstalowany kompilator. Przy tworzeniu nowego projektu będzie on widoczny jako opcja do wyboru.
Jeśli doinstalujemy licencję na XC32++ będziemy mieć odblokawany również i ten kompilator.

Kocham Microchipa za to , że cały soft do programowania ma przygotowany profesjonalnie również na Linuxa.
Warto nadmienić, że do mikrokontrolerów PIC32MM jest dedykowana paczka z freeRTOS .

Pierwszy program jaki napiszemy to tradycyjnie miganie diodą LED. Wykorzystamy Timer sprzętowy do generowania podstawy czasu 100 ms. Zbudujemy na tej podstawie timer programowy i pomrugamy diodą LED znajdującą się na płytce na wyjściu RD3. Do szybkiej konfiguracji zegara i timera skorzystałem z narzędzia znajdującego się w MPLABX IDE - MCC (MPLAB Code Configurator).W MCC  za pomocą pisma obrazkowego ustawiamy zegar na 24 MHz i parametry pracy Timera1.




MCC jest bardzo prostym i intuicyjnym narzędziem, umożliwiającym szybką konfigurację mikrokontrolera.
Generowany kod  to nie tylko konfiguracja ale również rozbudowane przykłady użycia i dodatkowe sztuczki programistyczne z , którch też można czegoś się nauczyć. Ale ostrzegam narzędzie to bardzo rozleniwia i powoduje , że mniej zaglądamy do datasheet-u.a to jest absolutnie niedopuszczalne :)

Poniżej artykułu kod dla mrugania diodą LED. Napisanie kodu i konfiguracja za pomocą MCC to ok 5 minut, tyle czasu trwało przejście z rodziny 16-bitowej na 32-bitową Microchipa :) Sam się zdziwiłem , że to tak łatwo poszło, gdyby to był ARM to zanim zamrugamy diodą LED to może i parę dni zająć :)

Odnośnie kodu programu to jedna uwaga, ponieważ mamy do czynienia z mikrokontrolerem 64-nóżkowym czyli z definicji mamy dużo portów I/O, dobrze jest konfigurację wszystkich portów umieścić w jednym pliku wtedy łatwiej będzie to ogarnąć.


Pozdrawiam
picmajster.blog@gmail.com

LINKI :
PIC32MM płytka developerska
PIC32MM0256GPM064 - datasheet



Pliki projektu :

tmr1.h                - plik deklaracji dla timera sprzętowego Timer1
pin_manager.h         - plik deklaracji dla wszystkich I/O
mcc.h                 - plik deklaracji dla inicjalizacji systemu / zegara
interrupt_manager.h   - plik deklaracji dla inicjalizacji przerwania od Timera1


tmr1.c                - plik definicji dla dla timera sprzętowego Timer1
pin_manager.c         - plik definicji dla dla wszystkich I/O
mcc.c                 - plik definicji dla dla inicjalizacji systemu / zegara
interrupt_manager.c   - plik definicji dla inicjalizacji przerwania od Timera1
main.c                - główny plik programu / mruganie diodą LED

/*@File 
        Name              :  tmr1.h
  
  @Description:
      
        Device            :  PIC32MM0256GPM064
        Compiler          :  XC32 1.42
        MPLAB             :  MPLAB X 3.45*/

#ifndef _TMR1_H
#define _TMR1_H


#include <xc.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdint.h> /*dyrektywy do uint8_t itp*/


#define TMR1_INTERRUPT_TICKER_FACTOR    1
extern volatile uint8_t Timer1_Programowy , Timer2_Programowy ;

void TMR1_Initialize (void);
void TMR1_Startvoid );
void TMR1_Stopvoid );


#endif
    
/*End of File*/

/*@File 
        Name              :  pin_manager.h
  
  @Description:
      
        Device            :  PIC32MM0256GPM064
        Compiler          :  XC32 1.42
        MPLAB             :  MPLAB X 3.45*/

#ifndef PIN_MANAGER_H
#define PIN_MANAGER_H

void PIN_MANAGER_Initialize(void);

#endif

/* End of File*/


/*@File 
        Name              :  mcc.h
  
  @Description:
      
        Device            :  PIC32MM0256GPM064
        Compiler          :  XC32 1.42
        MPLAB             :  MPLAB X 3.45*/

#ifndef MCC_H
#define MCC_H
#include <xc.h>
#include "pin_manager.h"
#include <stdint.h>
#include <stdbool.h>
#include "interrupt_manager.h"
#include "tmr1.h"

#define _XTAL_FREQ  24000000UL

 /*SYSKEY - blokuje/odblokowuje zapisy do ustawienia zegara*/             
 inline static void SYSTEM_RegUnlock(void)
{
    SYSKEY = 0x12345678//write invalid key to force lock
    SYSKEY = 0xAA996655//write Key1 to SYSKEY
    SYSKEY = 0x556699AA//write Key2 to SYSKEY
}


inline static void SYSTEM_RegLock(void)
{
   SYSKEY = 0x00000000
}


void SYSTEM_Initialize(void);


void OSCILLATOR_Initialize(void);


#endif  /* MCC_H */

/*End of File*/


/*@File 
        Name              :  interrupt_manager.h
  
  @Description:
      
        Device            :  PIC32MM0256GPM064
        Compiler          :  XC32 1.42
        MPLAB             :  MPLAB X 3.45*/

#ifndef _INTERRUPT_MANAGER_H
#define _INTERRUPT_MANAGER_H


void INTERRUPT_Initialize(void);



inline static void INTERRUPT_GlobalEnable(void)
{
    __builtin_enable_interrupts();
}


inline static void INTERRUPT_GlobalDisable(void)
{
    __builtin_disable_interrupts();
}

#endif

/*End of File*/


/*@File 
        Name              :  main.c
  
  @Description:
      
        Device            :  PIC32MM0256GPM064
        Compiler          :  XC32 1.42
        MPLAB             :  MPLAB X 3.45*/
  

#include "mcc.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h> /*dyrektywy do uint8_t itp*/

#define LED1_TOG PORTD ^= (1<<_PORTD_RD3_POSITION) /*zmienia stan bitu na przeciwny*/

void main(void)
{
    /*initialize the device*/
    SYSTEM_Initialize();

    while (1)
    {
        if(!Timer1_Programowy) {
              Timer1_Programowy = 10 ; /*Timer1 sprzetowy x Timer1_Programowy = 100ms x 10 = 1 s*/
              LED1_TOG ; /*zmieniaj stan wyjscia na przeciwny*/
          }
    }
}
/*End of File*/
/*@File 
        Name              :  tmr1.c
  
  @Description:
      
        Device            :  PIC32MM0256GPM064
        Compiler          :  XC32 1.42
        MPLAB             :  MPLAB X 3.45*/


#include <xc.h>
#include "tmr1.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h> /*dyrektywy do uint8_t itp*/

volatile uint8_t Timer1_Programowy , Timer2_Programowy ;

void TMR1_Initialize (void)
{
    uint32_t tcon_value = 0x00000000;
    //  TCKPS 1:64; TWDIS disabled; TCS PBCLK; TECS SOSC; SIDL disabled; TSYNC disabled; TWIP disabled; TGATE disabled; ON enabled; 
    T1CON = 0x8020;   
    tcon_value = 0x8020;  // Temporary storage of value
    T1CONCLR = _T1CON_ON_MASK;  // disable Timer, before loading the period/counter value
    // Period = 0.1 s; Frequency = 24000000 Hz; PR1 37500; 
    PR1 = 0x927C ;

    T1CON = tcon_value;//restore the TCON value
    IFS0CLR= 1 << _IFS0_T1IF_POSITION;
    IEC0bits.T1IE = true;
  
}



void __attribute__ ((vector(_TIMER_1_VECTOR), interrupt(IPL1SOFT))) TMR1_ISR()
{
    uint8_t x;
    x = Timer1_Programowy ;
    if (x) Timer1_Programowy = --x ;
    x = Timer2_Programowy ;
    if (x) Timer2_Programowy = --x ;
    /*zerowanie flagi przerwania*/
    IFS0CLR= 1 << _IFS0_T1IF_POSITION;
}


void TMR1_Startvoid )
{
    /*Enable the interrupt*/
    IEC0bits.T1IE = true;

    /* Start the Timer */
    T1CONSET = _T1CON_ON_MASK;
}

void TMR1_Stopvoid )
{
    /* Stop the Timer */
    T1CONCLR = _T1CON_ON_MASK;

    /*Disable the interrupt*/
    IEC0bits.T1IE = false;
}

/*End of File*/
/*@File 
        Name              :  pin_manager.c
  
  @Description:
      
        Device            :  PIC32MM0256GPM064
        Compiler          :  XC32 1.42
        MPLAB             :  MPLAB X 3.45*/


#include <xc.h>
#include "pin_manager.h"
#include "mcc.h"


void PIN_MANAGER_Initialize(void);

void PIN_MANAGER_Initialize(void)
{
    /****************************************************************************
     * Setting the Output Latch SFR(s)
     ***************************************************************************/
    LATA = 0x0000;
    LATB = 0x0000;
    LATC = 0x0000;
    LATD = 0x0000;

    /****************************************************************************
     * Setting the GPIO Direction SFR(s)
     ***************************************************************************/
    TRISA = 0xFFFF/*all in*/
    TRISB = 0xFFFF/*all in*/
    TRISC = 0xFFFF/*all in*/
    TRISD = 0x0000/*all out*/

    /****************************************************************************
     * Setting the Weak Pull Up and Weak Pull Down SFR(s)
     ***************************************************************************/
    CNPDA = 0x0000;
    CNPDB = 0x0000;
    CNPDC = 0x0000;
    CNPDD = 0x0000;
    CNPUA = 0x0000;
    CNPUB = 0x0000;
    CNPUC = 0x0000;
    CNPUD = 0x0000;

    /****************************************************************************
     * Setting the Open Drain SFR(s)
     ***************************************************************************/
    ODCA = 0x0000;
    ODCB = 0x0000;
    ODCC = 0x0000;
    ODCD = 0x0000;

    /****************************************************************************
     * Setting the Analog/Digital Configuration SFR(s)
     ***************************************************************************/
    ANSELA = 0x384F;
    ANSELB = 0xE01C;
    ANSELC = 0x0123;

}

/*End of File*/

/*@File 
        Name              :  mcc.c
  
  @Description:
      
        Device            :  PIC32MM0256GPM064
        Compiler          :  XC32 1.42
        MPLAB             :  MPLAB X 3.45*/


// Configuration bits: selected in the GUI

// FDEVOPT
#pragma config SOSCHP = OFF    // Secondary Oscillator High Power Enable bit->SOSC oprerates in normal power mode.
#pragma config ALTI2C = OFF    // Alternate I2C1 Pins Location Enable bit->Primary I2C1 pins are used
#pragma config FUSBIDIO = OFF    // USBID pin control->USBID pin is controlled by the USB module
#pragma config FVBUSIO = OFF    // VBUS Pin Control->VBUS pin is controlled by the USB module

// FICD
#pragma config JTAGEN = OFF    // JTAG Enable bit->JTAG is disabled
#pragma config ICS = PGx1    // ICE/ICD Communication Channel Selection bits->Communicate on PGEC1/PGED1

// FPOR
#pragma config BOREN = BOR3    // Brown-out Reset Enable bits->Brown-out Reset enabled in hardware; SBOREN bit disabled
#pragma config RETVR = OFF    // Retention Voltage Regulator Enable bit->Retention regulator is disabled
#pragma config LPBOREN = ON    // Downside Voltage Protection Enable bit->Low power BOR is enabled, when main BOR is disabled

// FWDT
#pragma config SWDTPS = PS1048576    // Sleep Mode Watchdog Timer Postscale Selection bits->1:1048576
#pragma config FWDTWINSZ = PS25_0    // Watchdog Timer Window Size bits->Watchdog timer window size is 25%
#pragma config WINDIS = OFF    // Windowed Watchdog Timer Disable bit->Watchdog timer is in non-window mode
#pragma config RWDTPS = PS1048576    // Run Mode Watchdog Timer Postscale Selection bits->1:1048576
#pragma config RCLKSEL = LPRC    // Run Mode Watchdog Timer Clock Source Selection bits->Clock source is LPRC (same as for sleep mode)
#pragma config FWDTEN = OFF    // Watchdog Timer Enable bit->WDT is disabled

// FOSCSEL
#pragma config FNOSC = FRCDIV    // Oscillator Selection bits->Fast RC oscillator (FRC) with divide-by-N
#pragma config PLLSRC = FRC    // System PLL Input Clock Selection bit->FRC oscillator is selected as PLL reference input on device reset
#pragma config SOSCEN = OFF    // Secondary Oscillator Enable bit->Secondary oscillator (SOSC) is disabled
#pragma config IESO = ON    // Two Speed Startup Enable bit->Two speed startup is enabled
#pragma config POSCMOD = OFF    // Primary Oscillator Selection bit->Primary oscillator is disabled
#pragma config OSCIOFNC = OFF    // System Clock on CLKO Pin Enable bit->OSCO pin operates as a normal I/O
#pragma config SOSCSEL = OFF    // Secondary Oscillator External Clock Enable bit->Crystal is used (RA4 and RB4 are controlled by SOSC)
#pragma config FCKSM = CSECMD    // Clock Switching and Fail-Safe Clock Monitor Enable bits->Clock switching is enabled; Fail-safe clock monitor is disabled

// FSEC
#pragma config CP = OFF    // Code Protection Enable bit->Code protection is disabled

#include "mcc.h"

void SYSTEM_Initialize(void)
{
    PIN_MANAGER_Initialize();
    OSCILLATOR_Initialize();
    INTERRUPT_Initialize();
    TMR1_Initialize();
    INTERRUPT_GlobalEnable();
}


void OSCILLATOR_Initialize(void)
{
    SYSTEM_RegUnlock();
    // ORPOL disabled; SIDL disabled; SRC SOSC; TUN Center frequency; POL disabled; ON disabled; 
    OSCTUN = 0x0;
    // PLLODIV 1:4; PLLMULT 12x; PLLICLK FRC; 
    SPLLCON = 0x2050080;
    // SWRST disabled; 
    RSWRST = 0x0;
    // WDTO disabled; GNMI disabled; CF disabled; WDTS disabled; NMICNT 0; LVD disabled; SWNMI disabled; 
    RNMICON = 0x0;
    // SBOREN disabled; VREGS disabled; RETEN disabled; 
    PWRCON = 0x0;
    //Clear NOSC,CLKLOCK and OSWEN bits
    OSCCONCLR = _OSCCON_NOSC_MASK | _OSCCON_CLKLOCK_MASK | _OSCCON_OSWEN_MASK;
    // CF No Clock Failure; FRCDIV FRC/1; SLPEN Device will enter Idle mode when a WAIT instruction is issued; NOSC SPLL; SOSCEN disabled; CLKLOCK Clock and PLL selections are not locked and may be modified; OSWEN Oscillator switch initiate; 
    OSCCON = (0x100 | _OSCCON_OSWEN_MASK);
    SYSTEM_RegLock();
    // ON enabled; DIVSWEN disabled; RSLP disabled; ROSEL FRC; OE disabled; SIDL disabled; RODIV 0; 
    REFO1CON = 0x8003;
    // ROTRIM 0; 
    REFO1TRIM = 0x0;
    // SPDIVRDY disabled; 
    CLKSTAT = 0x0;
}

/*End of File*/

4 komentarze:

  1. Witam. Jakie minimalne napięcie referencyjne może przyjąć przetwornik ADC w tym mcu ?
    Potrafi on mierzyć napięcie różnicowe byle nie schodzić poniżej 0V ?
    Standardowo band gap 1.2V.Dla zewnętrznego to 1.7V ?

    OdpowiedzUsuń
  2. Zerknij na stronę 315 datasheet TABLE 29-34: ADC MODULE INPUTS SPECIFICATIONS A tu masz dodatkowy manual o ADC dla tego procka http://ww1.microchip.com/downloads/en/DeviceDoc/60001359b.pdf

    OdpowiedzUsuń
  3. Тhanks for үour marvelous posting! І genuinely enjoyed reading іt, yoս're a gret author.
    Ӏ wilⅼ be suree to bopokmark үour blog and wiⅼl comе Ьack in the
    foreseeble future. I wаnt to encourage yoou continue yоur grteat
    posts, һave а nice holiday weekend!

    OdpowiedzUsuń
  4. Thank you for your kind words.

    OdpowiedzUsuń