Sida 1 av 2
Timer problem
Postat: 2 juni 2008, 21:32:01
av Eriktronix
Jag håller på med ett litet test projekt där jag använder en PIC18F2431. Jag får inte timer-avbrotten att fungera, kan någon se något fel i min kod. uppkopplingen består bara av PIC:en strömförsörjning samt anslutning till en IDC2 och två avkopplings kondigar. Jag har även två stycken pull-up motstånd för FLTA och FLTB
Kod: Markera allt
#include <p18cxxx.h>
#include <pcpwm.h>
#include <timers.h>
#pragma config WDTEN = OFF
#pragma config OSC = IRC
#pragma config LVP = OFF
//--- DEFINITIONS --- DEFINITIONS --- DEFINITIONS ---
#define TRM0_OFFSET 25540
//--- PROTOTYPES --- PROTOTYPES --- PROTOTYPES ---
void timer_isr(void);
void timer_config(void);
void pcpwm_config( void );
void loop_50_hz( void);
//--- VARIABLES --- VARIABLES --- VARIABLES ---
//--- CODE --- CODE --- CODE ---
void pcpwm_config( void )
{
PORTB = 0;
TRISB = 0b11000000;
TRISC = 0b00000010;
DTCON = 0b00000000;
PTCON0 = 0b00000101;
PTPERH = 0x05;
PTPERL = 0x34; //F_pwm = 400Hz
PWMCON0 = 0b01011111;
PWMCON1 = 0b00001001;
PTCON1 = 0b00000000;
FLTCONFIG = 0b00000011;
PDC0H = 0x05;
PDC0L = 0xf0;
PDC1H = 0x0B;
PDC1L = 0x28;
PDC2H = 0x12;
PDC2L = 0xd0;
}
#pragma code low_vector = 0x18
void interrupt_at_low_vector(void)
{
_asm GOTO timer_isr _endasm
}
#pragma code
#pragma interruptlow timer_isr
void timer_isr(void)
{
INTCONbits.TMR0IF = 0; //Clear interrupt flag
loop_50_hz();
WriteTimer0( TRM0_OFFSET );
}
void timer_config(void)
{
OpenTimer0( TIMER_INT_ON &
T0_16BIT &
T0_SOURCE_INT &
T0_EDGE_RISE &
T0_PS_1_1 );
WriteTimer0( TRM0_OFFSET );
INTCONbits.GIE = 1; //Allow interrupts
}
void loop_50_hz( void)
{
PTCON1bits.PTEN = 1;
}
void main( void )
{
OSCCON = 0x72; //Sets F_osc to 8MHz
loop_50_hz();
timer_config(); //Low pri interupt 50Hz
pcpwm_config(); //Single-shot mode 400Hz
while (1);
}
Postat: 2 juni 2008, 23:16:06
av sodjan
Vad händer ?
Du kanske skulle minska ner koden till enbart det som du vill testa.
Postat: 3 juni 2008, 19:34:18
av Eriktronix
Det var en av de första sakerna jag testade, dock utan resultat. Jag har även testat att byt PIC:en, men inte heller det ger något resultat. Jag har den senaste versionen av MPLAB IDE, kan det finnas någon inställning som måste göras. I övrigt exekveras koden som den ska.
Postat: 3 juni 2008, 20:21:24
av sodjan
> > Du kanske skulle minska ner koden till enbart det som du vill testa.
> Det var en av de första sakerna jag testade, dock utan resultat.
Då borde du visa *den* koden, så att vi bara behöver läsa det viktiga.
Visa den minsta möjliga kod som uppvisar det problem du ser !
Jag ser inte att du clearar RCON.IPEN. I.o.f.s ska den vara "0" vid
reset, men...
Sedan kan du strunta i Open/Write timer funktionerna och skriva direkt
till de aktuella registren. D.v.s koppla bort så mycket libr.funktioner
som möjligt...
Men viktigast, banta ner koden till det minsta möjliga som uppvisar
problemet.
Postat: 3 juni 2008, 22:41:38
av Eriktronix
Okej... här kommer ett försök till att skriva alla fuktioner själv...
Jag har tagit bort allt "onödigt". För att se att jag får ett avbrott tänder jag en led som förväntas slockna så fort jag får ett avbrott. Detta sker inte.
Kod: Markera allt
#include <p18cxxx.h>
#pragma config WDTEN = OFF
#pragma config OSC = IRC
#pragma config LVP = OFF
//--- DEFINITIONS --- DEFINITIONS --- DEFINITIONS ---
#define TIMER_OFFSET 25536
#define LOWBYTE(v) ((unsigned char) (v))
#define HIGHBYTE(v) ((unsigned char) (((unsigned int) (v)) >> 8))
//--- PROTOTYPES --- PROTOTYPES --- PROTOTYPES ---
void init(void);
void init_clk(void);
void init_timer(void);
void init_interrupts(void);
void set_offset_timer( unsigned int o );
void timer_isr(void);
//--- VARIABLES --- VARIABLES --- VARIABLES ---
//--- CODE --- CODE --- CODE ---
#pragma code low_vector = 0x18
void interrupt_at_low_vector(void)
{
_asm GOTO timer_isr _endasm
}
#pragma code
#pragma interruptlow timer_isr
void timer_isr(void)
{
INTCONbits.TMR0IF = 0; //Clear interrupt flag
set_offset_timer( TIMER_OFFSET );
PORTCbits.RC3 = 0;
}
void init_clk()
{
OSCCON = 0x72; //Sets F_osc to 8MHz
}
void set_offset_timer( unsigned int o )
{
TMR0H = HIGHBYTE( o );
TMR0L = LOWBYTE( o );
}
void init_timer()
{
T0CON = 0b00001000;
set_offset_timer( TIMER_OFFSET );
init_interrupts();
T0CONbits.TMR0ON = 1; // Start timer
}
void init_interrupts(void)
{
RCONbits.IPEN = 0; // Disable priority levels
INTCON = 0b01100000;
INTCONbits.TMR0IF = 0; // Clear interrupt flag
INTCON2bits.TMR0IP = 1; // Enable interrupts
}
void init(void)
{
init_clk();
init_timer();
INTCONbits.GIE = 1;
}
void main( void )
{
TRISC = 0;
PORTCbits.RC3 = 1;
init();
while (1)
{
// wait for interrupt.
}
Postat: 3 juni 2008, 22:54:01
av spaderkung
En titt i kompilerad asm kan vara på sin plats.
Postat: 3 juni 2008, 23:25:57
av sodjan
OK, jag har ingen direkt ide, men om det var jag som hade problemet
så skulle jag:
- Förenkla koden så att den bli lättare att följa.
D.v.s plocka bort alla helt onödiga funktioner, skriv allt rakt av
i main().
- Skriva en kort ASM kod som gör samma sak för att verifiera funktionen.
- Lägg till *alla* CONFIG flaggor, så att inget är missat.
Postat: 4 juni 2008, 14:03:32
av vfr
Jag tycker Sodjans idéer är bra. Vid felsökning gäller det hela tiden (enligt min mening) att förenkla problemställningen så långt att man slutligen bara har problemet kvar. Då är det inga problem att hitta det.
Postat: 4 juni 2008, 14:12:49
av sodjan
Jag skulle kanske lägga till en 4'de punkt, "Ge inte upp"...
Jag skulle även plocka bort skrivningen till TMR0, låt
den vara "free-running" och få *det* att fungera först.
Lägg till en poll i main() på TMR0IF flaggan för att verifiera
att *den* sätts i alla fall.
> RCONbits.IPEN = 0; // Disable priority levels
> #pragma code low_vector = 0x18
Om int-prio-level är disablat så sker alla interrupt till h'0008'.
Se databladet !!
Postat: 4 juni 2008, 21:12:16
av Eriktronix
Hej på er, tack för visat intresse! Här kommer dagen uppdatering. Jag har försökt att göra det ni föreslår. TMR0IF sätts när TMR0L går från 0xFF till 0x00 med det blir aldrig något avbrott. Jag inte säker på i vilken ordning man bör sätt alla "inställningar" i registren.
Kod: Markera allt
#include <p18f2431.h>
#pragma config WDTEN = OFF
#pragma config OSC = IRCIO
#pragma config LVP = OFF
void timer_isr(void);
#pragma code low_vector = 0x18
void interrupt_at_low_vector(void)
{
_asm GOTO timer_isr _endasm
}
#pragma code
#pragma interruptlow timer_isr
void timer_isr(void)
{
INTCONbits.TMR0IF = 0; // Pull down TMR0 interrupt flag
PORTCbits.RC3 = 0;
INTCONbits.GIEL = 1; // Enables low-prio interrupts
T0CONbits.TMR0ON = 1; // Enables Timer0
}
void main( void )
{
OSCCON = 0x72; // Sets F_osc to 8MHz
TRISC = 0;
PORTCbits.RC3 = 0;
PORTCbits.RC3 = 1;
T0CONbits.T016BIT = 1; // 16-bit mode
T0CONbits.T0CS = 0; // Internal instruction cycle clock
T0CONbits.T0SE = 0; // Rising edge
T0CONbits.PSA = 1; // By-pass prescaler
RCONbits.IPEN = 1; // Enables piro levels
INTCONbits.GIEH = 0; // Disable high-prio interrupts
INTCONbits.TMR0IE = 1; // Enable timer0 overflow interrupt
INTCONbits.INT0IE = 0; // Disable External interrupts
INTCONbits.RBIE = 0; // Disable portB interrupts
INTCONbits.TMR0IF = 0; // Pull down TMR0 interrupt flag
INTCONbits.INT0IF = 0; // Pull down INT0 interrupt flag
INTCONbits.RBIF = 0; // Pull down portb interrupt flag
INTCON2bits.TMR0IP = 0; // Timer0 interrupt prio = low
INTCONbits.GIEL = 1; // Enables low-prio interrupts
T0CONbits.TMR0ON = 1; // Enables Timer0
while (1)
{
// wait for interrupt.
}
}
Postat: 4 juni 2008, 23:06:52
av sodjan
> Jag har försökt att göra det ni föreslår.
Men misslyckats.
Kolla mitt senaste inlägg igen. Du kan inte ha läst det eftersom
du inte ens kommenterar det kanske viktigaste i inlägget,
adressen för interruptrutinen...
Postat: 10 juni 2008, 18:42:39
av Eriktronix
Okej... du har rätt jag testade inte med att bara använda en prio-nivå. Men nu har jag det och det fungerar nu! Men va f-n är det som gör att det inte fungerar men två prio-nivårer??? Återstår att lösa...
Tack för all hjälp och alla förslag!
Postat: 10 juni 2008, 22:01:23
av sodjan
> Men va f-n är det som gör att det inte fungerar men två prio-nivårer???
Det gör det nog om du gör rätt...
> Återstår att lösa...
Varför det ? Behöver du det (d.v.s 2 nivåer) ?
Postat: 10 juni 2008, 22:47:45
av Eriktronix
Jag funderar på om jag behöver det. Jag är av den naturen att jag inte kan lämna ett problem olöst.
Allt är möjligt

Postat: 11 juni 2008, 00:53:04
av sodjan
I 99 fall av 100 behövs det inte.
Och om man inte måste köra med 2 nivåer, så bara
ställe det till mer besvär, t.ex genom att det inte finns
"shadow" register till mer än en nivå...