PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Eriktronix
Inlägg: 34 Blev medlem: 9 mars 2006, 18:10:46
Ort: Södertälje
Inlägg
av Eriktronix » 2 juni 2008, 21:32:01
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);
}
sodjan
EF Sponsor
Inlägg: 43231 Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Inlägg
av sodjan » 2 juni 2008, 23:16:06
Vad händer ?
Du kanske skulle minska ner koden till enbart det som du vill testa.
Eriktronix
Inlägg: 34 Blev medlem: 9 mars 2006, 18:10:46
Ort: Södertälje
Inlägg
av Eriktronix » 3 juni 2008, 19:34:18
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.
sodjan
EF Sponsor
Inlägg: 43231 Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Inlägg
av sodjan » 3 juni 2008, 20:21:24
> > 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.
Eriktronix
Inlägg: 34 Blev medlem: 9 mars 2006, 18:10:46
Ort: Södertälje
Inlägg
av Eriktronix » 3 juni 2008, 22:41:38
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.
}
spaderkung
Inlägg: 138 Blev medlem: 12 maj 2007, 11:24:24
Ort: Sjöbo
Inlägg
av spaderkung » 3 juni 2008, 22:54:01
En titt i kompilerad asm kan vara på sin plats.
sodjan
EF Sponsor
Inlägg: 43231 Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Inlägg
av sodjan » 3 juni 2008, 23:25:57
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.
vfr
EF Sponsor
Inlägg: 3515 Blev medlem: 31 mars 2005, 17:55:45
Ort: Kungsbacka
Inlägg
av vfr » 4 juni 2008, 14:03:32
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.
sodjan
EF Sponsor
Inlägg: 43231 Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Inlägg
av sodjan » 4 juni 2008, 14:12:49
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 !!
Eriktronix
Inlägg: 34 Blev medlem: 9 mars 2006, 18:10:46
Ort: Södertälje
Inlägg
av Eriktronix » 4 juni 2008, 21:12:16
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.
}
}
sodjan
EF Sponsor
Inlägg: 43231 Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Inlägg
av sodjan » 4 juni 2008, 23:06:52
> 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...
Eriktronix
Inlägg: 34 Blev medlem: 9 mars 2006, 18:10:46
Ort: Södertälje
Inlägg
av Eriktronix » 10 juni 2008, 18:42:39
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!
sodjan
EF Sponsor
Inlägg: 43231 Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Inlägg
av sodjan » 10 juni 2008, 22:01:23
> 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) ?
Eriktronix
Inlägg: 34 Blev medlem: 9 mars 2006, 18:10:46
Ort: Södertälje
Inlägg
av Eriktronix » 10 juni 2008, 22:47:45
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
sodjan
EF Sponsor
Inlägg: 43231 Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Inlägg
av sodjan » 11 juni 2008, 00:53:04
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å...