Problém s měřením na PIC16f84a a implementovaném kódu v C

Zdravím, dostal jsem úkol změřit proudový odběr na mcu PIC16f84a při jedné operaci šif. algoritmu. Mcu je připojeno na vývojové desce Microchip PICDEM 2 PLUS a vývojové prostředí MPLAB IDE 8.88 a překladač MPLAB XC8 C Compiler v1.12.

V programu jsou dvě proměnné v destítkové soustavě (m,N) a jedna v binární (e) a má fungovat tak, že má procházet všech 8 pozic (0 nebo 1) binární proměnné “e” a u každý pozice provést operaci “SQUARE” a pokud je “e=1” tak i operaci “MULTIPLY”.

cs.wikipedia.org/wiki/Square-and-multiply

Problém mám v tom že u průběhu co měřím osciloskopem (opakuje se s zpožďovací smyčkou mezi) se průběh stále mění, ikdyž se proměnné nemění a křivka by měla být stabilní a když se opakuje tak by měla být stále stejná.

Neporadil by někdo jestli by to šlo nějak lépe sesynchronizovat, popř. jestli nemám v programu nějakou chybu, atd???

#include <pic16f84a.h>				
#include <stdio.h>

#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config CP = OFF
#pragma config FOSC = XT


#define SIG PORTBbits.RB1			

//--------------------------------------
int m,N;
unsigned long int R,V;
unsigned char e,i;							
float j;
//--------------------------------------
//--------------------------------------
int sifr(int m, int N, unsigned char e) 
{				
	R=m;
											
	for(i=0;i<3;i++)					
{

		R=(R*R)%N;						//SQUARE
		
				
		if((e&0b001)==0b001)	
		{
	
		R=(R*m)%N;						//MULTIPLY
							
		}

	
	e = e>>1;					
	
	

}
		
	return(R);						
}

void init()							
{
	STATUSbits.C = 1;				
	TRISB = 0b00000001;
	SIG = 0;

							
	return;								
}
//--------------------------------------
void main()							
{

	init();

	m = 5;
	N = 3;
	e = 0b010;

	while(1)
	{
		SIG = 1;
		V=sifr(m,N,e);
		SIG = 0;
for(j=0;j<50;j++);
	}

}

Akym sposobom meras prudovy odber kde je zapojeny snimaci odpor, predpokladam ze doska je origo a filtracia napajania priamo na pinoch je. T ok. Premena typu int staci.? Simulacia chodi korektne ?

Měřím to proudovou sondou přímo na napájecím pinu mcu a jako synchronizaci používám výstup na desce. A simulace, nejsem v tom tak zkušený… Proměnnou zkusím pozměnit na větši to mě nenapadlo…

Simulaci jsem odzkoušet, hodnoty jsou v pořádku, proměnné také zkontroloval, ale na průběh se stále mění, už nevím co s tím…

Cau, musel sem si to tu precist 4x ! abych pochopil o co tu de :unamused:
tu sinchronizaci mas na RB1/pin 8 ? opravdu
netusim co to ma delat a jakej je pak vysledek ale tady if((e&0b001)==0b001) kdyz se ti meni to e tak se to nekdy vykona a nekdy ne , i za predpokladu ze mas to e na zacatku inicializovany ale pred volanim programu uz ji neinicializujes … moznej problem…?

Ten kod by měl vypadat takhle, zkoušel jsem to simulovat v MPLABu.

/*
 *
 *  Funkce a = x^y
 *
 *
 * příklad: 5^10
 *  10 = 0b00001010
 *
 *
 * 0:0
 * 0:0
 * 0:0
 * 0:0
 * 1:5
 * 0:5^2 = 25
 * 1:25^2 * 5 = 625 * 5 = 3125
 * 0:3125^2 = 9 765 625
 *
 */

#include <htc.h>

__CONFIG(WDTE_OFF & PWRTE_ON & CP_OFF & FOSC_XT);

#define SIG PORTBbits.RB1
//--------------------------------------
unsigned char x, y;
unsigned char j;
unsigned long a;
//--------------------------------------
/*
 * Funkce a = x^y
 * a = (2^0 .. 2^32) - 1
 *
 */
//--------------------------------------
unsigned long sifr(unsigned char zaklad, unsigned char exp)
{
    unsigned char i;
    unsigned char bite = 0b10000000;
    unsigned long R = 0;

    for(i=0;i<8;i++)
    {
       if((exp & bite)>0)
       {
           if(R == 0) R = zaklad;  
           else R = ((R*R)*zaklad);
       }
       else
       {
           R = (R*R);
       }

       bite = bite>>1;   
    }

    return R;
}
 //--------------------------------------
void main(void)
{
    TRISB = 0b00000001;
    SIG = 0;

    x = 5;
    y = 10;
	sifr(0,0);  // jen pro reset proměnných v simulaci

    while(1)
    {
        SIG = 1;
        a = sifr(x,y);
        SIG = 0;

        for(j=0;j<50;j++);
    }
} 

Po proběhnutí výpočtu mi vychází 0x9502F9 = 5^10 = 9 765 625
sifr_simulace.GIF

Stejně nechápu to měření odběru při jednom výpočtu. Pokud se měří odběr proudu, zřejmě se měří na rezistoru v napájecí větvi. Jenže - není-li za rezistorem filtrační kondenzátor, může se procesor rozkmitávat a dělat paseku. Ale pokud se tam filtrační kondenzátor dá, měření bude silně zkreslené. Navíc ty příkazy pro výstup SIG také silně ovlivňují proudový odběr. Správně by se mělo měřit tak, že se bude daná operace neustále opakovat a bude se měřit odběr klidně i multimetrem (ne osciloskopem), ale s filtračním kondenzátorem. Aby se eliminovalo časování smyček, použije se např. blok 10 volání funkce sifr a až tento blok se bude opakovat v nekončené smyčce. Bez jakýchkoliv další operací nebo výstupů.

Díky moc za zdroják a nápady, vyzkouším. Já mám na osciloskopu zobrazit celej ten průběh “a = sifr(x,y)” a jeho proudový odběr ze zdroje pomocí proudový sondy. (za těmi dvoumi výpočetními operacemi má být ještě mod “číslo”), a na osciloskopu by mělo být rozpoznat rozdíl mezi operací “R = (RR) % cislo" a operací "R = ((RR)*zaklad) % cislo”. Jelikož druhá operace by měla být na výpočty proudově náročnější a měl bych z průběhu zjistit exponent (viz priloha jak by to melo pro predstavu vypadat co mě dal vedoucí)
S_a_M.pdf (127 KB)

Ten vzorec nemůžeš jen tak změnit na R = (R*R)%N, ve výsledku bys dostal chybný výsledek. Jediné co můžeš provést je přidat pomocnou proměnnou Z = R%N; tímto nezměníš hodnotu R, ale mělo by se to projevit na změně proudu(asi).

Já jsem to změnil a dopsal modulo, a když jsem si našel stránku na online výpočty na modula, např:

calculatorpro.com/calculator … alculator/

tak mi výsledek v simulaci vycházel správně.

#include <pic16f84a.h>
#include <htc.h> 

__CONFIG(WDTE_OFF & PWRTE_ON & CP_OFF & FOSC_XT); 

#define SIG PORTBbits.RB1 
//-------------------------------------- 
unsigned char x, y; 
unsigned int N;
unsigned char j; 
unsigned long a; 
//-------------------------------------- 
/* 
 * Funkce a = x^y 
 * a = (2^0 .. 2^32) - 1 
 * 
 */ 
//-------------------------------------- 
unsigned long sifr(unsigned char zaklad, unsigned char exp) 
{ 
    unsigned char i; 
    unsigned char bite = 0b10000000; 
    unsigned long R = 0; 

    for(i=0;i<8;i++) 
    { 
       if((exp & bite)>0) 
       { 
           if(R == 0) R = zaklad;  
           else R = ((R*R)*zaklad)%N; 
       } 
       else 
       { 
           R = (R*R)%N; 
       } 

       bite = bite>>1;    
    } 

    return R; 
} 
 //-------------------------------------- 
void main(void) 
{ 
    TRISB = 0b00000001; 
    SIG = 0; 
	
	x = 25; 
    y = 6;
	N = 655; 
 //  sifr(0,0);  // jen pro reset proměnných v simulaci 

    while(1) 
    { 
        SIG = 1; 
        a = sifr(x,y); 
	    SIG = 0; 

        for(j=0;j<50;j++); 
    } 
} 

např.
25^6mod 655=244140625 mod 655 = 510 (1FE)
Bez názvu.png

To ale používáš úplně jiný vzorec než ten původní, vycházel jsem z tohoto:
cs.wikipedia.org/wiki/Square-and-multiply.

tj. a = x^y , ty jsi to změnil na a = (x^y)%N.

Tohle přesně mám měřit, princip je stejnej ne?

Není myšleno aby bylo N mocnina dvou, jen proto aby se výsledek vešel do proměnných (např. N=0x10000)? Rozdíl rychlosti by byl markantní, namísto složité operace modulo by se dělalo jen rychlé maskování výsledku AND.

Je to možné… Jak by pak ale vypadal zdrojový kód? :frowning:

Jestli je N jen symbolický zápis kvůli omezení rozsahu výsledku, tak pak se část “%N” prostě vypustí a výsledek se bude ukládat do R (s tím, že se bude počítat, že přetečení výsledku se ignoruje).

Tak i tak, jsem to byl měřit a průběh se stále mění, ikdyž se opakuje stále to stejné se zpoždovací smyčkou mezi, nechápu co se tam mění za data…

Podla mna namerate nemeratelny res nepodstany rozdiel. Hod tam kod s vypoctom bez casovej pauzy. Zmeraj v mplabe ako dlho trva prechod jedneho cyklu, a zmeraj prud, potom nahraj do up len program s casovou sluckou ktorej dlzka odpoveda zmeranej dobe cyklu nahraj do uP a zmeraj odber

Já nemám změřit určitou hodnotu nebo velikost proudu, ale jde mi o ten přůběh(křivku) kdy by měl být poznat ten rozdíl. Jen jestli se dobře chápem :wink:

Nastavil jsem tedy v simulaci oscilátor kterej mám na desce (4MHz), změřit jsem dobu a ta přesně odpovídá hodnotě co jsem změřil na osciloskopu.

Zmeras prud pri kode kde sa robi vypocet a potom nahrajes do uP len casovu slucku a zmeras prud. Ide o vysledok ak tam bude nejaka zmena badaj dalej ak nie tak je vsetko zbytocne, navyse nikto nepovedal ze tak ako to mas robit je jediny spravny a dokonaly postup. Ide o to ze ten procesor vykonava instrukcie aj v casovej slucke. Proste to nieje Intel o frekvencii 2GHz s mechanizmami uspory energie. Na setrenie je sleep rezim.

A nameral si nejky rozdiel medzi vypoctom a casovou sluckou? Mas to hotove teda?