so basically I'm trying set up a ISR(Interrupt subroutine) to simply turn a light on, but the ISR doesn't seem to run. I've looked through the microcontroller datasheet a lot to see if I'm doing something wrong but I couldn't find anything.
Heres my code.
#include <asf.h>
int main (void) {
DDRD = 0b10000000;
cli(); // turn off global interrupts
//Timer
TCCR2A |=_BV(WGM21); //CTC mode
TCCR2B |=_BV(CS22)|_BV(CS21); //clk pre-scale 1/256
OCR2A = 0x7d; //125clk cycles = 2ms
TIMSK2 |=_BV(OCIE2A); //enable interrupt on compare matchA
TIFR2 |= _BV(OCF2A); //clear flag
TCNT2 = 0x00; // reset counter
sei(); // enable global interrupts
}
ISR(TIMER2_COMPA_vect) {
PORTD = 0b10000000;
}
You should have an endless loop at the end of your main() function:
#include <asf.h>
int main (void) {
DDRD = 0b10000000;
cli(); // turn off global interrupts
//Timer
TCCR2A |=_BV(WGM21); //CTC mode
TCCR2B |=_BV(CS22)|_BV(CS21); //clk pre-scale 1/256
OCR2A = 0x7d; //125clk cycles = 2ms
TIMSK2 |=_BV(OCIE2A); //enable interrupt on compare matchA
TIFR2 |= _BV(OCF2A); //clear flag
TCNT2 = 0x00; // reset counter
sei(); // enable global interrupts
while(1);
}
ISR(TIMER2_COMPA_vect) {
PORTD = 0b10000000;
}
Without endless loop your AVR reaches an undefined state!
Related
I am working on a project and I have two external interrupts (push buttons) and using TIMER1 compare match mode, I want the timer to reach the top value twice (here I have it one time only because I was trying to see where's the problem) then turn off a dc motor but it doesn't seem to fire the interrupt, the external interrupts work btw, I even tried to toggle a led in the ISR and it won't do anything. Here's the code:
uint8 volatile flag=0; //for stopping the motor
void INT0_init(void)
{
MCUCR = MCUCR | (1<ISC01) ; /*interrupt with rising edge */
MCUCR = MCUCR | (1<<ISC00);
GICR |= (1<<INT0);
DDRD = DDRD & (~(1<<PD2)); /* setting PD2 as input pin */
}
ISR (INT0_vect)
{
SET_BIT(PORTB, PB3); //when the interrupt happens the motor moves in anti clockwise direction
CLEAR_BIT(PORTB, PB4);
TIMER1_ctcMode(0x0000, 0xFFFF);
while( PIND & (1<<PD2) ) {} /*to stay in this state as long as it got pressed once */
}
void INT1_init(void)
{
MCUCR = MCUCR | (1<ISC11) ; /*interrupt with rising edge */
MCUCR = MCUCR | (1<<ISC10);
GICR |= (1<<INT1);
DDRD = DDRD & (~(1<<PD3)); /* setting PD3 as input pin */
}
ISR (INT1_vect)
{
SET_BIT(PORTB, PB3); //when the interrupt happens the motor moves in clockwise directio
CLEAR_BIT(PORTB, PB4);
TIMER1_ctcMode(0x0000, 0xFFFF); //call the timer for 8-ish seconds
while( PIND & (1<<PD3) ) {} /*to stay in this state as long as it got pressed once */
}
ISR (TIMER1_COMPA_vect) //timer isr
{
flag++;
PORTA ^=(1<<0);
_delay_ms(500);
}
int main()
{
SET_BIT(SREG,7); /* setting the i-bit */
SET_BIT(DDRB, PB3); //setting the pins as output pins of the H-bridge
SET_BIT(DDRB, PB4);
TIMER1_initCtcMode();
INT0_init(); /* initializing interrupt0 */
INT1_init(); /*initializing interrupt1 */
while (1)
{
if(flag==1)
{
TIMER1_deinit(); // to stop the timer
CLEAR_BIT(PORTB, PB3); //when the timer finishes counting stop the motor
CLEAR_BIT(PORTB, PB4);
flag=0; //set the flag to zero for the next time the timer is used
}
}
}
and here's the timer configuration:
void TIMER1_initCtcMode(void)
{
SREG= SREG | (1<<7); //setting the i-bit
TIMSK |=(1<<OCIE1A); //setting interrupt enable for timer1
TIFR &=~(1<<OCF1A);
TCCR1A |=(1<<FOC1A) ;
TCCR1A |= (1<<FOC1B); //setting the non-pwm bits
TCCR1B |=(1<<WGM12);
TCCR1B |= (1<<CS12);
TCCR1B |= (1<<CS10); //setting prescalar at 1024
TCCR1B = TCCR1B &( ~(1<<CS11));
TCCR1A &= ~(1<<COM1A0); //clearing them for non-pwm mode
TCCR1A &= ~(1<<COM1A1);
}
void TIMER1_ctcMode(volatile uint16 initialValue, volatile uint16 topValue)
{
TCNT1=initialValue; //initial value
OCR1A=topValue; //top value to reach 8.3sec
}
void TIMER1_deinit(void)
{
CLEAR_BIT(TCCR1B, CS12);
CLEAR_BIT(TCCR1B, CS10);
CLEAR_BIT(TCCR1B, CS11);
TCNT1=0;
OCR1A=0;
TIMSK &=~(1<<OCIE1A);
}
An Arduino Uno LED is not toggling and is always in the "on" state, what could be wrong?
#include <avr/io.h>
void delay_timer0(){
TCNT0 = 0x00;
TCCR0A = 0x00;
TCCR0B = 0x01;
while((TIFR0 & 0x01) == 0);
TCCR0A = 0x00;
TCCR0B = 0x00;
TIFR0 = 0x01;
}
This is the infinite loop of toggling under the main method...
int main(void){
DDRB = DDRB | (1<<5); //output pb5
while(1){
PORTB = PORTB ^ (1<<5); //toggle bit
delay_timer0();
}
}
I bet it is a delay function problem
try
#include <util/delay.h>
/* .... */
while(1){
PORTB = PORTB ^ (1<<5); //toggle bit
delay_ms(500);
}
I found the error. I have worked with tinkercad and in that simulator the timer doesn't work. But I have configured this in real environment and it worked fine.
I have written the following C code to trigger two port interrupts in order to blink a LED at different rates, I have used _delay_cycles(900000); instead I want to use a method delayMS(125); using timer interrpts, I tried as shown but Does not work , please help...
#include <msp430.h>
void initTimer_A(void);
void delayMS(int msecs);
unsigned int ofCount;
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
BCSCTL1 = CALBC1_1MHZ; //Set DCO to 1Mhz
DCOCTL = CALDCO_1MHZ;
P1OUT=0X00;
P1DIR=0x01; //P1.0 (LED) as output)
P1IES |= 0x08; // high -> low is selected with IESx = 1.
P1IFG &= ~0x08; // To prevent an immediate interrupt, clear the flag for
P1IE |= 0x08; // Enable interrupts for P1.3
P1DIR &= ~0b00001000; // p1.3 as in
P2OUT=0X00;
P2DIR=0x01; //P2.0 (LED) as output)
P2IES |= 0x08; // high -> low is selected with IESx = 1.
P2IFG &= ~0x08; // To prevent an immediate interrupt, clear the flag for
// P2.3 before enabling the interrupt.
P2IE |= 0x08; // Enable interrupts for P1.3
P2DIR &= ~0b00001000; // p2.3 as in
_enable_interrupt();
// initTimer_A();
ofCount = 0;
P1OUT |= 0x01; //Initially the led will glow
P2OUT |= 0x01; //Initially the led will glow
while(1)
{
}
return 0;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//configure timer
void initTimer_A(void){
TACCR0 = 0;
TACCTL0 |= CCIE;
TACTL = TASSEL_2 + ID_0 + MC_1;
}
void delayMS(int msecs){
ofCount= 0;
TACCR0 = 1000-1;
while(ofCount<=msecs);
TACCR0 = 0;//stp timer
}
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A_CCR0_ISR(void)
{
ofCount++;
}
//+++++++++++++++++ port vectors ++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#pragma vector = PORT1_VECTOR //PORT1 interupt vecotr name
__interrupt void P1_ISR(void) {
while(P1IN == 1){
P1OUT ^= BIT0;
This is the place where I want to change with delayMS() function using timer interrupts ….
_delay_cycles(900000);
//delayMS(125);
P1OUT ^= BIT0;
// delayMS(125);
_delay_cycles(900000);
P1IFG &= ~BIT3; } // clear the interupt flag
}
#pragma vector = PORT2_VECTOR
__interrupt void P2_ISR(void) {
while(P2IN == 1){
P1OUT ^= BIT0;
_delay_cycles(9000);
//delayMS(125);
P1OUT ^= BIT0;
_delay_cycles(9000);
//P2OUT ^= BIT0;
P2IFG &= ~BIT3; } // clear the interupt flag
}
I am looking to receive serial data from an arduino, and then transmit the data received back to the arduino, however I am having trouble receiving the correct data. Below is my code, I am not sure on where I have gone wrong, can anyone see any problems?
I am using register level programming and using USART 3 on the STM32L476RG development board, an I am using ADM485 chip to transfer the data between each serial port.
#include "stm32L476XX.h"
#include "stdio.h"
int T ;
int R ;
uint8_t z;
void USART3_init(void)
{
USART3->BRR |= 26UL<<4; //BAUD RATE MANTISSA 234UL<<4
USART3->BRR |= 1UL<<0; // BAUD RATE FRACTION 6UL<<0
USART3->CR1 |= 1UL<<0; //enable USART
USART3->CR1 ^= 0UL<<28; //1 start bit, 8 data bits, n stop bit
USART3->CR1 ^= 0UL<<12; //also sets word length to 8 data bits
USART3->CR1 ^= 0UL<<10; //no parity control
USART3->CR1 |= 1UL<<6; //Transmission complete interrupt enabled
USART3->CR1 |= 1UL<<7; //TXE interrupt enable
USART3->CR1 |= 1UL<<5; //RXNEIE interrupt enable
USART3->CR2 ^=00UL<<12; //1 stop bit
USART3->CR1 |= 1UL<<3; // enable transmitter
USART3->CR1 |= 1UL<<2; // enable receiver
NVIC_EnableIRQ(USART3_IRQn); //enable USART interrupts
}
void Delay(void)
{
uint32_t i=0;
for (i=0; i<50000; i++){}
}
void USART3_IRQHandler(void)
{
//Delay();
if ((USART3->ISR>>5)&1UL) //Check if RXNE interrupt is high
{
z = USART3->RDR; //put what is on RDR into Z (also clears RXNE flag)
GPIOB->ODR |= 1UL<<5; //set transceiver into transmit mode USART3->TDR = z; // Clears TXIE flag and outputs z on TX
}
if ((USART3->ISR>>7)&1UL) //Check if TXIE interrupt is high
{
GPIOB->ODR &= 0UL<<5; //sets transceiver in receive mode
}
if ((USART3->ISR>>6)&1UL) //Check if TC interrupt is high
{
USART3->ICR |= 1UL<<6; //Clear TC flag
GPIOB->ODR &= 0UL<<5; //Set transceiver in receive mode
}
}
void RCC_GPIO_init(void)
{
RCC->APB1ENR1 |= 1UL<<18; //Enable USART 3 clock
RCC->AHB2ENR |= 1UL<<1; //Enable GPIOB clock
GPIOB->MODER = 0; //reset all register bits
GPIOB->MODER |= 2UL<<20; //enable GPIOB pin 10 as alternate function
GPIOB->MODER |= 2UL<<22; //enable GPIOB pin 11 as alternate function
GPIOB->MODER |= 1UL<<10; //enable GPIOB pin 5 as output
GPIOB->AFR[1] = 0; //reset all register bits
GPIOB->AFR[1] |= 7UL<<8; //enable GPIOB pin 10 as TX
GPIOB->AFR[1] |= 7UL<<12; //enable GPIOB pin 10 as RX
GPIOB->ODR ^= 0UL<<5; //GPIOB pin 5 as low (to put ADM485 transceiver in receive mode)
}
int main (void)
{
RCC_GPIO_init();
USART3_init();
while(1)
{
}
}
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.