Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Avr-bit_is_clear macro not working as expected?

Status
Not open for further replies.

kgavionics

Full Member level 3
Full Member level 3
Joined
Jun 12, 2012
Messages
167
Helped
7
Reputation
14
Reaction score
11
Trophy points
1,298
Location
Alberta.Canada
Activity points
2,482
Hello guys
I have the following code, which uses 2 interrupts to determine if the Rotary encoder is rotated cw or ccw !
I have written an assembly code which was corrected in this thread and working like a charm!
I translated the code to C, but the result is the opposite to what expect! when I turn the RE clockwise, the output is CCW and vice versa!

I used the macro bit_is_set and bit_is_clear in another c code, and they were ok!
this is my C code:
C:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define FOSC 16000000
unsigned char counter=0;

//INT0 interrupt
ISR(INT0_vect )
{
    if(bit_is_clear(PIND, PD1))
    {
counter++;
PORTF=counter;

PORTC=0X01;

    }
    else
    {
counter--;
PORTF=counter;

PORTC=0X02;
    }
}

//INT1 interrupt
ISR(INT1_vect )
{
    if(bit_is_set(PIND, PD0))
    {
counter--;
PORTF=counter;

PORTC=0X02;
    }
    else
    {
counter++;

PORTF=counter;

PORTC=0X01;

    }
}

int main(void)
{

  /* set PD0 and PD1 as input */
  DDRD &=~ (1 << PD0);                /* PD0 and PD1 as input */
  DDRD &=~ (1 << PD1);       
  PORTD |= (1 << PD0)|(1 << PD1);   /* PD0 and PD1 pull-up enabled   */
  DDRF=0XFF;

  DDRC=0X03;

 EIMSK |= (1<<INT0)|(1<<INT1);        /* enable INT0 and INT1 */
 EICRA |= (1<<ISC01)|(1<<ISC11)|(1<<ISC10); /* INT0 - falling edge, INT1 - rising edge */

  /* enable interrupts */
  sei();


   while(1)
   {
    //do nothing ;)
    _delay_ms(1);
   }

  return 0;
}

Can someone tell me what I'm doing wrong?
 

Hi,

I don't ghink that "bit_is_set" is the problem.
I rather think the interrrupt polarity or the A/B vs B/A connection is the problem.

Mind: your counting is unequal:
When turning in one diriection you get 4 edges per pulse sequence:
* A rising: count
* B falling: count
* A falling: do nothing
* B rising: do nothing

Klaus
 

Thank you klausST for your help, I really appreciate it!
I changed accidentally both interrupts to this (both : bit_is_set, and it works, but I don't know the reason why!
C:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define FOSC 16000000
unsigned char counter=0;

//INT0 interrupt
ISR(INT0_vect )
{
    if(bit_is_set(PIND, PD1)) //---------------------------->change I have made
    {
counter++;
PORTF=counter;

PORTC=0X01;

    }
    else
    {
counter--;
PORTF=counter;

PORTC=0X02;
    }
}

//INT1 interrupt

ISR(INT1_vect )
{
    if(bit_is_set(PIND, PD0))
    {
counter++;
PORTF=counter;

PORTC=0X01;

    }
    else
    {
counter--;
PORTF=counter;

PORTC=0X02;
    }
}
int main(void)
{

  /* set PD0 and PD1 as input */
  DDRD &=~ (1 << PD0);                /* PD0 and PD1 as input */
  DDRD &=~ (1 << PD1);      
  PORTD |= (1 << PD0)|(1 << PD1);   /* PD0 and PD1 pull-up enabled   */
  DDRF=0XFF;

  DDRC=0X03;

EIMSK |= (1<<INT0)|(1<<INT1);        /* enable INT0 and INT1 */
EICRA |= (1<<ISC01)|(1<<ISC11)|(1<<ISC10); /* INT0 - falling edge, INT1 - rising edge */

  /* enable interrupts */
  sei();


   while(1)
   {
    //do nothing ;)
    _delay_ms(1);
   }

  return 0;
}
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top