KidE
February 3, 2009, 3:59pm
1
I’m trying to get my servo moving using a interupt steered pulstrain.
The servo is not moving but if i connect a LED to it i see the led light up (very low) for a few sec and then on full power.
Could anyone assist to see where i fail?
Solution in last post
#include "LPC214x.h"
#include "VIClowlevel.h"
#define PLOCK 0x400
void init(void);
void IRQ_Routine (void) __attribute__ ((interrupt("IRQ")));
int main(void)
{
int i;
IODIR0 = 0x00200000; //Output
IOCLR0 = 0x00200000; //LEDs off
init();
T0TCR = 0x02; //reset counter
T0IR = 0xff;
T0MCR = 0x0003; //interrupt and reset on MR0
T0MR0 = 0x00124F80; //compare-hit count 20ms
VICVectCntl0 = 0x00000024; //use it for Timer 0 Interrupt:
VICVectAddr0 = (unsigned)IRQ_Routine; //set interrupt vector in 0
VICIntEnable = 0x00000010; //enable TIMER0 interrupt
T0TCR = 0x01; //enable Timer0
enableIRQ();
while(1){
i=0;
i=1;
}
}
void IRQ_Routine(void)
{
int i;
IOSET0 = 0x00200000;
for(i=0;i<6000;i++);
IOCLR0 = 0x00200000;
T0IR = 0x01; //clear interrupt
VICVectAddr = 0; //end of interrupt - dummy write
}
void init(void)
{
PLLCFG=0x24; //set multiplier/divider values
PLLFEED=0xaa;
PLLFEED=0x55;
PLLCON=0x01; //enable PLL
PLLFEED=0xaa;
PLLFEED=0x55;
while(!(PLLSTAT & PLOCK)); //wait for the PLL to lock to set frequency
PLLCON=0x3; //connect the PLL as the clock source
PLLFEED=0xaa;
PLLFEED=0x55;
MAMCR=0x02; //enable MAM
MAMTIM=0x04; //set number of clocks for flash memory fetch
VPBDIV=0x01; //set peripheral clock(pclk) to system clock(cclk)
}
Thanks
What type of servo are you trying to drive?? is it a thre wire PWM type or a multiquadrant type?
Roughly how long is the LED dim and full during each interrupt?
KidE
February 5, 2009, 9:20pm
3
It’s a 3 wire servo i use a normal analoge one.
I used the servo with PWM and it worked fine but i’m trying it now with a puls train to use it in combi with interrupts.
The led is dimm for 3 sec and after that it fires up fully.
Ernst
KidE:
The led is dimm for 3 sec and after that it fires up fully.
Ernst
Hmm, does the LED turn off and repeat this cycle or is that it it just stays fully lit??
I’m not seeing any immediate coding issues but i am curious whether the issues is that the interrupt routine you have developed probably doesnt provide a 50/50 square wave pulse train.
Actually wondering if you’d be better off changing the interrupt routine so that it just complimented the state of the GPIO pin that you have the servo attached to each time.
This would give a nice 50/50 cycle and then you can just change the timer values to get the servo to move from min to max.
KidE
February 8, 2009, 8:10am
6
It stays LIT for the rest of the times and i’m wondering if it crashed.
Actually wondering if you’d be better off changing the interrupt routine so that it just complimented the state of the GPIO pin that you have the servo attached to each time.
This would give a nice 50/50 cycle and then you can just change the timer values to get the servo to move from min to max.
Could you supply me with a hint in the right direction? i’m quite new at this so.
Thanks up front.
[/code]
KidE:
Could you supply me with a hint in the right direction? i’m quite new at this so.
Thanks up front.
[/code]
I’ll see what i can do. To help would you mind posting the content of your ‘VIClowlevel.h’ file?
KidE
February 9, 2009, 7:50am
8
Both pieces of code ore from http://ghmicro.com/index.php/lpc2000/1- … rd?start=6
VIClowlevel.h
unsigned enableIRQ(void);
unsigned disableIRQ(void);
unsigned restoreIRQ(unsigned oldCPSR);
#define IRQ_MASK 0x00000080
VIClowlevel.c
This piece of code must be used to enable and disable interrupts.
#include "VIClowlevel.h"
static inline unsigned asm_get_cpsr(void)
{
unsigned long retval;
asm volatile (" mrs %0, cpsr" : "=r" (retval) : /* no inputs */ );
return retval;
}
static inline void asm_set_cpsr(unsigned val)
{
asm volatile (" msr cpsr, %0" : /* no outputs */ : "r" (val) );
}
unsigned enableIRQ(void)
{
unsigned _cpsr;
_cpsr = asm_get_cpsr();
asm_set_cpsr(_cpsr & ~IRQ_MASK);
return _cpsr;
}
unsigned disableIRQ(void)
{
unsigned _cpsr;
_cpsr = asm_get_cpsr();
asm_set_cpsr(_cpsr | IRQ_MASK);
return _cpsr;
}
unsigned restoreIRQ(unsigned oldCPSR)
{
unsigned _cpsr;
_cpsr = asm_get_cpsr();
asm_set_cpsr((_cpsr & ~IRQ_MASK) | (oldCPSR & IRQ_MASK));
return _cpsr;
}
KidE
February 10, 2009, 7:17am
9
OK i forgot to mention that i use crossworks.
In another piece of code i ran into the same problem so it seems that crossworks is handeling interrupts in a different way and they bite with the current “gcc for ARM” way.
I have some sample code how it should be done and i have to look into this.
I found some interesting links and i’m going to dig into this somewhere this week.
http://tech.groups.yahoo.com/group/lpc2 … sage/31140
http://ccgi.rowley.co.uk/support/faq.ph … ticleid=28
http://ccgi.rowley.co.uk/support/faq.ph … ticleid=25
KidE
February 12, 2009, 7:10pm
10
If i look in the examples from Rowley’s this is how it
should look i think.
Only downside… its not working
Reading the manual part of ctl_api this should be working.
In the startup file i’ve also enabled: VECTORED_IRQ_INTERRUPTS
Anyone smart idea’s?
#include <ctl_api.h>
#define PLOCK 0x400
void init(void);
void delay_ms(int);
volatile int servo;
int main(void)
{
init();
PINSEL1 = 0x10000000; //p0.30 = AD0.3
IODIR0 = 0x00200000; //p0.21 = output
AD0CR = 0x00210e08; //start burst A/D on AD0.3
T0TCR = 0x02; //reset counter
T0IR = 0xff;
T0MCR = 0x0003; //interrupt and reset on MR0
T0MR0 = 0x00124f80; //compare-hit count
// VICVectCntl0 = 0x00000024; //use it for Timer 0 Interrupt:
// VICVectAddr0 = (unsigned)isr; //set interrupt vector in 0
// VICIntEnable = 0x00000010; //enable TIMER0 interrupt
T0TCR = 0x01; //enable Timer0
ctl_global_interrupts_enable();
while(1){
}
}
void isr(void)
{
// let burn some LED's
T0IR = 0x01; //clear interrupt
VICVectAddr = 0; //end of interrupt - dummy write
}
void init_isr(void)
{
ctl_set_isr(1, 0, CTL_ISR_TRIGGER_FIXED, isr, 0);
ctl_unmask_isr( 1);
}
Gr,
Ernst
KidE
February 13, 2009, 8:49am
11
Ok almost solved
The code is working now and interrupts are fired
#include <ctl_api.h>
#define PLOCK 0x400
void init(void);
void delay_ms(int);
volatile int servo;
int main(void)
{
init();
init_isr();
PINSEL1 = 0x10000000; //p0.30 = AD0.3
IODIR0 = 0x00200000; //p0.21 = output
AD0CR = 0x00210e08; //start burst A/D on AD0.3
T0TCR = 0x02; //reset counter
T0IR = 0xff;
T0MCR = 0x0003; //interrupt and reset on MR0
T0MR0 = 0x00124f80; //compare-hit count
T0TCR = 0x01; //enable Timer0
ctl_global_interrupts_enable();
while(1){
}
}
void isr(void)
{
// let burn some LED's
T0IR = 0x01; //clear interrupt
VICVectAddr = 0; //end of interrupt - dummy write
}
void init_isr(void)
{
ctl_set_isr(1, 0, CTL_ISR_TRIGGER_FIXED, isr, 0);
ctl_unmask_isr( 1);
}
Using crossworks in the ISR the following should be replaced by something else. Only what?
T0IR = 0x01; //clear interrupt
VICVectAddr = 0; //end of interrupt - dummy write
nbl1268
February 15, 2009, 4:55am
12
Hi, great to hear you almost got it working.
Spent some time doing the same and come up with this.
#include "LPC214x.h"
//#include "VIClowlevel.h"
#define PLOCK 0x400
#define TIMER0_INT (1<<4)
#define LED (1<<17) // PIN address of output
#define LEDON() IOSET0 = LED
#define LEDOFF() IOCLR0 = LED
void init(void);
//void ISR_Timer0 (void) __attribute__ ((interrupt("IRQ")));
void ISR_Timer0 (void);
//void delay_ms(int count);
int main(void){
int i;
// Initialise uC
init(); // Setup PPL
//IOCLR0 = 0x00200000; //LEDs off
LEDOFF();
//enableIRQ(); // use if using VIClowlevel.h
VICIntEnable |= TIMER0_INT; //Turn on Timer0 interrupts
while(1){
// Wait here for interrupt
i=0;
i=1;
}
}
void ISR_Timer0(void){
// Interrupt from Timer0
// Toggles state of the output; effectively halves the freq of Timer0
if((IOPIN0 & LED) == 0)
{
//IOSET0 = 0x00200000;
LEDON();
}
else
{
//IOCLR0 = 0x00200000;
LEDOFF();
}
T0IR = 0x01; //clear interrupt
VICVectAddr = 0; //end of interrupt - dummy write
}
void init(void){
// Setup IO
//IODIR0 = 0x00200000; //Output
IODIR0 = LED; // Set as GPIO as output
// Setup PLL
PLLCFG=0x24; //set multiplier/divider values
PLLFEED=0xaa;
PLLFEED=0x55;
PLLCON=0x01; //enable PLL
PLLFEED=0xaa;
PLLFEED=0x55;
while(!(PLLSTAT & PLOCK)); //wait for the PLL to lock to set frequency
PLLCON=0x3; //connect the PLL as the clock source
PLLFEED=0xaa;
PLLFEED=0x55;
MAMCR=0x02; //enable MAM
MAMTIM=0x04; //set number of clocks for flash memory fetch
//Setup the Interrupts
VPBDIV=0x01; //set peripheral clock(pclk) to system clock(cclk)
VICIntSelect = ~(TIMER0_INT);
//VICVectCntl0 = 0x00000024; //use it for Timer 0 Interrupt:
VICVectCntl0 = 0x20 | 4; // Timer 0 Interrupt
VICVectAddr0 = (unsigned int)ISR_Timer0; // set interrupt vector in 0
//VICIntEnable = 0x00000010; //enable TIMER0 interrupt
//Setup Timer0 to interrupt on count value
T0PR = 0; // increment every PCLK
// T0TCR = 0x02; // reset counter
T0TCR |= 0X01; // enable Timer0
T0CTCR = 0x00; // Timer Mode
T0MCR = 0x0003; // Interrupt and Reset Timer on Match
T0MR0 = 0x00124F80; // compare-hit count 20ms
// 0x00124F80 = 1,200,000
// 60MHz / 1200000 = 50Hz or 20ms
/* //Setup Timer0 to Interrupt on timer value
// alternate way of setting up timer 0
T0PR = 1200; // Divide Clock(60MHz) by 1200 for 50kHz PS
T0TCR |= 0X01; // Enable the clock
T0CTCR = 0; // Timer Mode
T0MCR = 0x0003; // Interrupt and Reset Timer on Match
T0MR0 = 1000; // Divide Timer Clock (50KHz) by 1000 for 50Hz or 20ms
*/
}
I havent used the VIClowlevel.h file
The output toggles every timer match and provides a nice 50% duty cycle for controlling the servo.
Neil
KidE
February 23, 2009, 6:59pm
13
Ok somebody from lpc2000 group helped me good and my problem (at least teh IRQ thing) is solved now.
#include "LPC214x.h"
#include <ctl_api.h>
#define PLOCK 0x400
void init(void);
void delay_ms(int);
void isr_servo_out(void);
volatile int servo;
void init_isr(void)
{
ctl_global_interrupts_enable(); // interrupts enabled
ctl_set_isr(4, 0, CTL_ISR_TRIGGER_FIXED, isr_servo_out, 0); //interrupt set
ctl_unmask_isr( 4); //interrupt unmasked
}
void isr_servo_out(void)
{
IOSET0 = 0x00200000; // and there was light
T0IR = 0x01; //clear interrupt
}
int main(void)
{
init();
init_isr();
PINSEL1 = 0x00002000; //p0.22 = capture 0.1 (timer0)
IODIR0 = 0x00200C00; //p0.10, p0.11, p0.21 = GPIO output
IOSET0 = 0x00000C00; // LED1+2 off
T0TCR = 0x02; //reset counter
T0IR = 0xff;
T0CCR = 0x00000005; //capture on rising edge
T0TCR = 0x00000001; //enable timer
while(1){
}
}
void init(void)
{
PLLCFG=0x24; //set multiplier/divider values
PLLFEED=0xaa;
PLLFEED=0x55;
PLLCON=0x01; //enable PLL
PLLFEED=0xaa;
PLLFEED=0x55;
while(!(PLLSTAT & PLOCK)); //wait for the PLL to lock to set frequency
PLLCON=0x3; //connect the PLL as the clock source
PLLFEED=0xaa;
PLLFEED=0x55;
MAMCR=0x02; //enable MAM
MAMTIM=0x04; //set number of clocks for flash memory fetch
VPBDIV=0x01; //set peripheral clock(pclk) to system clock(cclk)
}