You are here

C nyelvű kód megfejtése (MEGOLDVA)

11 posts / 0 new
Last post
rainbow555
rainbow555 picture

Sziasztok!

Segítséget szeretnék kérni, mert C nyelven sajnos nem értek. A következő kis program egy jelsorozatot ad ki, de így nem tudom kiszámolni milyen hosszúak az impulzusok.
Az órajel 4MHz, van benne egy órajel pontosító rutin is.

Előre is köszönöm a segítséget!
Üdv.: Emil

Íme a kód (vastaggal kijelöltem a szerintem lényeges részt):

#define __12f675
#include "pic12f675.h"

static unsigned int __at 0x2007 __CONFIG =
_CP_OFF &
_CPD_OFF &
_WDT_ON &
_BODEN_ON &
_PWRTE_ON &
_INTRC_OSC_NOCLKOUT &
_MCLRE_OFF;

#define GPIO_OUT GPIO2
#define GPIO_CAL GPIO4
#define GPIO_FRQ (1<<5) // GPIO5

#define clrwdt() _asm CLRWDT _endasm

#define gotoAddr(Addr) do { \
_asm PAGESEL Addr _endasm; \
_asm GOTO Addr _endasm; \
} while (0)

#define nextStep(_pass, _high, _new) do { \
clrwdt(); \
if ((pass == _pass) && (TMR1H == _high)) GPIO_OUT = _new; \
} while (0)

#define lastStep(_pass, _high, _new, _lpass, _lhigh) do { \
clrwdt(); \
if ((pass == _pass) && (TMR1H == _high)) { \
GPIO_OUT = _new; \
pass = _lpass; \
TMR1H = _lhigh; \
TMR1L = 0; \
T1IF = 0; \
if (calMode & 128) calMode++; \
} \
} while (0)

#ifdef WITH_OSCCAL
/*
* Simple SDCC workaround that puts the RETLW instruction on 0x3FF. It
* results in an 0x34FF. The correct calibration value is replaced by
* the pic programmer. Since this area is reserved GPLINK will
* complain about code outside of address range.
*/
const unsigned char __code __at 0x3FF _OSCVAL = 0xFF;
#endif

unsigned char getCalib() {
EEADR = 0x00; // 0000 0000
RD = 1;

if (EEDATA == 0xFF) gotoAddr(0x3FF); /* Does not return */
return EEDATA;
}

void saveCalib() {
do clrwdt(); while (WR);

WREN = 1;
EEADR = 0x00; // 0000 0000
EEDATA = OSCCAL;

EECON2 = 0x55; // 0101 0101
EECON2 = 0xAA; // 1010 1010
WR = 1;
}

static unsigned char pass;
static unsigned char calMode;
void main() {
/* Bank 2 */
clrwdt();
ANSEL = 0x00; // 0000 0000
TRISIO = 0x1B; // 0001 1011
WPU = 0x10; // 0001 0000
OPTION_REG = 0x07; // 0000 0111

/* Bank 1 */
clrwdt();
GPIO = 0x00; // 0000 0000
CMCON = 0x07; // 0000 0111
ADCON0 = 0x00; // 0000 0000

/* Prepare calibration */
clrwdt();
if (!GPIO_CAL) {
OSCCAL = 0;
calMode = 128;
} else {
OSCCAL = getCalib();
calMode = 0;
}

/* Init timer */
clrwdt();
TMR1L = 0;
TMR1H = 0;
T1CON = 0x31; // 0011 0001
T1IF = 0;
pass = 0;

/* Main loop */
while (1) {
if (calMode & 128) {
if (GPIO_CAL) {
calMode = 0;
saveCalib();
}

if (calMode & 4) {
calMode = 128;

OSCCAL += 8;
}
}

while (TMR1L) clrwdt();

if (T0IF) {
T0IF = 0;
GPIO ^= GPIO_FRQ;
}

if (T1IF) {
T1IF = 0;
pass++;
}

/* Sequence */
nextStep(0, 98, 0); // 1
nextStep(1, 218, 1); // 2
nextStep(2, 16, 0); // 3
nextStep(2, 43, 1); // 4
nextStep(2, 69, 0); // 5
nextStep(2, 96, 1); // 6
nextStep(2, 231, 0); // 7
nextStep(4, 93, 1); // 8

/* Loop */
lastStep(5, 105, 0, 0, 98); // 9
}
}

Comments
szepi1031
szepi1031 picture

Szia!
Milyen fejlesztői környezetben dolgozol?
Mi a C compilered pontos neve, verziószáma?
A topicba beraktad az összes forrás kódot? (.h file-ok..)
Ezek ismeretében tudok segíteni.

Üdv.

István

0

rainbow555
rainbow555 picture

Szia!

Köszönöm a segítő szándékot!

MPLAB IDE, én csak asm kódot használok:) C compiler szerintem nincs is benne, még sosem kellett.
Ezt a forrást így kaptam, nincs hozzá .h, se semmi.

Oszi megírta/kiszámolta nekem az időzítéseket, így már gyerekjáték lesz:)

Üdv.: Emil

0

Oszi11
Oszi11 picture

Szia!

Itt a program kommentben megtalálod az időket! Egyébként a kalibrációs érték nem sokat tud kompenzálni a 4MHz-en olyan 0,1-0,2Mhz frekvenciát ami max, 50ns hiba, Ennél több hibát okoz a hőmérsékletváltozás.

Üdv,
Oszi

File csatolás: 

0

rainbow555
rainbow555 picture

Szia!

Nagyon szépen köszönöm a fáradozásod!
Ezzel eddig sosem kellett foglalkoznom, hogy mennyi lehet az eltérés az osccal beállítás miatt. Az 50ns nem sok ránézésre, de ha felszorzod, akkor már sokat számíthat.
Meg is írom asm-ban a programot, aztán jövő hét elejeén tudom tesztelni.

Kellemes hétvégét!

Üdv.: Emil

0

Lengyel József
Lengyel József picture

Szia,rainbow555!

Elnézést a zavarásért szerény tudásom szerint próbálók válaszolni. Az egész forráskód listából fontos az T1CON = 0x31 ; utasítás . Ha az általad,lévő PIC adatlapját tanulmányozod,egész pontosan a Timer 1 rovatot/fejezetet látni fogod a T1CON regiszter leírását is.
A T1CON regiszteren keresztül tudod ezt a periferia egységet beállítani a megfelelő üzemmódnak megfelelően ,amit a feladat megkíván.

Ez az érték mint : T1CON = 0x31; annyit jelent,hogy a nevezetes periferia(most timer) belső óra jelről van üzemeltete,és be van kapcsolva,tehát "időzít".

Ennek a periferiának van további két regisztere (Olyannak képzeld el ezeket mint két preszetelhető számláló).Az említett két regiszter elnevezése : TMR1L és TMR1H. Ez annyit jelent ,hogy ez a periferia(timer) 65536-ig tud számolni. Ezt az értéket az 65536 két bájt- ban lehet tárolni.
Van eegy felső bájt TMR1H és egy alsó bájt regiszter TMR1L.

A programodban mindkettőnek az értéke ,ha jól olvastam nulla. Ez annyit tesz ,hogy nullátol egészen 65536 számol.

*** Periódus idő : függ a Timer1-től a következő modon ÉS EZ A LÉNYEGE AZ EGÉSZNEK:

-Timer 1 belső órajelről üzemel ;
-A belső órajel értéke : Fosc /4 .tehát 4MHz/4 = 1MHz;
-ezt a jelet az 1MHz oztja 65536.Amikor túlcsordul generál egy megszakítást amit kezelni kell.

****Fontos : kívánom,hogy választ találj a problémádra,szerény tudásom szerint igyekeztem felvázolni néhány lényeges dolgot.Annak érdekében,hogy közelebb kerüli a megoldáshoz.

Továbbá elnézés a hosszúra sikeredett levélért ,és távol állt tőlem az "okítás".

További sok sikert kívánok a munkádhoz, a probléma megoldáshoz !

Üdv : Lengyel józsef

0

rainbow555
rainbow555 picture

Szia!

Köszönöm a választ!
Az időzítőkkel nincs gond, ismerem/használom, csak asm nyelven. Biztosan megszakítással megy? Mert nekem nem úgy tűnik.
Nincs gond az okítással sem, mert nem értek a C-hez:)

Kb. ennyit tudtam kihámozni:
nextStep(0, 98, 0)
pass=0, TMR1H=98, és 0-ra állítja a kimenetet
De hogy működik ez a pass ciklus? (egyszer lefut a TMR1H 98-ra állítva?)

Üdv.: Emil

0

Lengyel József
Lengyel József picture

Szia,rainbow555!

A pass egy bájtos előjel nélküli változó. Akkor inkrementálodik amikor a timer1 túl csordul,és az ezt az állapotot jelzó flag bit T1F(megszakítást jelző flag) értéke =1 .Ekkor a pass inkermentálódik: pass++;

Üdv : Józsi

0

rainbow555
rainbow555 picture

Szia!

Köszönöm a magyarázatot!

Oszi fentebb nagyon profin leírta a dolgot, így már sima ügy lesz.

Üdv.: Emil

0

SzG
SzG picture

Szia!
Oszcilloszkópod van?

0

rainbow555
rainbow555 picture

Szia!

Van szkóp (analóg), de sajna nem sokra megyek vele, mert a program átállította a gyári pontosítást (osccal). A leghosszabb impulzus ~700mS, a legrövidebb pedig ~40mS, mindössze 8 lépés és utána ismétli.

Valahogy így néz ki a jel:
kép

0

Sponsored links