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 XC32 : kompilator 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.
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 XC32 : kompilator 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 .
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
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_Start( void );
void TMR1_Stop( void );
#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_Start( void )
{
/*Enable the interrupt*/
IEC0bits.T1IE = true;
/* Start the Timer */
T1CONSET = _T1CON_ON_MASK;
}
void TMR1_Stop( void )
{
/* 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*/
Witam. Jakie minimalne napięcie referencyjne może przyjąć przetwornik ADC w tym mcu ?
OdpowiedzUsuńPotrafi on mierzyć napięcie różnicowe byle nie schodzić poniżej 0V ?
Standardowo band gap 1.2V.Dla zewnętrznego to 1.7V ?
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ńТhanks for үour marvelous posting! І genuinely enjoyed reading іt, yoս're a gret author.
OdpowiedzUsuńӀ 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!
Thank you for your kind words.
OdpowiedzUsuń