I am using stm8l - discovery board and I am curious about the functionality of trap in the micro controller. My program stops instead of running continously in the while loop, Is the functionality of trap interrupt that if it occurs, it does not execute (similar to reset)?
#include <iostm8l.h>
#include <stdio.h>
#include <stdint.h>
void Cus_delay(uint32_t ntime)
{
while(ntime!=0)
{
ntime--;
}
}
main()
{
CLK_DIVR = 0x00; // Set the frequency to 16Mhz
PC_DDR = 0x80; // direction output for led
PC_CR1 = 0x80; // fast push pull mode
int a = 10;
while(1)
{
Cus_delay(400000);
Cus_delay(400000);
PC_ODR ^= 0x80;
a = a/0;
}
}
Hi I write code below for initial External Interrupt for LPC2138 in KEIL 4.7 Compiler and when run code in proteus software , code dosent Work. I double check VIC and EXTINT registers seems correct. thanks
Project Picture on Proteus
one Switch on EXTINT2 (P0.15) and one LED on P1.25
#include <LPC213x.h>
void delay(int count);
void init_ext_interrupt(void);
__irq void Ext_ISR(void);
int main (void)
{
init_ext_interrupt(); // initialize the external interrupt
while (1)
{
}
}
void init_ext_interrupt(void) //Initialize Interrupt
{
EXTMODE = (1<<2); //Edge sensitive mode on EINT2
EXTPOLAR &= ~(1<<2); //Falling Edge Sensitive
PINSEL0 = 0x80000000; //Select Pin function P0.15 as EINT2
/* initialize the interrupt vector */
VICIntSelect &= ~(1<<16); // EINT2 selected as IRQ 16
VICVectAddr5 = (unsigned)Ext_ISR; // address of the ISR
VICVectCntl5 = (1<<5) | 16;
VICIntEnable = (1<<16); // EINT2 interrupt enabled
EXTINT &= ~(1<<2); //Set interrupt
}
__irq void Ext_ISR(void) // Interrupt Service Routine-ISR
{
IO1DIR |= (1<<25);
IO1SET |= (1<<25); // Turn ON LED
delay(100000);
IO1CLR |= (1<<25); // Turn OFF LED
EXTINT |= (1<<2); //clear interrupt
VICVectAddr = 0; // End of interrupt execution
}
void delay(int count)
{
int j=0,i=0;
for(j=0;j<count;j++)
{
for(i=0;i<35;i++);
}
}
You should correct the line:
(VICVectCntl5 = (1<<5) | 16;)
to:
(VICVectCntl5 = 0x20 | 16;)
as datasheet said.
I am programming an MSP430 microcontroller with the MSP430 LaunchPad Dev Kit and I am running into some problems on this simple code.
#include <msp430.h>
void Delay(void);
#define LED1 BIT0 //define LED1 as bit 0 (0x00)
#define LED2 BIT6 //define LED2 as bit 6 (0x40)
#define delayTime 20000 //define iTime as 20000
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; //stop watchdog timer
P1DIR |= (LED1|LED2); //set P1.0 and P1.6 to output direction (P1.3 is naturally an input)
P1OUT |= LED1; //set P1.0 high so the LEDs will blink alternatively
while(1)
{
Delay();
P1OUT ^= (LED1|LED2); //toggle P1.0 using exclusive-OR
}
}
void Delay(void)
{
int i = 0;
while(delayTime > i)
{
i++;
}
}
This code compiles fine, but when debugging the code, the function call 'Delay()' is skipped entirely and the function is never entered. However, when I give the function a return type of 'unsigned int' like this:
unsigned int Delay(void)
{
int i = 0;
while(delayTime > i)
{
i++;
}
return 1;
}
I can call the Delay function in an if statement like the one below and the debugger will enter the function.
if(Delay() == 1)
{
P1OUT ^= (LED1|LED2); //toggle P1.0 using exclusive-OR
}
I'm sure there is some simple oversight that I'm making. I can't for the life of me figure out why the debugger is skipping my first void function call. Any wisdom?
swineone has responded with the following correct solution in a comment:
"Try changing the declaration int i = 0; to volatile int i = 0; in the
Delay() function. This tells the optimizer not to touch that variable,
and may be the difference between the optimizer optimizing the code
away or not."
Thanks for the help!
It's recommended to work with interrupts. Such a task goes to this:
#include "io430.h"
#define ON 1
#define OFF 0
#define LED1 P1OUT_bit.P0
#define LED2 P1OUT_bit.P6
void init(void)
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
P1OUT = 0x00;
P1DIR = 0xFF;
// initialize Timer0_A
TA0CCR0 = 62500; // set up terminal count
TA0CTL = TASSEL_2 + ID_3 + MC_1; // configure and start timer
// enable interrupts
TA0CCTL0_bit.CCIE = 1; // enable timer interrupts
__enable_interrupt(); // set GIE in SR
}
#pragma vector = TIMER0_A0_VECTOR
__interrupt void myTimerISR(void)
{
LED1 = ~LED1;
}
I've been doing a project about home automation in which I have to use timer interrupts with 8051 microcontroller. I've constructed the following code, however I couldn't manage to get interrupt working. It seems that the program does not go into timer ISR at all. I use a buton to simulate PIR input, therefore lampControl is triggered, no worries there. I use as a library.
Any ideas or help will be greately appreciated:
void timer0_isr(void) interrupt 1 //Timer 0 Interrupt
{
TH0 = 0xDC;
TL0 = 0x00;
TR0 = 1;
if (++lamp_interrupt_count == 6000)
{
sendCharacterShowAsHex(0x8F);
lamp_interrupt_count = 0;
TR0 = 0;
}
}
void main()
{
unsigned char chr;
IE = 0x93;
while(1)
{
serialInput();
if (getPIRInput() == 0x00)
{
lampControl(0x80);
}
....
....
....
}
void lampControl(unsigned char serial_data_in)
{
if (serial_data_in == 0x80)
{
sendCharacterShowAsHex(0x80);
//enable interrupts
IE = 0x93;
device_interrupt = 2; //Lamp
TMOD = 0x21; // Timer0 Gate=0, Mode 1, 16bit timer
TH0 = 0xDC;
TL0 = 0x00;
TR0 = 1;
}
else if(serial_data_in == 0x8F)
{
sendCharacterShowAsHex(0x8F);
}
}
You need to configure the timer and interrupts before you can use them.
In main() you need at least the following configuration bits set in order to be able to turn
the timer on with "TR0 = 1;" :
Set those bits first thing in main() and this should do the trick:
TMOD = 0x01; // 16-bit no auto reload
TH0 = 0xDC; //Set high and low bits to count 0xFFFF - 0xDC00 = 0x23FF counts
TL0 = 0x00;
ET0 = 1; // Enable timer0 interrupt
EA = 1; // Enable all interrupts
//TR0 = 1; //Enable Timer0 immediately
The rest of your code should run fine.
Note: you could change your interrupt function definition to:
"void timer0_isr(void) interrupt 1 using 1" to force it to use register bank 1 for the interrupt function operation.
I am running a C program on an AVR chip. Whenever a serial signal is heard, it runs the serial interrupt ISR (USART_RX_vect). In this method it should turn on change to = 1;. Then in my main while loop, it should clear the LCD and display it and then set change = 0 again.
This is to stop it continually doing the calulations, and displaying the result on the LCD a million times a minute..
However, when the interrupt method changes the change variable to 1, it does not seem to change it "globally" and in the main method it is always 0..
There is a bit of stuff in here that is for debugging purposes.
/* LCD DEFINES */
#define LED PB5
#define output_low(port,pin) port &= ~(1<<pin)
#define output_high(port,pin) port |= (1<<pin)
#define set_input(portdir,pin) portdir &= ~(1<<pin)
#define set_output(portdir,pin) portdir |= (1<<pin)
/* UART SERIAL DEFINES */
#define F_CPU 16000000UL
#define BAUD 9600
#define MYUBRR F_CPU/16/BAUD-1
#define STARTCHAR 'R'
#define ENDCHAR 'E'
char reading;
char inputBuffer[12];
char readStatus;
uint8_t position;
int change;
char output;
int result;
struct Axis
{
uint8_t axisNumber;
uint16_t position;
uint16_t oldPosition;
} axis1, axis2, axis3;
/* SETUP UART */
void USART_Init( unsigned int ubrr)
{
/*Set baud rate */
UBRR0H = (unsigned char)(ubrr>>8);
UBRR0L = (unsigned char)ubrr;
/*Enable receiver and transmitter */
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
/* Set frame format: 8data, 2stop bit */
UCSR0C = (1<<USBS0)|(3<<UCSZ00);
}
void USART_Transmit( unsigned char data )
{
UDR0 = data;
}
unsigned char USART_Receive( void )
{
return UDR0;
}
/*****************************************************************/
int main(void)
{
/* INITALISE SERIAL */
USART_Init(MYUBRR);
/* Turn on Receive Complete Interrupt */
UCSR0B |= (1 << RXCIE0);
/* Turn On GLobal Interrupts */
sei();
position = 0;
change = 0;
/* Initialise LCD */
lcd_init(LCD_DISP_ON); /* Initialize display, cursor off. */
lcd_clrscr();
lcd_puts("READY");
//Turn on LED 13
set_output(PORTB,LED);
output_low(PORTB,LED);
while (1) /* Loop forever */
{
if (change == 1)
{
//If not reading, display the result on the LCD display.
axis1.position = (inputBuffer[0]<< 8) | inputBuffer[1];
axis2.position = (inputBuffer[2]<< 8) | inputBuffer[3];
axis3.position = (inputBuffer[4]<< 8) | inputBuffer[5];
char axis1Printout[12];
char axis2Printout[12];
char axis3Printout[12];
sprintf(axis1Printout,"%u ", axis1.position);
sprintf(axis2Printout,"%u ", axis2.position);
sprintf(axis3Printout,"%u ", axis3.position);
char output[40] = "";
strcat(output, axis1Printout);
strcat(output, axis2Printout);
//strcat(output, axis3Printout);
lcd_clrscr(); /* Clear the screen*/
lcd_puts(output);
_delay_ms(300);
change = 0;
}
}
}
/* INTERRUPTS */
ISR (USART_RX_vect)
{
change = 1;
unsigned char input = USART_Receive();
if (input == 'R')
{
readStatus = 0; //Reading
position = 0;
}
else if ((input != 'E') && (position < 12) && (position > -1))
{
inputBuffer[position] = input;
position++;
}
else if (input == 'E')
{
readStatus = 1; //Stop Reading
position = -1;
output_high(PORTB,LED);
}
}
You need to declare change using the volatile keyword:
volatile int change;
This tells the two 'threads' (main execution loop and your ISR code) to not 'cache' the value in a register, but always retrieve it from memory.
Edit: There's another problem with the code - in your main loop, by the time you set changed to 0, you may have already had another interrupt which should have triggered your loop to run again. The easy-but-not-guaranteed fix is to immediately set changed to 0 straight after you check it. The proper way would be to use a lock - but depending on your situation, the first option might do.
Make the variable declaration volatile to ensure that a changed value is written imediately to the variable in memory.
An object shared by an interrupt handler and the application code should be qualified as volatile in the declaration.
Without the qualifier, the implementation can assume the object cannot change unexpectedly in the application code and can cache the variable (in a register for example) for optimizations while executing the application code.