Sari la conținut
ELFORUM - Forumul electronistilor

PIC 18F2550 - scrierea in LATB inhibia conversia


Vizitator mitumunteanu

Postări Recomandate

Vizitator mitumunteanu

Salutare. 

 

Am scris un cod pentru pic-ul 18F2550 in care citesc valoare de la un senzor de temperatura (LM35) pe canalul AN0, apoi o convertesc si o afisez pe un display cu 7 segmente ce are 4 digiti (RC0 - digit1, RC1 - digit2, RC2 - digit3, RC6 - digit4).

Portul B l-am folosit pentru cele 7 segmente ale fiecarui digit (A-RB0, B-RB1 ... G-RB6, * - RB7).

 

Am rulat programul cu un debugger, punand break pointuri in functia in care tratez intreruperile.

Prima conversie (cea pornita in main) este ok (registrii ADRESL si ADRESH sunt actulalizati cu o valoare intre 0 - 1023).

Dupa ce scriu o valoare o valoare in portul B (functia DisplayDigit, instructiunea LATB = value), toate celelalte conversiile imi pun 0x00 in registrii ADRESL si ADRESH.

Are cineva idee de ce se intampla asta?

 

 

#include <xc.h>#include <stdint.h>// #pragma config statements should precede project file includes.// Use project enums instead of #define for ON and OFF.// CONFIG1L#pragma config PLLDIV = 1       // PLL Prescaler Selection bits (No prescale (4 MHz oscillator input drives PLL directly))#pragma config CPUDIV = OSC1_PLL2// System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2])#pragma config USBDIV = 1       // USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) (USB clock source comes directly from the primary oscillator block with no postscale)// CONFIG1H#pragma config FOSC = INTOSCIO_EC // Oscillator Selection bits (Internal oscillator, port function on RA6)#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)// CONFIG2L#pragma config PWRT = OFF       // Power-up Timer Enable bit (PWRT disabled)#pragma config BOR = OFF        // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)#pragma config BORV = 3         // Brown-out Reset Voltage bits (Minimum setting 2.05V)#pragma config VREGEN = OFF     // USB Voltage Regulator Enable bit (USB voltage regulator disabled)// CONFIG2H#pragma config WDT = OFF       // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)// CONFIG3H#pragma config CCP2MX = ON      // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)#pragma config PBADEN = OFF     // PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)#pragma config LPT1OSC = OFF    // Low-Power Timer 1 Oscillator Enable bit (Timer1 configured for higher power operation)#pragma config MCLRE = OFF      // MCLR Pin Enable bit (RE3 input pin enabled; MCLR pin disabled)// CONFIG4L#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)#pragma config LVP = OFF        // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))// CONFIG5L#pragma config CP0 = OFF        // Code Protection bit (Block 0 (000800-001FFFh) is not code-protected)#pragma config CP1 = OFF        // Code Protection bit (Block 1 (002000-003FFFh) is not code-protected)#pragma config CP2 = OFF        // Code Protection bit (Block 2 (004000-005FFFh) is not code-protected)#pragma config CP3 = OFF        // Code Protection bit (Block 3 (006000-007FFFh) is not code-protected)// CONFIG5H#pragma config CPB = OFF        // Boot Block Code Protection bit (Boot block (000000-0007FFh) is not code-protected)#pragma config CPD = OFF        // Data EEPROM Code Protection bit (Data EEPROM is not code-protected)// CONFIG6L#pragma config WRT0 = OFF       // Write Protection bit (Block 0 (000800-001FFFh) is not write-protected)#pragma config WRT1 = OFF       // Write Protection bit (Block 1 (002000-003FFFh) is not write-protected)#pragma config WRT2 = OFF       // Write Protection bit (Block 2 (004000-005FFFh) is not write-protected)#pragma config WRT3 = OFF       // Write Protection bit (Block 3 (006000-007FFFh) is not write-protected)// CONFIG6H#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) are not write-protected)#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot block (000000-0007FFh) is not write-protected)#pragma config WRTD = OFF       // Data EEPROM Write Protection bit (Data EEPROM is not write-protected)// CONFIG7L#pragma config EBTR0 = OFF      // Table Read Protection bit (Block 0 (000800-001FFFh) is not protected from table reads executed in other blocks)#pragma config EBTR1 = OFF      // Table Read Protection bit (Block 1 (002000-003FFFh) is not protected from table reads executed in other blocks)#pragma config EBTR2 = OFF      // Table Read Protection bit (Block 2 (004000-005FFFh) is not protected from table reads executed in other blocks)#pragma config EBTR3 = OFF      // Table Read Protection bit (Block 3 (006000-007FFFh) is not protected from table reads executed in other blocks)// CONFIG7H#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot block (000000-0007FFh) is not protected from table reads executed in other blocks)//***********  ***********// typedef unsigned char uint8;typedef char int8;typedef unsigned short int uint16;typedef short int int16;typedef unsigned int uint32;typedef int  int32;#define ADC_Vref 5#define ADC_MaxCounter 25 // 25 - 100ms#define Digit1 LATCbits.LATC0#define Digit2 LATCbits.LATC1#define Digit3 LATCbits.LATC2#define Digit4 LATCbits.LATC6 // ********** function prototype *************//void __interrupt ISR();void SYS_init();uint8 getLookup_value(uint8 number);void DisplayDigit(uint8 digit, uint8 Value);void ADC_start();void Set_index();void Convert ();void Display();// ********** Lookup table *************//const uint8 Lookup_t[10] = {0xC0,		//	'0'							0xF9,		//	'1' 							0xA4,		//	'2' 							0xB0,		//	'3' 							0x99,		//	'4' 							0x92,		//	'5' 							0x82,		//	'6' 							0xF8,	 	//	'7'							0x80,	 	//	'8'							0x90};		//	'9'// ********** Global variables ***********//uint16 ADC_result;uint16 ADC_Counter = 0;uint8 Display_index[4];uint16 ADC_ConvertResult;uint8 Current_index = 1;// *********** MAIN *********** //void main(void) {    SYS_init();	ADC_start();	// debug	    while (1){	}}//********* INTERRUPT **********//void __interrupt ISR() {	if (INTCONbits.TMR0IF)	{		Display();	// 32 uS		if (ADC_Counter == ADC_MaxCounter){				ADC_Counter = 0;				ADC_start();			// every 250 ms		}		else{			ADC_Counter++;		}		INTCONbits.TMR0IF = 0;	}	if(PIR1bits.ADIF)	{		Set_index();		// 1 mS		PIR1bits.ADIF = 0;	}}//********* SYS_init **********//void SYS_init() {	// OSC config	OSCCON = 0x70;		// oscilator frequency - 8MHZ	// ADC init	ADCON1 = 0x0E; 		// 	ADCON0 = 0x00;		// 		TRISAbits.RA0 = 1;				ADCON2 = 0xBE;		// 		ADCON0bits.ADON = 1;	//Timer0	T0CON = 0xD4;  	 // interrupt on every 4ms	// PORTB init	LATB = 0xFF;		// 	TRISB = 0x00;		// 	LATC = 0xFF;	TRISC = 0x00;		// Interrupt	PIR1bits.ADIF = 0;		//clear A/D interrupt flag	PIE1bits.ADIE = 1;		//enable A/D interrupt	INTCONbits.PEIE = 1;	//enable periferial interrupt	INTCONbits.GIE = 1;		//enalbe gloabal interrupt		INTCONbits.TMR0IE = 1;}//********* getLookup_value **********//uint8 getLookup_value(uint8 number){	return Lookup_t[number];}//********* ADC_start **********//void ADC_start(){	ADCON0bits.GO = 1;}//********* Convert **********//void Convert (){	float buffer = ADC_result * ADC_Vref * 100/1024.;	ADC_ConvertResult = buffer*100;}//********* DisplayDigit **********//void DisplayDigit(uint8 digit, uint8 Value){	Digit1 = 1;	Digit2 = 1;	Digit3 = 1;	Digit4 = 1;		switch (digit){		case 1:			LATB = Value;			Digit1 = 0;		break;				case 2:			LATB = Value + 0x80;			Digit2 = 0;		break;		case 3:			LATB = Value;			Digit3 = 0;		break;		case 4:			LATB = Value;			Digit4 = 0;		break;	}	}//********* Set_index **********//void Set_index(){			ADC_result = (ADRESH << 8) + ADRESL;			Convert();					Display_index[0] =  ADC_ConvertResult/1000;			Display_index[1] = (ADC_ConvertResult/100)%10;			Display_index[2] = (ADC_ConvertResult/10)%10;			Display_index[3] =  ADC_ConvertResult%10;}//********* Display **********//void Display(){			uint8 Display_value = getLookup_value(Display_index[Current_index-1]);		DisplayDigit(Current_index,Display_value);	if(Current_index < 4){		Current_index++;	}	else{	Current_index = 1;	}}

 

Link spre comentariu
  • Răspunsuri 8
  • Creat
  • Ultimul Răspuns

Top autori în acest subiect

Zile populare

Top autori în acest subiect

Cateva idei.

 

- 18F2550 are o errata cat o zi de post. Merita citita, s-ar putea sa te lovesti de ceva mentionat acolo.

- Stiu ca ai pragma-ul PBADEN = OFF dar merita sa pui si ANSELH = 0 (sau ce nume are registrul ANSEL pentru PORTB) in SYS_init().

Editat de mars01
Link spre comentariu

Eu nu prea ma prind care e scopul folosirii lui TMR0 in acest program .... E un exercitiu pe baza de intreruperi si timer ?

if(PIR1bits.ADIF)	{		Set_index();		// 1 mS		PIR1bits.ADIF = 0;	}

cand executi asta nu cumva TMR0 va genera o alta intrerupere ?

Editat de djvas
Link spre comentariu

@djvas

"Heart rate" - din cate vad totul se intampla pe tick-ul TMR0. Display() se executa odata la 4ms (tick-ul TMR0) deci este responsabil si de refresh rate pt digiti.

 

cand executi asta nu cumva TMR0 va genera o alta intrerupere ?

 

Ai un punct de vedere.

OP mai bine pune niste flag-uri in intrerupere cu care cheama functiile care sunt pe acolo. Inainte de set_index() se face disable la TMR0 si dupa ce se termina set_index() se face din nou enable la TMR0. 

 

Si ca un sfat pt @mitumunteanu, in ISR, in loc de:

if (INTCONbits.TMR0IF)

foloseste:

if (INTCONbits.TMR0IE && INTCONbits.TMR0IF)

TMR0IF este setat periodic indiferent daca intreruperea este activa sau nu.

Note: Interrupt flag bits are set when an interrupt condition occurs regardless of the state of its corresponding enable bit or the global interrupt enable bit. User software should ensure the appropriate interrupt flag bits are clear prior to enabling an interrupt. This feature allows for software polling.

Editat de mars01
Link spre comentariu

Eu nu prea ma prind care e scopul folosirii lui TMR0 in acest program .... E un exercitiu pe baza de intreruperi si timer ?

if(PIR1bits.ADIF)	{		Set_index();		// 1 mS		PIR1bits.ADIF = 0;	}

cand executi asta nu cumva TMR0 va genera o alta intrerupere ?

Nu, pentru ca la intrarea in rutina de tratare intreruperi intreruperile sunt deactivate. Sunt sanse, in schimb, sa piarda intreruperi de la TMR0. Recomandat e ca in functiile interrupt sa se stea cat mai putin.

Link spre comentariu
Vizitator mitumunteanu

Nu se pierd intreruperi de la TMR0, desi exista posibilitatea ca TMR0 sa de-a overflow in timp ce se executa  

	if(PIE1bits.ADIE && PIR1bits.ADIF)	{		Set_index();		// 1 mS		PIR1bits.ADIF = 0;	}

si atunci intreruperea de la TMR0 este amanata pana se termina cu intreruperea de la ADC

Editat de mitumunteanu
Link spre comentariu
Sa inteleg ca  TMR0 (cazul nostru ) nu va genera alta intrerupere pana cand nu e gata si codul de mai jos ?

Cel mai simplu de raspuns la intrebari ramane cititul documentatiei. Citat din sectiune "Intreruperi" in foaia de catalog a PIC 18F2550 - capitolul 9, pagina 99:

 

When an interrupt is responded to, the global interruptenable bit is cleared to disable further interrupts. If theIPEN bit is cleared, this is the GIE bit. If interrupt prioritylevels are used, this will be either the GIEH or GIEL bit.High-priority interrupt sources can interrupt a low-priority interrupt. Low-priority interrupts are notprocessed while high-priority interrupts are in progress.The return address is pushed onto the stack and thePC is loaded with the interrupt vector address(000008h or 000018h). Once in the Interrupt ServiceRoutine, the source(s) of the interrupt can be deter-mined by polling the interrupt flag bits. The interruptflag bits must be cleared in software before re-enablinginterrupts to avoid recursive interrupts.The “return from interrupt” instruction, RETFIE, exitsthe interrupt routine and sets the GIE bit (GIEH or GIELif priority levels are used) which re-enables interrupts. 

Sunt convins ca aceleasi informatii stau in toate foile de catalog pentru picurile 16F/18F.

 

PS Am bolduit eu sectiunile despre care vorbim aici.

Si pentru ca probabil n-o sa mai pot posta citate, folosesc code
Nu se pierd intreruperi de la TMR0, 
Probabil in cazul de fata nu, da' tot e "bad practice".
Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum



×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări