problem med uart interrupt och timer interrupt

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Christian
Inlägg: 86
Blev medlem: 3 november 2003, 22:54:49

problem med uart interrupt och timer interrupt

Inlägg av Christian »

Hej,
Jag skriver kod för att ta emot data via UART samtidigt som jag genererar 3 st PWM signaler mha interrupt på Timer0. När jag fått in relevant data sparas detta undan i en array som sedan skrivs ut via UART.
Jag har märkt att om jag kör init_timer(); så går inte processorn varken in i main() och heller inte in i switch-satsen som finns i ISR:en för UART delen.
Men om jag utesluter init_timer(); så kommer jag in i switch-satsen och relevant data läggs in i min array för att sedan skrivas ut i main(). Då kommer naturligtvis inga PWM signaler..
Har kontrollerat allt med en logikanalysator och kan se att mina PWM signaler kommer när jag kör med init_timer() men det kommer ingen utskrift från UARTen.

Har även kört ett eko direkt när jag tar emot ett tecken på UART dvs. c = RCREG; --> putch(c); och då kommer data.. Men den går aldrig in i switchen..

Kan detta ha att göra med prioritet i ISR? Jag har ju två olika typer av avbrott UART och Timer0.. Är det att processorn helt enkelt inte hinner gå in i switchen?

Någon som tror sig veta svaret på denna "gåta"?

För övrigt så är det fråga om en PIC18F14k50 med intern osc på 16MHz och Hi-techs kompilator..

Kod: Markera allt

#include <htc.h>
//#include "delay.h"
#include <stdio.h>  
#include <stdlib.h>
#include <stdarg.h> 
#include <math.h>
#include "math.h"
#define LED1 LATC2
#define LED2 LATC1
#define LED3 LATC0
unsigned int t = 0;
unsigned char duty_LED1,duty_LED2,duty_LED3;
#define PWM_LIMIT 465
enum {START_WAIT, RECEIVING, MSG_RECEIVED} state = START_WAIT; 
#define BUFFMAX 80
unsigned char gps_string[BUFFMAX] = 0;   //Databuffer
int head = 0; 
void init_PIC(void);
void init_interrupts();
void usart(void);
void init_timer(void);
void interrupt pic_isr(void);
void putch(unsigned char c);


void main(void){
	duty_LED1 = 53;
	duty_LED2 = 42;
	duty_LED3 = 28;
	
	init_PIC();
	usart();
	init_interrupts();
	TMR0 = 255;
	//init_timer();
	while(1){
		
		if(state == MSG_RECEIVED){

			if(gps_string[4]=='C'){
				
				for(int i = 0; i<head; i++){
					putch(gps_string[i]);
				}
				
			}
			state = START_WAIT;
		}
	}
}
void init_PIC(void){
	OSCCON =0b11111111;   //Internal 16MHz
	OSCCON2 =0b00000000;
	OSCTUNE = 0b00000000;
	TRISC = 0; 
	PORTC = 0;
}

void init_interrupts(void){
	GIE = 1;  		//*Interrupts
	PEIE = 1;
	TXIE = 0; 		//Disable transmit interrupt
	RCIE = 1; 		//Enable receive interrupt
    TMR0IE = 1;		//TMR0 overflow enable bit
    TMR0IF = 0; 	//TMR0 overflow flag bit
}
void usart(void){
	TRISB = 0XFF;
	TXEN = 1; 		//Allows sending
	SYNC = 0; 		//The SYNC bit should be cleared to select asynchronous operation.
	SPEN = 1; 		//SPEN bit is used to enable the entire serial port
	ANSELH = ANSELH & 0b11110111; //ANSELH(3) ANS11: RB5 Analog Select Control bit,  0 = Digital input buffer of RB5 is enabled 
	BRGH = 0;
	SPBRG = 51;		// 4800  
	BRG16 = 0;
	TX9 = 0;
	RX9 = 0;
	CREN = 0;
	CREN = 1; 		//Allows receiving
}
void init_timer(void){
	T08BIT = 1;
	T0CS = 0;	//timer mode
    T0SE = 0;
    PSA = 1;	// prescaler
    T0PS0 = 1;
    T0PS1 = 1;
    T0PS2 = 1;
	TMR0ON = 1; 
}
void interrupt pic_isr(void) {  
    unsigned char c;

	if((RCIE)&&(RCIF)){                                  // If this interrupt was generated by a receive character  

		c = RCREG;
		//putch(c);
	 	switch(state){
		 			
			case START_WAIT:
				
				if(c == '$'){
						
					head = 0;
					state = RECEIVING;
				}
				break;
			case RECEIVING:
				
				if(c == '*'){
					
					state = MSG_RECEIVED;
				}
				else{
					gps_string[head] = c;	   
				
					if(++head >= sizeof(gps_string)){
                   		state = START_WAIT;
            	 	}
								
				}
				break;	
		}

	}
if (TMR0IF == 1) {
		TMR0IF = 0;
		if(t<=duty_LED1){
			LED1 = 1;
		}
		else if(t>duty_LED1){
			LED1 = 0;
		}
		if(t<=duty_LED2){
			LED2 = 1;
		}
		else if(t>duty_LED2){
			LED2 = 0;
		}
		if(t<=duty_LED3){
			LED3 = 1;
		}
		else if(t>duty_LED3){
			LED3 = 0;
		}
		t++;
		if(t>PWM_LIMIT){
			t = 0;
		}
		TMR0 = 255;
		
	}
	if(OERR){           // If we missed a character (Overrun Error) 
    	CREN = 0;       // Reset the error bit  
		CREN = 1;
	}
	if(FERR){           // If Framing Error 	
  		c = RCREG;      // Reset the error bit
		CREN = 0;       // Reset the error bit  
		CREN = 1;
	}
}

void putch(unsigned char c){ 
	while(!TXIF) 	//Set when TXREG is empty
	continue; 		//Continue looping while TXREG is not available
	TXREG = c; 		//Put character to be sent onto TXREG 

}
mvh / Christian
Christian
Inlägg: 86
Blev medlem: 3 november 2003, 22:54:49

Re: problem med uart interrupt och timer interrupt

Inlägg av Christian »

När jag minskar frekvensen på TIMER0 så fungerar det.. Alltså måste det berott på att det blir interrupt på TIMER0 för ofta för att processorn ska hinna göra något annat..
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: problem med uart interrupt och timer interrupt

Inlägg av sodjan »

> Alltså måste det berott på att det blir interrupt på TIMER0 för ofta...

Hur ofta var det ?
bos
Inlägg: 2311
Blev medlem: 24 februari 2007, 23:29:15
Kontakt:

Re: problem med uart interrupt och timer interrupt

Inlägg av bos »

Jag orkar inte sätta mig in i problemet i detalj, men något jag höjer ögonbrynen över direkt är följande:
Christian skrev:

Kod: Markera allt

	if((RCIE)&&(RCIF)){    // If this interrupt was generated by a receive character
För det första räcker det med att kolla RCIF, såvida du inte har för avsikt att stänga av interrupts för dessa (RCIE = 0), men det gör du inte i din aktuella kod.

För det andra glömmer du att nollställa RCIF, vilket innebär att så fort din ISR kört klart kommer den att triggas igen oavsett om en ny interrupt kommit eller inte. Nolla den direkt efter if-satsen i fråga.
Skriv svar