Subversion Repositories svnkaklik

Rev

Go to most recent revision | Details | Last modification | View Log

Rev Author Line No. Line
2 kaklik 1
// DART01A verze programu 1.00
2
// (c)miho 2005
3
 
4
#include "DART.h"
5
 
6
 
7
#define BEEP0     PIN_A6   // pipak, prvni vystup
8
#define BEEP1     PIN_A7   // pipak, druhy vystup
9
#define PWM       PIN_B3   // PWM vystup pro menic
10
#define REFPOWER  PIN_B1   // napajeni zdroje Vref
11
#define MOTOR     PIN_B2   // zapinani motoru
12
#define SW0       PIN_B7   // konfiguracni prepinac 0
13
#define SW1       PIN_B6   // konfiguracni prepinac 1
14
 
15
 
16
void InitRS232()
17
// Inicializace HW RS232
18
{
19
   SPBRG=xclock/9600/16-1; // ryclost 9600Bd
20
   RCSTA=0b10000000;       // enable USART
21
   TXSTA=0b00100100;       // BRGH=1, TX enable
22
}
23
 
24
 
25
void Putc(char c)
26
// Posilani znaku pres HW RS232
27
{
28
   while(TRMT==0);         // cekej na prazdny TX buffer
29
   TXREG=c;                // predej data
30
}
31
 
32
 
33
// Globalni promenna pro data posilana na SSP
34
//   Nastavuje se funkci MotorPatternSet()
35
//   Vyuziva se v prerusovaci rutine IntSSP()
36
unsigned int8 MotorPattern;   // aktualni data pro SSP jednotku
37
 
38
 
39
void MotorPatternSet(unsigned int Gear)
40
// Na zaklade rychlosti nastavi MotorPattern pro SSP
41
// Rychlost 0 znamena stop, rychlost 8 je maximum
42
{
43
   // Tabulka rychlost -> pattern pro SSP
44
   unsigned int8 const ExpTab[8] = {0x02,0x06,0x0e,0x1e,0x3e,0x7e,0xfe,0xff};
45
 
46
   // Vyber patternu
47
   if (Gear==0)                     // stav 0 znamena stop
48
   {
49
      output_low(MOTOR);            // klidovy stav
50
      SSPSTAT = 0;
51
      SSPCON1 = 0;                  // SPI stop
52
      disable_interrupts(INT_SSP);  // neni preruseni od SSP
53
   }
54
   else                             // rizeny vykon
55
   {
56
      if (Gear>7)                   // stav 8 a vice znamena plny vykon
57
      {
58
         Gear=8;                    // plny plyn
59
      }
60
 
61
      MotorPattern=ExpTab[--Gear];  // prevod z hodnoty plynu na data pro SSP
62
      output_low(MOTOR);            // klidovy stav
63
      SSPSTAT = 0;
64
      SSPCON1 = 0x22;               // SPI OSC/64
65
 
66
      SSPBUF=MotorPattern;          // prvni data pro vyslani
67
      enable_interrupts(INT_SSP);   // az budou vyslana prijde interrupt od SSP
68
   }
69
}
70
 
71
 
72
// Obsluha preruseni od SSP jednotky, posila data z promenne MotorRun do SSP.
73
#INT_SSP
74
void IntSSP()
75
{
76
   SSPBUF=MotorPattern;             // znova hdnota PWM patternu na SSP
77
}
78
 
79
 
80
void MotorSet(unsigned int Gear)
81
// Nastavi vykon motoru dle hodnoty Gear a zahaji posilani PWM dat pres SSP pod prerusenim
82
// od SSP jednotky
83
//    0   stop
84
//    1-7 pocet 1/8 vykonu
85
//    >7  plny vykon
86
{
87
   // Nastav PWM pattern
88
   MotorPatternSet(Gear);           // nastav PWM pattern pro SSP
89
 
90
   // Povol preruseni
91
   enable_interrupts(GLOBAL);       // povol preruseni
92
}
93
 
94
 
95
void InitT0()
96
// Inicializace casovace T0 (cca 1000x za sekundu)
97
{
98
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);  // T0 z internich hodin 1/4
99
   enable_interrupts(INT_RTCC);              // generuj preruseni od T0
100
   enable_interrupts(GLOBAL);                // povol preruseni
101
}
102
 
103
 
104
// Globalni promenna pro mereni casu
105
//   Nastavuje se procedurou TimeSet()
106
//   Testuje se funkci TimeIf()
107
//   Modifikuje se pri preruseni od casovace IntTo()
108
unsigned int16 TimeTime;
109
 
110
 
111
void TimerSet(unsigned int16 Time)
112
// Nastavi casovac na zadany pocet ms
113
// Test uplynuti casu se dela pomoci TimerIf()
114
{
115
   // Nastav hodnotu
116
   disable_interrupts(INT_RTCC);    // nesmi prijit preruseni
117
   TimeTime=Time;                   // pri nastavovani hodnoty
118
   enable_interrupts(INT_RTCC);     // promenne (o delce vice nez 8 bitu)
119
}
120
 
121
 
122
int1 TimerIf()
123
// Vraci TRUE pokud casovac jiz dobehl
124
{
125
   int1 Flag;                       // pomocna promenna
126
 
127
   // Otestuj casovac
128
   disable_interrupts(INT_RTCC);    // nesmi prijit preruseni
129
   Flag=(TimeTime==0);              // behem testu promenne
130
   enable_interrupts(INT_RTCC);     // ted uz muze
131
 
132
   // Navratova hodnota
133
   return Flag;                     // TRUE znamena dobehl casovac
134
}
135
 
136
 
137
// Globalni promenne pro akceleraci
138
//   Nastavuje se metodou MotorStart()
139
//   Pouziva se v obsluze preruseni IntT0()
140
unsigned int8 MotorTime;            // aktualni casovac pro rozjezd
141
unsigned int8 MotorDelay;           // spozdeni mezi razenim
142
unsigned int8 MotorGear;            // rychlostni stupen
143
 
144
 
145
void MotorStart(unsigned int8 Delay)
146
// Provede rizeny rozjezd motoru
147
{
148
   disable_interrupts(INT_RTCC);
149
   MotorGear=1;
150
   MotorDelay=Delay;
151
   MotorTime=MotorDelay;
152
   enable_interrupts(INT_RTCC);
153
 
154
   MotorPatternSet(1);
155
}
156
 
157
 
158
#INT_TIMER0
159
void IntT0()
160
// Preruseni od casovace cca 1000x za sekundu
161
{
162
   // Odpocitavani casovace
163
   if (TimeTime) TimeTime--;
164
 
165
   // Obsluha akcelerace
166
   if (MotorTime) MotorTime--;                           // dekrementuj casovac rozjezdu
167
   if ((MotorGear>0) && (MotorGear<8) && (!MotorTime))   // dalsi rychlostni stupen
168
   {
169
      MotorTime=MotorDelay;         // znovu nastav casovac
170
      MotorGear++;                  // dalsi rychlost
171
      MotorPatternSet(MotorGear);   // nastav rychlost
172
   }
173
}
174
 
175
 
176
// Cteni dat z AD prevodniku, zadava se cislo kanalu
177
int8 ReadAD(int8 Ch)
178
{
179
   // Pokud merim Vref zapnu si jeho napajeni
180
   if (Ch==4) output_high(REFPOWER);
181
 
182
   // Inicializace a cislo kanalu
183
   ADCON1=0x30;         // Vref+-, bez deleni hodin, Left Justify
184
   ADCON0=0x41+(Ch<<3); // on, Tosc/8, cislo kanalu
185
 
186
   // Mereni
187
   delay_us(50);        // doba na prepnuti kanalu
188
   ADCON0 |= 4;         // start prevodu
189
   delay_us(50);        // doba na prevod
190
 
191
   // Vypnu napajeni Vref (vzdycky)
192
   output_low(REFPOWER);
193
 
194
   // Navrat hodnoty
195
   return ADRESH;
196
}
197
 
198
 
199
void main()
200
{
201
   unsigned int8 Debug;
202
   unsigned int8 i;
203
 
204
   // Hodiny
205
   OSCCON = 0x62;          // 4 MHz interni RC oscilator
206
/*
207
   // Digitalni vystupy
208
   output_low(PWM);        // PWM vystup
209
   output_low(MOTOR);      // Proud do motoru
210
   output_low(REFPOWER);   // Napajeni Vref
211
   port_b_pullups(TRUE);   // Zbyvajici vyvody portu B
212
 
213
   // Watch Dog
214
   PSA=0;                  // preddelic prirazen casovaci
215
   WDTCON=0x0E;            // Watch Dog cca 130ms
216
   // Analogove vstupy
217
   ANSEL = 0x1F;           // AN0 az AN4
218
 
219
   // nastaveni RS232
220
   InitRS232();            // inicializace HW RS232 (nutno pockat cca 10ms)
221
 
222
   // Pipnuti (a cekani)
223
   for (i=1;i<30;i++)      // pocet 1/2 period
224
   {
225
      int1 beep;           // stavova promenna pro pipak
226
 
227
      output_bit(BEEP0,beep);
228
      beep=~beep;
229
      output_bit(BEEP1,beep);
230
      delay_us(1000);
231
   }
232
 
233
   // Rozhodnuti o rezimu cinnosti
234
   Debug=0;
235
   if (~input(SW0)) Debug|=1;    // precti bit 0
236
   if (~input(SW1)) Debug|=2;    // precti bit 1
237
   output_low(SW0);              // nastav L aby se snizila spotreba
238
   output_low(SW1);              // na obou vstupech
239
 
240
   // Zobrazeni rezimu
241
   printf(Putc,"\fMode:%d",Debug);
242
*/
243
   // Inicializace PWM
244
   PR2     = 0x1F;      // perioda PWM casovace
245
   T2CON   = 0x04;      // povoleni casovace T2 bez preddelicu a postdelicu
246
   CCP1CON = 0x0C;      // PWM mode, lsb bity nulove
247
   CCPR1L  =    0;      // na zacatku nulova data
248
   output_low(PWM);     // PWM vystup
249
 
250
//!!!KAKL
251
CCPR1L = 20;              // pouziti vystupu
252
disable_interrupts(GLOBAL);
253
while(true);
254
 
255
   // Inicializace casovace
256
   InitT0();            // nastav casovac na cca 1ms
257
 
258
//!!!KAKL
259
Debug=3;
260
 
261
   // Test menice PWM a rozjezdoveho PWM
262
   if (Debug==1)
263
   {
264
      unsigned int8 Data1;       // poteniometr P1 = PWM
265
      unsigned int8 Data2;       // poteniometr P2 = Rozjezd
266
 
267
      while (1)
268
      {
269
         // watch dog
270
         restart_wdt();
271
 
272
         // mereni vstupu
273
         Data1=ReadAD(0);        // nacti parametr pro PWM
274
         Data1>>=2;              // redukuj rozsah na 0 az 63
275
         Data2=ReadAD(1);        // nacti parametr pro rozjezd
276
         Data2>>=4;              // redukuj rozsah na 0 az 15
277
 
278
         // zobrazeni
279
         printf(Putc,"\nPWM:%03u RUN:%03u",Data1,Data2);
280
         delay_ms(20);
281
 
282
         // nastaveni parametru PWM
283
         CCPR1L = Data1;
284
 
285
         // nastaveni parametru RUN
286
         MotorSet(Data2);
287
      }
288
   }
289
 
290
   // Testovani rozjezdu
291
   // Zadava se cas mezi stupni razeni pro rozjezd v ms
292
   if (Debug==2)
293
   {
294
      int8 Data;
295
      int8 Start;
296
 
297
      Start=0;                               // uvodni stav
298
      while(1)
299
      {
300
         // Nacti a zobraz parametr
301
         Data=ReadAD(1);                     // potenciometr P2 = rozjezd
302
         printf(Putc,"\nRUN: %3ums ",Data);  // zobraz
303
         delay_ms(10);                       // prodleva pro terminal
304
 
305
         // Uvodni pauza
306
         if (Start==0)                       // spousti se 1x na zacatku
307
         {
308
            Start++;                         // dalsi stav je cekani
309
            TimerSet(2000);                  // na dokonceni uvodni prodlevy
310
         }
311
 
312
         // Rozjezd
313
         if ((Start==1) && TimerIf())
314
         {
315
            Start++;
316
            printf(Putc,"R");
317
            MotorStart(Data);                // rozjezd s nastavenim prodlevy
318
 
319
            TimerSet(2000);                  // nastav celkovy cas jizdy
320
         }
321
 
322
         // Zastaveni
323
         if ((Start==2) && TimerIf())
324
         {
325
            Start++;
326
            printf(Putc,"S");
327
            MotorSet(0);                     // pokud dobehl casovac zastav motor
328
         }
329
 
330
         // watch dog
331
         restart_wdt();
332
      }
333
   }
334
 
335
   // Test nabijeciho algoritmu
336
   if (Debug==3)
337
   {
338
      unsigned int8 PwmOut;   // akcni hodnota pro PWM
339
      unsigned int8 Req;      // pozadovana hodnota z P1
340
      unsigned int8 Vref;     // merena hodnota vref
341
 
342
      // Inicializace stavove promenne
343
      PwmOut=0;
344
 
345
      // Hlavni smycka
346
      while (1)
347
      {
348
         // watch dog
349
         restart_wdt();
350
 
351
         // pozadovana hodnota (potenciometr P1)
352
         Req=ReadAD(0);
353
         Req=50+(ReadAD(0)>>1);                      // 50 az 177
354
 
355
         // napeti na napajeni (vref)
356
         Vref=ReadAD(4);
357
 
358
         // ricici algoritmus
359
         if ((Vref<Req) &&(PwmOut<30)) PwmOut++;
360
         if ((Vref>=Req)&&(PwmOut> 0)) PwmOut--;
361
         Vref+=10;
362
         if ((Vref<(Req))&&(PwmOut<30)) PwmOut++;    // urychleni nabehu
363
 
364
         // nastaveni parametru PWM
365
         if (PwmOut>24) PwmOut=24;     // saturace
366
//!!!KAKL
367
PwmOut=20;
368
         CCPR1L = PwmOut;              // pouziti vystupu
369
disable_interrupts(GLOBAL);
370
while(true);
371
         // zobrazeni
372
         printf(Putc,"\nALG:%03u %03u %03u",Req,Vref,PwmOut);
373
         delay_ms(10);
374
      }
375
   }
376
 
377
   // Standardni beh
378
   if (Debug==0)
379
   {
380
      unsigned int8 PwmOut;   // akcni hodnota pro PWM
381
      unsigned int8 Req;      // pozadovana hodnota z P1
382
      unsigned int8 Vref;     // merena hodnota vref
383
      int1 Run;
384
 
385
      // Inicializace stavove promenne
386
      PwmOut=0;
387
      TimerSet(14000);        // casovani startu
388
      Run=1;
389
 
390
      // Hlavni smycka
391
      while (1)
392
      {
393
         // watch dog
394
         restart_wdt();
395
 
396
         // pozadovana hodnota (potenciometr P1)
397
         Req=ReadAD(0);
398
         Req=50+(ReadAD(0)>>1);                      // 50 az 177
399
 
400
         // napeti na napajeni (vref)
401
         Vref=ReadAD(4);
402
 
403
         // ricici algoritmus
404
         if ((Vref<Req) &&(PwmOut<30)) PwmOut++;
405
         if ((Vref>=Req)&&(PwmOut> 0)) PwmOut--;
406
         Vref+=10;
407
         if ((Vref<(Req))&&(PwmOut<30)) PwmOut++;    // urychleni nabehu
408
 
409
         // nastaveni parametru PWM
410
         if (PwmOut>24) PwmOut=24;     // saturace
411
         CCPR1L = PwmOut;              // pouziti vystupu
412
 
413
         // zobrazeni
414
         printf(Putc,"\nALG:%03u %03u %03u",Req,Vref,PwmOut);
415
         delay_ms(10);
416
 
417
         // rozjezd
418
         if (TimerIf()&&Run)
419
         {
420
            Run=0;
421
            MotorStart(65);
422
         }
423
      }
424
   }
425
}