16F690 ses kayıt devresi uyku modu...

Başlatan akrepefe007, 30 Eylül 2015, 14:17:39

akrepefe007



arkadaşlar bu devreyi yaptım . akım verince 0.08 A akım çekiyor. devreye akım verdiğimizde uyku moduna almak için kod yazdım fakat uyku moduna girmiyor. nerde yanlış yapıyorum acaba? derleyici Hi-tech C ya da mplab xc8 . bunlarn uyku modu kodu SLEEP(); değil mi? AŞağıda yazılımı paylaştım. SLEEP();kodunu main içerisinde While(1){} içerisine yazdım. kısacası butonlara basılmadıgı zaman uyku modunda kalması için ne yapmalıyım. kod mu yanlış kodun yeri mi bilmiyorum.

#include <htc.h>
#include <pic16f690.h>

#if defined(__XC8)
  #pragma config FOSC=HS, CP=OFF, CPD=OFF, WDTE=ON, BOREN=OFF, MCLRE=OFF
#else defined(COMPILER_MPLAB_PICC)
  __CONFIG(WDTDIS & UNPROTECT & HS & MCLRDIS & UNPROTECT & BORDIS & PWRTDIS);
#endif

#define CS RC2		//chip select input
#define Stop RA2	//stop pushbutton
#define Play RB5	//play PB
#define Rec RB7		//record PB
#define Pause RA1	//pause PB
#define RecLED RC0
#define errorLED RC1
#define sdLED RC4	//SD or SDHC optional LED
int a,b;

//prototypes
unsigned char SPI(unsigned char data);
char Command(unsigned char frame1, unsigned long adrs, unsigned char frame2 );
void InitSD(void);
void main(void);
void WriteSD();
void ReadSD();
void Sayac(void);



unsigned long loc;	//pause location
unsigned char sdhc=0;	//standard sd

void main(void)
{
	OSCCON = 0B1110001;	//8MHz,
	// PIC I/O init
	ANSEL = 0;
	ANSELH = 0;
	TRISC = 0b1000000;		//  rc5=CPP1.
	TRISA = 0b110;   	// switches
	TRISB = 0b10111111;
	//pullup on
	#if defined(__XC8)
    	nRABPU = 0;
    #else defined(COMPILER_MPLAB_PICC)
    	RABPU = 0;
    #endif
	WPUA1 = 1;
	WPUA2 = 1;
	WPUB5 = 1;
	WPUB7 = 1;

	ANS8 = 1;	//analogue chan 8
	RecLED = 0;
	errorLED = 0;
	sdLED = 0;

	//analogue init
	CCP1CON = 0B1100;	//PWM mode
	PR2 = 100;	//20KHz
	T2CON = 0B100;	//prescale 1, post scale 1, timer2 on
	ADCON1 = 0B1010000;		// Fosc/16.
	ADCON0 = 0B10100000;	// ref=Vdd, right just, AN8, AD off

	//SPI init
	SSPCON = 0B110010;	//low speed osc/64(125kHz),enabled,clock idle=H
        
	CS = 1; 		// disable SD
        
	InitSD();
	if(sdhc){loc = 10;}else{loc = 5120;}	//SD or SDHC
	while(1) {

        if(!Play)ReadSD();
	if(!Rec) WriteSD();
        if(!Stop) {
		Sayac();
                     }
SLEEP();                  }
}


unsigned char SPI(unsigned char data)		// send character over SPI
{
	SSPBUF = data;			// load character
	while (!BF);		// sent
	return SSPBUF;		// received character
}


char Command(unsigned char frame1, unsigned long adrs, unsigned char frame2 )
{
	unsigned char i, res;
	SPI(0xFF);
	SPI((frame1 | 0x40) & 0x7F);	//first 2 bits are 01
	SPI((adrs & 0xFF000000) >> 24);		//first of the 4 bytes address
	SPI((adrs & 0x00FF0000) >> 16);
	SPI((adrs & 0x0000FF00) >> 8);
	SPI(adrs & 0x000000FF);
	SPI(frame2 | 1);				//CRC and last bit 1

	for(i=0;i<10;i++)	// wait for received character
	{
		res = SPI(0xFF);
		if(res != 0xFF)break;
	}
	return res;
}

void InitSD(void)
{
	unsigned char i,r[4];

	CS=1;
	for(i=0; i < 10; i++)SPI(0xFF);		// min 74 clocks
	CS=0;			// Enabled for SPI mode

	i=100;	//try enter idle state for up to 100 times
	while(Command(0x00,0,0x95) !=1 && i!=0)
	{
		CS=1;
		SPI(0xFF);
		CS=0;
		i--;
	}
	if(i==0)	errorLED = 1;	//idle failed

	if (Command(8,0x01AA,0x87)==1){					//check card is 3.3V
		r[0]=SPI(0xFF); r[1]=SPI(0xFF); r[2]=SPI(0xFF); r[3]=SPI(0xFF);		//rest of R7
		if ( r[2] == 0x01 && r[3] == 0xAA ){ 		//Vdd OK (3.3V)

			//Command(59,0,0xFF);		//CRC off
			Command(55,0,0xFF);
			while(Command(41,0x40000000,0xFF)){Command(55,0,0xFF);} 	//ACMD41 with HCS bit
			}
	}else{errorLED = 1;}

	if (Command(58,0,0xFF)==0){		//read CCS in the OCR - SD or SDHC
		r[0]=SPI(0xFF); r[1]=SPI(0xFF); r[2]=SPI(0xFF); r[3]=SPI(0xFF);		//rest of R3
		sdhc=r[0] & 0x40;
		if(r[0] & 0x40)sdLED=1;
	}

	SSPM1 = 0;	// full speed 2MHz
	CS = 1;
}

void WriteSD(void)
{
	
}

void ReadSD(void)
{
	unsigned int i,r;
	unsigned char data;
	aq:
        Command(12,0x00,0xFF);	//stop transmit
	SPI(0xFF);
	SPI(0xFF);
	CS = 0;
        SPI(0xFF);
	SPI(0xFF);
        Command(12,0x00,0xFF);	//stop transmit
	SPI(0xFF);
	SPI(0xFF);
        if(sdhc){loc = 10;}else{loc = 5120;}
        r = Command(18,loc,0xFF);	//read multi-sector
	if(r != 0)errorLED = 1;			//if command failed


	while(Stop && Pause)
	{
		while(SPI(0xFF) != 0xFE)continue;	// wait for first byte

		for(i=0;i<512;i++){
			while(!TMR2IF){}
			data = SPI(0xFF);
			DC1B1 = data & 1;	//shift byte to get the required PWM duty cycle
			CCPR1L = (data >> 1);
			TMR2IF = 0;
                        if(!Play)goto aq;
                        
                }
                
               	SPI(0xFF);	//discard of CRC
		SPI(0xFF);
                Sayac();
        }

	Command(12,0x00,0xFF);	//stop transmit
	SPI(0xFF);
	SPI(0xFF);
	CS = 1;

}


void Sayac(void){
       CS=1;
        if(sdhc){loc = 10;} else{loc = 5120;}
       SLEEP();
       CS=0;
        SPI(0xFF);
        SPI(0xFF);
        Command(12,0x00,0xFF);	//stop transmit
	SPI(0xFF);
	SPI(0xFF);
       


akrepefe007

arkadaşlar sıkıntı nerde bilen varmı?  :( :-[ :-\ :'(

Gökhan BEKEN

16f887 için bir low power fonksiyonum vardı , olduğu gibi ekliyorum, dikkat edilmesi gereken şey, low moda sokmadan önce pinlerin modularını ayarlamak, çalışan timer adc gibi kısımları iptal etmek.


void DusukMod(void) {
    INTCONbits.GIE = 0;
    OPTION_REGbits.nRBPU = 1; //PORTB pull-ups are disabled
    INTCONbits.T0IE = 0; //timer kesmesi kapali
    //T0CONbits.TMR0ON = 0;

    ADCON0bits.ADON = 0; //ADC is disabled
    ADCON0bits.CHS = 3; //Selects channel 0 ( AN3 )

    VRCONbits.VREN = 0; //datasheet sayfa 99 CVREF=0

    //TRISEbits.TRISE3=1; //MCLR
    //PORTEbits.RE3=0;


    //pinler:
    //led sat?r:
    TRISBbits.TRISB0 = 0;
    PORTBbits.RB0 = 1;

    TRISBbits.TRISB1 = 0;
    PORTBbits.RB1 = 1;

    TRISBbits.TRISB2 = 0;
    PORTBbits.RB2 = 1;

    TRISBbits.TRISB3 = 0;
    PORTBbits.RB3 = 1;

    TRISBbits.TRISB4 = 0;
    PORTBbits.RB4 = 1;

    //led sutun:
    TRISCbits.TRISC5 = 1;
    PORTCbits.RC5 = 0;

    TRISCbits.TRISC6 = 1;
    PORTCbits.RC6 = 0;

    TRISCbits.TRISC7 = 1;
    PORTCbits.RC7 = 0;

    //butonlar:
    TRISCbits.TRISC0 = 1; //denedik, bunlar cikis olursa cok akim cekiyor
    PORTCbits.RC0 = 0; //buton

    TRISCbits.TRISC1 = 1; //denedik
    PORTCbits.RC1 = 0; //motor

    //ADC'Ler:
    TRISAbits.TRISA3 = 0; //denedik farketmedi
    PORTAbits.RA3 = 0; //LDR

    TRISBbits.TRISB5 = 1; //denedik
    PORTBbits.RB5 = 0; //GSM

    TRISAbits.TRISA5 = 1; //denedik
    PORTAbits.RA5 = 0; //3G

    TRISAbits.TRISA0 = 1; //denedik
    PORTAbits.RA0 = 0; //UHF

    //kontroller:
    TRISCbits.TRISC4 = 1; //denedik
    PORTCbits.RC4 = 0; //GSM

    TRISAbits.TRISA7 = 1; //denedik
    PORTAbits.RA7 = 0; //3G

    TRISAbits.TRISA1 = 1; //denedik
    PORTAbits.RA1 = 0; //UHF

    TRISCbits.TRISC3 = 1; //denedik
    PORTCbits.RC3 = 0; //RF

    TRISCbits.TRISC2 = 0; //denedik
    PORTCbits.RC2 = 0; //MOTOR

    TRISAbits.TRISA4 = 1; //LDR
    PORTAbits.RA4 = 0; //denedik


    //kullanilmayanlar:
    TRISBbits.TRISB6 = 1; //denedik
    PORTBbits.RB6 = 0;

    TRISBbits.TRISB7 = 0; //denedik
    PORTBbits.RB7 = 1;

    TRISAbits.TRISA2 = 1; //denedik
    PORTAbits.RA2 = 0; //test point 1

    TRISAbits.TRISA6 = 1; //denedik
    PORTAbits.RA6 = 0; //test point 2


    __delay_ms(3000);

    WDTPS0 = 0x1011;

    while (1) {
        SWDTEN = 1; //wdt aktif
        SLEEP();
        SWDTEN = 0; //wdt pasif, calisma modu
        if (!INPUT_PIN_BUTON) {
            SWDTEN = 1; //software reset icin //wdt aktif
            while (1);
        }

    }


    //SLEEP();

}
Özel mesaj okumuyorum, lütfen göndermeyin.

akrepefe007

peki Gökhan bey onu deniyeceğim. sizin kodda uyku moduna girdikten sonra tekrar çalışma kodu geliyor. uyku modundan çıkma işlemini ne yapıyor? butonlara basmak mı? ben bir fonksiyon yazayım uyku modu için . dediğiniz gibi timer adc leri iptal edeyim. sonra da uyku moduna alayım. şöyle ki
uyku(void)
{
...//adc iptal
...//timer iptal
...// vs.
SLEEP();
}

burda mesala benim devre uyku moduna girerse geri çıkması için devrede bir butona basmam yeterli mi?uyku modundan çıkınca tekrar adc ,timer vs. aktif etmem gerekmiyor mu=? bu konularda pek çalışmadığım için sorularım basit y a da saçma olabilir. kusuruma bakmayın...
teşekkür ederim bu arada yardımınız için.

Gökhan BEKEN

Koddaki
if (!INPUT_PIN_BUTON) {
            SWDTEN = 1; //software reset icin //wdt aktif
            while (1);
}

kısmına dikkat edin, siz istediğiniz kadar sleep moduna sokun, program çalışmaya devam edecek, bu yüzden sonsuz döngüde bekletmek gerekiyor.
Sonsuz döngüden arada bir çıkıp, butonu kontrol etmesi lazım. Sonsuz döngüden çıkmasını sağlamak için watch dog timer kullanmanız lazım. Belli bir sürede çıkıp butonu kontrol edecek, basıldıysa bu moddan çıkacak.
Özel mesaj okumuyorum, lütfen göndermeyin.

akrepefe007

tamam işte bakın ben de main içerisinde
while(1) {
SLEEP();
        if(!Play)ReadSD();
	if(!Rec) WriteSD();
        if(!Stop) {
		Sayac();

        }

içerisinde butonlar kontrol ettiriyorum zaten. sanırım benim sıkıntım wdt olayı. ya da dediğiniz gibi timer ve adc kısımları fakat bunu nasıl yapacagımı henüz bilmiyorum. kod SLEEP(); değil mi bunda hemfikiriz?

Gökhan BEKEN

ReadSD ve WriteSD fonksiyonları sd kart ile ilgiliyse sıkıntı var. Uyku sırasında sd kartla konuşursanız o uykudan hayır gelmez, yine akım çekersiniz.
WDT'ı kullanın zor değil zaten, yukarıda eklediğim kodlar dışında sigorta ayarlarından da WDT ON yapın.
TIMER ve ADC'nin nasıl açılıp kapatılacağı chip'e göre değişir, datasheet'ten ilgili register'ları bulun.
SLEEP uyku için yeterli ama sağlıklı uyku için takım elbisenizi çıkartıp pijamalarınızı giymeniz gerekiyor. Bu yüzden kullandığınız her çevre birimini kapatmanız gerekiyor, uykudan çıktıktan sonra tekrar aktif etmeniz de şart.
Özel mesaj okumuyorum, lütfen göndermeyin.

akrepefe007

Alıntı YapReadSD ve WriteSD fonksiyonları sd kart ile ilgiliyse sıkıntı var
elbette . writeSD sd karta ses kaydıı için . butona basınca bu fonksiyon çalışıyor. ReadSd de aynı şekilde kaydı dinlemek için.
Alıntı YapBu yüzden kullandığınız her çevre birimini kapatmanız gerekiyor, uykudan çıktıktan sonra tekrar aktif etmeniz de şart.
Wdt ı on yaptım zaten ben . timer ve adc sıfırlama yerini bulamadım henüz. o konuları ddediğiniz gibi datasheetten bir araştırayım. inşallah yapabilirim.

akrepefe007

uyku moduna girip çıkıyor sürekli anlamadım gitti. giriyor 2 3 saniye bekliyor sonra çıkıyor.aynı şekilde 2 3 saniye bekleyip tekrar giriyor uyku moduna. Devreyi Deneme imkanı olan var mı acaba?

akrepefe007

WDT aktif  ettiğim içn program 2 3 saniyede bir yeniden başlıyor. WDT aktif edince neden böyle oluyor. yardımcı olabilecek var mı? yazılımda neresi etkileniyor olabilir? WDT'ı aktif yapmadan uyku moduna girilmiyor mu?

akrepefe007

şöyle bir kod yazdım ama... wdt'ı döngü içinde aktif yaptım. devre play işlemi yapmıyor artık:) öyle bekliyor.
while(1) {
           while(1) {
            if(Stop && Play && Rec ){
                          WDTCON=1;
                          SLEEP();
           }
	if(!Rec) WriteSD();
	if(!Play) ReadSD();
	if(!Stop) {
		if(sdhc){loc = 10;}else{loc = 5120;}
	}

SPI haberleşmeden dolayı mı uyku moduna girmiyor.? SPI haberleşme üzerinde çalışan var mı? ??? ??? :-\ :-\ ???