SOISK - SYSTEMY OPERACYJNE I SIECI KOMPUTEROWE
Tomasz Puchała

Projekt

/*
gr 192a
Wykonali:
..........................
*/
/*Program regulatora typu PI
Rownanie regulatora Y=K*e(n)+(T/Ti)[e(n)+suma_e(n-1)] przy czym e(n)=Uref-Uo uchyb w danym kroku
Y- wyjscie regulatora, K- wspolczynnik wzmocnienia, e- uchyb, Uref- napiecie zadane, Uo- napiecie zmierzone w obiekcie (zwrotne)
obsluga przetwornika A/C poprzez kanaly DMA

pozycja bufora DMA: Wejscia analogowe:
BufferA[0] CH0+ (AN0) - niewykorzystane
BufferA[1] CH1+ (AN3) - napiecie zadane (Uref)
BufferA[2] CH2+ (AN4) - napiecie zmierzone w obiekcie-sprzezenie zwrotne (Uo)
BufferA[3] CH3+ (AN5) - niewykorzystane

UWAGA !!! Genetrator taktujacy mikrokontroler DSP F33 jest wspolny dla ukladu CPLD - MAX II
i wynosi Finput=20MHz.
Magistrala kominikacyjna PORTD dane 8 bitow, PORTF sygnaly sterujace
RD0-7 dane 8 bitowe
RD8,9 adresy
RD10 informacja o przesylanym bajcie starszy(1)/mlodszy(0)
RF0 --- !WR
RF1 --- !RD
RF2 --- !CS
RF3 --- !RESET
*/

/* Definicja slow sterujacych
____
TCRW */
#define CS_WR_Data 0b1010 //!Reset=1, !CS=0, !RD=1 !WR=0,
#define CS_Data 0b1011 //!Reset=1, !CS=0, !RD=1 !WR=1,
#define Reset 0b0111 //!Reset=0, !CS=1, !RD=1 !WR=1,
#define InActive 0b1111 //!Reset=1, !CS=1, !RD=1 !WR=1,
#define RD_Data 0b1001 //!Reset=1, !CS=0, !RD=0 !WR=1,







/* Kolejność wyników w buforze DMA-adres:
0 = CH0 (AN6) U_zadane,
1 = CH1 (AN3) U_obiektu */


#include "p33FJ128MC706.h"

#define FCY 40000000
#define TPWM 0.00005
#define MIPS 40
#define T_Ti 0.1

//_________ GLOBAL VARIABLE __________
unsigned char const k=0; // Wspolczynnik wzmocnienia regulatora P
unsigned long DelayTime; // Czas opoznienia
int e=0; // Uchyb
/* Definicja adresow 98 uwaga bity umiejscowione na pozycjach 8,9 reszta wyzerowane */
unsigned int const AddrControl=0x0000; // adres 00 zapis do rejestru kontrolnego
unsigned int const AddrT=0x0100; // zapis do rejestru okresu
unsigned int const AddrT1=0x0200; // zapis do rejestru wypelnienia t1
unsigned int const AddrTd=0x0300; // zapis do rejestru czasu martwego
/* Definicja czesci starszej/mlodszej */
unsigned int const Data_H=0x0400; // wpis czesci H - jedynka na pozycji 10 (RD10), pozostale wyzerowane
unsigned int const Data_L=0x0400; // wpis czesci L - zero na pozycji 10

// Standardowa deklaracja obszarow pamieci obslugiwanych przez DMA
int BufferA[4]__attribute__((space(dma)));
int BufferB[4]__attribute__((space(dma)));


//____________ PROTOTYPE _____________
void Init_Ports(); //inicjalizacja portow komunikacyjnych z Altera
void Init_Osc(void); /*INICLAILZACJA OSCYLATORA*/
void Init_ADC(); /*INICJALIZACJA PRZETWORNIKA ANALOG-CYFRA*/
void Init_DMA1(); // inicjalizacja kanalu 1 DMA do wspolpracy z ADC
void Delay (unsigned long DelayTime); // petla opozniajaca
void Init_Pwm(void); /*INICLAILZACJA PWM*/
void WR_DATA(unsigned int adres,unsigned int H_L, unsigned char data8); // funkcja do wysylania danych
//____________________________________
//_______________ MAIN _______________
//____________________________________
int main(void)
{
int const max=1024-1; // Ograniczenie od góry do wartosci dodatniej 10 bitowej
int const min=-1024; // Ograniczenie od dolu do wartosci ujemnej 10 bitowej
int suma_e=0; // Suma uchybow
int Y, t1=0; // Wyjscie regulatora
int part_I; //czesc calkujaca regulatora *********
unsigned char Wyjscie_L, Wyjscie_H; // Zmienne do przechowania starszej i mlodszej czesci z wyjscia regulatora PI

Init_Ports(); // PORTG-control, PORTD-DATA+ADRESS
Init_Osc(); // INICJALIZACJA OSCYLATORA
Init_ADC(); // INICJALIZACJA PRZETWORNIKA
Init_DMA1(); // inicjalizacja kanalu 1 DMA do wspolpracy z ADC
Init_Pwm(); // inicjalizacja fali PWM do testów regulatora PI

BufferA[0]=0; // wstepne zerowanie buforow DMA
BufferA[1]=0;
BufferA[2]=0;
BufferA[3]=0;

//____________ main Loop __________

while(1)
{
IEC0bits.DMA1IE=0; // maska na przerwanie od DMA
AD1CON1bits.SAMP=0; // start przetwornika A/C - manual convertion

while (!AD1CON1bits.DONE); // czekaj na koniec konwersji
IEC0bits.DMA1IE=1; // zdjecie maski przerwania od DMA
Delay (10); // minimalne opoznienie na przejscie do obslugi przerwania

/* kod regulatora PI */

suma_e=suma_e+e;
part_I=T_Ti*suma_e;
if (part_I>max) part_I=max;
if (part_I<min) part_I=min;
Y=k*e+part_I;
if (Y<0) Y=0;
else if (Y>max) Y=max;


t1=Y;
t1=t1<<2; // dopasowanie do rozdzielczości 14 bitowej PWM
PDC1=t1;
PDC2=t1;
PDC3=t1;

/*
Wyjscie_L=Y; // przechowanie mlodszych 8 bitow wyjscia regulatora
Wyjscie_H=Y>>8; // przechowanie starszych 8 bitow wyjscia regulatora


PORTF=CS_Data; //!CS w stan niski - aktywny, !WR - nieaktywne
WR_DATA(AddrT1,Data_H,Wyjscie_H);
PORTF=CS_WR_Data; //!CS aktywne, !WR - aktywne
asm ("nop n"
"nop"); // opoznienie na operacje read-modify-write
PORTF=CS_Data; //!CS w stan niski - aktywny, !WR - nieaktywne

WR_DATA(AddrT1,Data_L,Wyjscie_L);
PORTF=CS_WR_Data; //!CS aktywne, !WR - aktywne
asm ("nop n"
"nop"); // opoznienie na operacje read-modify-write

PORTF=InActive; //!CS w stan wysoki - nieaktywny
*/

}

}

//________________ FUNCTION _______________
void Init_Ports()
{
PORTD=0;
TRISD=0; // Output
ODCD=0; // WY cyfrowe

PORTF=InActive; // szyna kontrolna nieaktywna - ustawione jedynki na wyjsciach
TRISF=0xFFF0; // RF<3:0> Output
ODCF=0; // WY cyfrowe

PORTF=Reset; //Reset układu
}


void Init_Osc(void)
{
/* USTAWIENIE OSCYLATORA przy Finput=20MHz a Fcy=40MIPS */
/* Fcy=(1/2)*Fin(M/(N1*N2)) */
CLKDIV=0x02; // N1=4 , N2=2

/*PLL FEEDBACK DIVISIOR REGISTER*/
PLLFBD=0x1E; // M=32

/* Przy Finput=40MHz a Fcy=40MIPS */
/* PLLFBD=0xE; // M=16 */
}

void Init_ADC()
{
AD1PCFGLbits.PCFG3 = 0; // AN3 WEJSCIE ANALOGOWE wielkosci zadanej (Uref)
AD1PCFGLbits.PCFG4 = 0; // AN4 WEJSCIE ANALOGOWE wielkosci mierzonej w obiekcie (Uo)
//AD1PCFGH=0xFF; // AN16=RC1, AN17=RC2 Wejscia/Wyjscia cyfrowe

AD1CON1 = 0x100C; // AD=off, ADDMABM=1 DMA conv order, 10-bits resolution, Integer format, manual start convertion, Simultaneously sampling
AD1CON2 = 0x2200; // Vref=External Vref+, Avss, convert CH0,CH1,CH3,CH4 increment DMA adress every S/H, active MUX A
// Czas konwersji jednego bitu Tad=Tcy(ADCS+1, Min Tsamp=2Tad
// W trybie AutoTsamp=16*Tad*SAMC<0:4>, Czas całkowity dla 10-bitów=16Tsamp+12Tad
AD1CON3bits.ADRC=0; // Internal clock
AD1CON3bits.SAMC=0b111; // Auto sample time 8*Tad
AD1CON3bits.ADCS=0b111; // Convertion time Tad=Tcy*(ADCS+1)=(Tosc/2)*(ADCS+1)=0,125*8=0,1us
// Tad=0,1us, Ttotal(10b, 4CH)=4*12Tad=48*0,1= 4,8us
AD1CON4=0x0000; // 1 word for each analog input
AD1CSSL = 0x0000; // Skip scan
AD1CHS123=0x0001; //Kanal CH1+ AN3, CH2 +AN4, CH3 +AN5 (niewykorzystane)
AD1CHS0 = 0x0; // Kanal CH0+ AN0 (niewykorzystane)
IFS0bits.AD1IF = 0; /* RESET FLAGI PRZERWANIA OD ADC */
IEC0bits.AD1IE = 0; /* ZABLOKOWANIE PRZEWAŃ */
AD1CON1bits.ADON = 1; /* Wlaczenie przetwornika */
}

void Init_DMA1()
{
DMA1CONbits.AMODE=0b00; //
DMA1CONbits.MODE=0b10; // continuous ping-pong with post increment
DMA1PAD=(volatile unsigned int)& ADC1BUF0; // DMA1 pointer to ADC1BUF0
DMA1CNT=0x3; // 4 DMA transfers (N+1=3+1=4)
DMA1REQ=13; // ADC1 REQ
DMA1STA=__builtin_dmaoffset(&BufferA);
DMA1STB=__builtin_dmaoffset(&BufferB);
IFS0bits.DMA1IF=0;
IEC0bits.DMA1IE=1;
DMA1CONbits.CHEN=1; // enable DMA1 CH

}


void Delay (unsigned long DelayTime) // Opoznienie czasowe
{
unsigned long n;

for (n=0;n<DelayTime;n++);
}

void __attribute__((__interrupt__)) _DMA1Interrupt(void)
{
//AN3=Uref AN4=Uo
e=BufferA[1]-BufferA[2]; // Obliczenie uchybu e=Uref-Uo
IFS0bits.DMA1IF=0; // Zerowanie flagi przerwania

}

void Init_Pwm(void)
{
// Inicjalizacja PWM UWAGA!!! Ustawic bity konfguracyjne PWM Output Pin Reset
// High side PWM Output Polarity; Low side PWM Output Polarity

PTPER=(FCY*TPWM)-1; /* (FCY/FPWM)-1 Fpwm=20000Hz*/
OVDCON = 0xFF00; /* ZABLOKOWANIE NADPISYWANIA DO PDC*/
DTCON1 = 0B11010010; /* CZESC A presc. 1:8, przy Fcy=40MHz W trybie symetrycznym Tded(us)=2*0,2*DTA<5:0>*/
DTCON2=0x0000; /* DEAD TIME Z CZESCI A*/

FLTACON=0x0000; /* KONTROLA WY PWM przez Fault A zablokowana */
FLTBCON=0x0000;
PWMCON1 = 0x0077; /* KOMPLEMENTARNE WYJSCIA PWM, przypisanie wy do PWM */
PWMCON2=0x0000; /* ZABLOKOWANIE NATYCHMIASTOWEGO MODYFIKOWANIA WYPELNIENIA PWM*/

/*INICJALIZACJA WYPELNIEIA PWM (0)*/
PDC1=PTPER;
PDC2=PTPER;
PDC3=PTPER;

/*WYBOR PRACY PWM(CENTER ALIGNED)*/
PTCON = 0x8002; //Time base ON - PTEN=1, Continouous UP/Down
}

void WR_DATA(unsigned int adres,unsigned int H_L,unsigned char data8)
{
unsigned int data16;
data16=adres+H_L+data8; // 16-bitowa wartosc adres, H/L i dane do wyslania
PORTD=data16; // wpisanie bajtu do wyslania

asm ("nop n"
"nop"); // opoznienie na operacje read-modify-write
}