Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
techie_avr
PostPosted: Dec 01, 2005 - 11:19 AM
Rookie


Joined: Oct 19, 2005
Posts: 48


Hi,

Can anyone suggest me a sample code for Switch debounce ?

Iam a newbie to C programming in AVR.
Iam using AT90CAN128 and AVRStudio 4.12.460.

Thank You!!!
 
 View user's profile Send private message  
Reply with quote Back to top
Astaroth
PostPosted: Dec 01, 2005 - 02:32 PM
Wannabe


Joined: Apr 03, 2003
Posts: 57


Here is a fat one:
Code:

char debouncePA1(void)
{
  char ones=0, zeroes=0, i;
  for(i=0;i<9;i++){
    if(PINA&0x01){ // read pin == 1
      ones++;
    } else { // read pin == 0
      zeroes++;
    }
  _delay_ms(10);
  }
  return ones>zeroes;
}

I really prefer a simple hardware debouncer (RC filter). Confused

_________________
___(°)^(°)___
A(VR)staroth
 
 View user's profile Send private message  
Reply with quote Back to top
groenhen
PostPosted: Dec 01, 2005 - 11:15 PM
Posting Freak


Joined: Apr 09, 2005
Posts: 1387
Location: Belgium

Here is the best de-bouncing guide I managed to find:
www.ganssle.com/debouncing.pdf
HTH,

_________________
Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
jfiresto
PostPosted: Dec 02, 2005 - 10:36 AM
Hangaround


Joined: Oct 07, 2002
Posts: 426
Location: Germany

Astaroth wrote:
Here is a fat one:
Code:

char debouncePA1(void)
{
  char ones=0, zeroes=0, i;
  for(i=0;i<9;i++){
    if(PINA&0x01){ // read pin == 1
      ones++;
    } else { // read pin == 0
      zeroes++;
    }
  _delay_ms(10);
  }
  return ones>zeroes;
}

This code will overflow. Sad
 
 View user's profile Send private message  
Reply with quote Back to top
Bingo600
PostPosted: Dec 02, 2005 - 04:23 PM
Raving lunatic


Joined: Apr 25, 2004
Posts: 3947
Location: Denmark

Peter Fleury has these examples on his homepage

http://jump.to/fleury


http://homepage.hispeed.ch/peterfleury/ ... tware.html

http://homepage.hispeed.ch/peterfleury/ ... amples.zip

The debounce is based on code from Peter Danegger if i remember correctly , and is quite neat.

Btw: His Uart & LCD lcd libs are also worth a look.

/Bingo


Last edited by Bingo600 on Nov 13, 2006 - 02:56 PM; edited 1 time in total
 
 View user's profile Send private message  
Reply with quote Back to top
xjedlins
PostPosted: Dec 12, 2005 - 08:49 AM
Rookie


Joined: Dec 04, 2001
Posts: 22


Code:

/*

THE ULTIMATE SOFTWARE DEBOUNCER         

Program: debounce.asm
Version: 1.0
Date:    5/5/2005
Author:  Elio Mazzocca
E-mail:  jnz9876@adam.co.uk

micro used: ATmega8 with internal 4 MHz oscillator
assembled with: AVR Studio 4.0
Timer0 interrupt period: 4 mSEC

Description: This is a 1st order recursive digital filter
   with Schmitt trigger output that filters noisy
   digital inputs to ATmega8 microcontroller.
   The formula employed for the recursive filter:

   ynew = 1/4 xnew + 3/4 yold

   Formula for an inverting Schmitt trigger:

   if(ynew>hi) and (flag=0) then flag=1; vout=1;
   if(ynew<lo) and (flag=1) then flag=0; vout=0;

Use:      The code is placed in Timer0 interrupt routine
   with a 4 mSEC period. The output of the trigger
   is continuously checked in the main program loop
   The interrupt routine checks the PORT bit and
   applies either 0 (keypress) or $3F to the digital
   filter, the output value is then applied to a
   Schmitt trigger with thresholds of 15, 240 for
   an effective "time constant" of 11 interrupts.
   Program requires 11 ints, 19/18 machine cycles,
  6 ints if schmitt threshold is $3C instead of $0F

;
.NOLIST
.INCLUDE "AvrAssembler2\appnotes\m8def.inc"
.LIST

; Register defines

.DEF   yold = R17         ; old/new filter output value, share same reg
.DEF   tmp  = R18         ; new input to filter value/threshold reg
.DEF    flag = R19
.DEF    VOUT = R20

.CSEG
.ORG $0000
   rjmp    Reset   

.ORG OVF0addr
   rjmp   tim0_ovf      ; Timer0 overflow handler

Reset:   
   ldi   R16,   LOW(RAMEND)    ; Initiate Stackpointer
   out   SPL,   R16       ; for use by interrupts
   ldi   R16,   HIGH(RAMEND)
   out   SPH,   R16
                        
   ldi   R16,   (1<<CS01)|(1<<CS00)  ; Fosc = 4 MHz
   out   TCCR0,   R16       ; set Timer/Counter0 Prescaler=64, int = 16x256 uSEC

   ldi   R16,   (1<<TOIE0)    ; set timer0 interrupt enable
   out   TIMSK,   R16       ; in the Timer Interrupt Mask Register
   ldi     R16,    (1<<TOV0)      ; clr pending interrupts
    out     TIFR,   R16      

   ser   tmp
   out   DDRB,   tmp      ; set PORTB = output
   clr   tmp
   out     DDRD,   tmp      ; set PORTD = input
   ser     tmp
   out     PORTD,  tmp      ; turn on PORTD pull-ups
 
   ldi   yold,   $FF      ;optional
   sei            ; enable interrupts
loop:               ; main program loop
   sbrs    VOUT,   0      ; if schmitt out = 1
   rjmp   a1
   sbi     PORTB,  0      ; then set PORTB, bit 0 - LED on
   rjmp    loop
a1:
   cbi     PORTB,  0      ; else clear PORTB, bit 0 - LED off
       rjmp    loop
;------------------------------------------------------------------------
tim0_ovf:
    mov     tmp,    yold      
   lsr     tmp
   lsr     tmp         ; tmp = 1/4 yold
   sub     yold,   tmp      ; 3/4 yold is in left in reg yold
   ldi     tmp,    $3F      ; re-use tmp register for xnew
   sbis    PIND,   0      ; if PIND bit 0 = 0, then input = 1/4 xnew
   clr     tmp
   add   yold,   tmp      ; yold same as ynew, saves 1 instruction/register !

.UNDEF tmp             ; re-use tmp register as threshold reg.
.DEF   thresh = R18   
               ; now apply filter output to schmitt trigger
   ldi     thresh, $0F      ; load lo thresh into threshold register
   sbrc   flag,   0         ; test bit 0 of flag register
   rjmp    s1               
   cp      yold,   thresh
   brsh    s1
   sbr     flag,   (1<<0)      ; set bit 0 of register flag
   sbr     VOUT,   (1<<0)      
s1:
    swap    thresh         ; to test hi thresh, swap nibbles
   cp      yold,   thresh
   brlo    s2
   cbr     flag,   (1<<0)
   cbr     VOUT,   (1<<0)      ; clear bit 0 of register VOUT
s2:
   reti            ; 19/18 (nokeypress/keypress) machine cycles
;------------------------------------------------------------------------
.EXIT



Sorry, dont have original link.

J.
 
 View user's profile Send private message  
Reply with quote Back to top
Thomas Strand
PostPosted: Dec 13, 2005 - 10:28 PM
Hangaround


Joined: Aug 26, 2003
Posts: 222
Location: Trondheim, Norway

Hello!
Here is my code for two switches (UP and DOWN).
Code:

// ---------- In header file ----------
#define KEY_UP         6
#define KEY_DN         7

// Pins
#define KEY_PINS       PIND

// Macros
#define KEY_DN_PRESS   (~(KEY_PINS) & (1<<KEY_DN))
#define KEY_UP_PRESS   (~(KEY_PINS) & (1<<KEY_UP))

// ---------- In main file ----------
int8_t read_keys(void) {
   if(KEY_UP_PRESS) {
      _delay_ms(10);
      while(KEY_UP_PRESS);      // Wait for key to be released
      _delay_ms(10);
      return 1;
   }
   if(KEY_DN_PRESS) {
      _delay_ms(10);
      while(KEY_DN_PRESS);
      _delay_ms(10);
      return -1;
   }
   else return 0;
}

Simple code, but the AVR will hang in the read_keys function as long as one of the buttons is pressed.
That's no problem in my app, interrupts are doing the housekeeping.

Regards,
Thomas
 
 View user's profile Send private message  
Reply with quote Back to top
groenhen
PostPosted: Dec 14, 2005 - 07:56 AM
Posting Freak


Joined: Apr 09, 2005
Posts: 1387
Location: Belgium

Hi Thomas!
Maybe the code you posted works ok for your app., but it's definitely NOT the way to go for a switch debounce code...
I recommend Jack G. Ganssle de-bouncing guide (it has also C-code examples) and the code suggested by xjedlins (asm code by Elio Mazzocca).

_________________
Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
bluegoo
PostPosted: Dec 14, 2005 - 04:25 PM
Posting Freak


Joined: Aug 20, 2005
Posts: 1134
Location: Pool of Goo

FYI Idea

http://www.edn.com/article/CA621638.htm ... axid=10577

link to asm posted previously and also some other interesting links at the bottom of the article Smile
 
 View user's profile Send private message  
Reply with quote Back to top
danni
PostPosted: Dec 14, 2005 - 10:57 PM
Raving lunatic


Joined: Sep 05, 2001
Posts: 2617


Most versions of debouncers are only able to debounce a single key.

My approach need extremely less code and time to debounce 1 ... 8 keys simultaneosly and independent and bulletproofed:

Code:

/************************************************************************
;*                                                                      *
;*              Testing Read and debounce up to 8 keys                  *
;*              Bulletproof: 4 equal samples needed                     *
;*                                                                      *
;*              Author: P. Dannegger                                    *
;*                                                                      *
;***********************************************************************/
#include <io.h>
#include <interrupt.h>
#include <signal.h>

#define KEY_INPUT       PINC
#define LED_OUTPUT      PORTB
#define LED_DIR         DDRB

char key_state;                         // debounced and inverted key state:
                                        // bit = 1: key pressed
char key_press;                         // key press detect


SIGNAL (SIG_OVERFLOW0)
{
  static char ct0, ct1;
  char i;

  i = key_state ^ ~KEY_INPUT;           // key changed ?
  ct0 = ~( ct0 & i );                   // reset or count ct0
  ct1 = ct0 ^ (ct1 & i);                // reset or count ct1
  i &= ct0 & ct1;                       // count until roll over ?
  key_state ^= i;                       // then toggle debounced state
                                        // now debouncing finished
  key_press |= key_state & i;           // 0->1: key press detect
}


char get_key_press( char key_mask )
{
  cli();
  key_mask &= key_press;                // read key(s)
  key_press ^= key_mask;                // clear key(s)
  sei();
  return key_mask;
}


int main( void )
{
  key_state = 0;
  key_press = 0;

  TCCR0 = 1<<CS02;                      //divide by 256 * 256
  TIMSK = 1<<TOIE0;                     //enable timer interrupt

  LED_DIR = 0xFF;
  LED_OUTPUT = 0xFF;
  sei();
  for(;;)                                       // main loop
    LED_OUTPUT ^= get_key_press( 0xFF );        // toggle LEDs on key press
}


And the same in Assembler:
Code:

;*************************************************************************
;*                                                                       *
;*              Testing Read and debounce up to 8 keys                   *
;*              Bulletproof: 4 equal samples needed                      *
;*                                                                       *
;*              Author: P. Dannegger                                     *
;*                                                                       *
;*************************************************************************
.nolist
.include "c:\avr\inc\1200def.inc"
.list
.def    save_sreg       = r0
.def    iwr0            = r1

.def    key_ct0         = r2
.def    key_ct1         = r3
.def    key_state       = r4
.def    key_press       = r5

.def    leds            = r16
.def    wr0             = r17

.equ    key_port        = pind
.equ    led_port        = portb

        rjmp    init
        .org    OVF0addr                ;timer interrupt 6ms
        in      save_sreg, SREG
get8key:
        in      iwr0, key_port
        com     iwr0
        eor     iwr0, key_state
        and     key_ct0, iwr0
        and     key_ct1, iwr0
        com     key_ct0
        eor     key_ct1, key_ct0
        and     iwr0, key_ct0
        and     iwr0, key_ct1
        eor     key_state, iwr0
        and     iwr0, key_state
        or      key_press, iwr0
;
;                       insert other timer functions here
;
        out     SREG, save_sreg
        reti
;-------------------------------------------------------------------------
init:
        ldi     wr0, 0xFF
        out     ddrb, wr0
        ldi     wr0, 1<<CS02^1<<CS00            ;divide by 256 * 256
        out     TCCR0, wr0
        ldi     wr0, 1<<TOIE0           ;enable timer interrupt
        out     TIMSK, wr0

        clr     key_state
        clr     key_press
        ldi     wr0, 0xFF
        mov     key_ct0, wr0
        mov     key_ct1, wr0
        ldi     leds, 0xFF
main:   cli
        eor     leds, key_press         ;toggle LEDs
        clr     key_press               ;clear, if key press action done
        sei
        out     led_port, leds
        rjmp    main
;-------------------------------------------------------------------------


Peter


Last edited by danni on Oct 28, 2011 - 12:16 PM; edited 1 time in total
 
 View user's profile Send private message  
Reply with quote Back to top
groenhen
PostPosted: Dec 14, 2005 - 11:43 PM
Posting Freak


Joined: Apr 09, 2005
Posts: 1387
Location: Belgium

Hi Peter!
Now this is a very *clean* de-bouncing code!
Ursprüngliche Deutsche Qualität?

_________________
Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
*Claus*
PostPosted: Dec 14, 2005 - 11:49 PM
Hangaround


Joined: Sep 05, 2002
Posts: 154
Location: Denmark, next to a very messy desk

Gee that's a lot of code to debounce a single pin.
In my experience the maximum time a switch (tactile style) will bounce is less then 30mS so if the value of the inputs (1-x) is stable for > 30 mS it should be ok. I increment a counter everytime a scan returns the same as the last scan. At 10mS scan interval this would need 3-4 scans (higher number gives "slower" keys) before the actual value (the value passed on to the rest of the program) is updated.

Simple and relative small overhead.

Different types of switches may need a bit of tweaking but 6 scans at 10mS interval works everytime for me.

/claus
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
theusch
PostPosted: Dec 15, 2005 - 12:12 AM
10k+ Postman


Joined: Feb 19, 2001
Posts: 29287
Location: Wisconsin USA

Quote:

Gee that's a lot of code to debounce a single pin.


With all the examples posted in the thread you will need to be more specific about which approach you are commenting on.

Most of the above seem quite economical in terms of code space, SRAM/registers, and cycles.

There definitely is a place for more elaborate filtering. I tend to agree that if the "single pin" you are referring to is connected to a common user switch of some type then a straightforward deterministic cookie-cutter tried-and-true debouncing routine does just fine. But that "single pin" could be connected to any input device--I've got lots of apps with multiple banks of fetch & debounce code. The user buttons might be on one bank, simple switches (e.g. limit switches) on another, and sometimes other stuff--I've got some sensors that when they have crept up to the setpoint will bounce around it, off and on, for several seconds. that drove us nuts till we 'scoped the sensor output as well as the sensor input and saw what was going on. Those types of situations require different measures and all will take more space, cycles, & resources.

Lee
 
 View user's profile Send private message  
Reply with quote Back to top
*Claus*
PostPosted: Dec 15, 2005 - 12:43 AM
Hangaround


Joined: Sep 05, 2002
Posts: 154
Location: Denmark, next to a very messy desk

Lee,
well maybe I was a little to quick on the trigger/Enter key about the code. It doesn't look to bad on a second look. Not that many lines really. My bad.

I defently agree that some sensors output some strange (and sometimes unexpected) garbage which requires som filtering but techie_avr asked about switch debouncing which simplifies this quite a bit.
The idea in xjedlins' code is quite fast to implement and so I often use it if nothing more complicated is required (which haven't really been the case - I'm more digital than analog Wink)

/claus
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
CoolHammer
PostPosted: Sep 16, 2007 - 10:24 PM
Rookie


Joined: Aug 28, 2006
Posts: 43
Location: Finland

I have made a small debouncing test with gasle:s guide. I'm using example 2 as a starting point.
Mine test program is not responsive enough. It is kinda sluggis and it flashes led sometimes when i press a button.
I'm running Atmega 8 with 1 mhz clock.
Here is mine code

Code:

#include <avr/io.h>
#include <avr/interrupt.h>

#define LED1OFF          PORTC |= (1<<5)
#define LED1ON           PORTC &= ~(1<<5)

//Functions
void init_hardware(void);
unsigned char DebounceSwitch(void);
unsigned char RawKeyPressed(void);

//Global variables
unsigned char on_btn;
unsigned char ButtonStatus;
unsigned char LedStatus;

int main (void)
{
   on_btn = 0;
   ButtonStatus = 0;

   init_hardware();
   LED1OFF;
   sei(); //  Enable global interrupts

   for (;;)
   {
    if (ButtonStatus)
   {
    if (LedStatus)
     {
        LED1OFF;
       LedStatus=0;
      }
      else
      {
      LED1ON;
      LedStatus=1;
      }
    }
   }
}

// Timer1 Compare match A interrupt
ISR(TIMER1_COMPA_vect)
{
 ButtonStatus = DebounceSwitch();
}

unsigned char RawKeyPressed(void)
{
 on_btn = ~PINC & (1<<3);
 return on_btn;
}

void init_hardware(void)
{
// PB3 As Output pin
    DDRB |= 1<<DDB3;

 // PC4,5 As Output pin
   DDRC |= 1<<DDC4;
   DDRC |= 1<<DDC5;

 // PC2,3 As Input pin
    DDRC &= ~(1<<2);
   DDRC &= ~(1<<3);

 // PC2,3 Activate internal pullUp resistor
    PORTC |= 1<<DDC2;
    PORTC |= 1<<DDC3;

// Timer setup

 // Configure timer 1 for CTC mode
    TCCR1B |= (1 << WGM12);

// Enable CTC interrupt
    TIMSK |= (1 << OCIE1A);

// Set CTC compare value to 5ms at 1MHz AVR clock, with a prescaler of 8
    OCR1A   = 625;

// Start timer at Fcpu/8
   TCCR1B |= ((1 << CS10));

}

// Service routine called by a timer interrupt
unsigned char DebounceSwitch(void)
 
{
 static uint16_t State = 0; // Current debounce status
 State=(State<<1) | !RawKeyPressed() | 0xe000;
 if(State==0xf000)return 1;
 return 0;
}
 


Any ideas how to improve this?
 
 View user's profile Send private message  
Reply with quote Back to top
morpheous87
PostPosted: Apr 10, 2009 - 11:08 AM
Newbie


Joined: Apr 09, 2009
Posts: 3


hi to all. First i'm quite new in AVR programming, but I hardly need a sample software debouncing code for 3 buttons. I need it in assembler source code for ATmega8515. Can anyone suggest some? Thanks
 
 View user's profile Send private message  
Reply with quote Back to top
Kartman
PostPosted: Apr 10, 2009 - 12:53 PM
10k+ Postman


Joined: Dec 30, 2004
Posts: 11872
Location: Melbourne,Australia

CoolHammer - you code has afew issues. Firslty, your code will fail if any optimisation is turned on for the compiler - your shared variables are not declared 'voltaile'

Secondly, you really don't want to call subroutines from your ISR - this incurs a fair amount of overhead.

What does this line do?

State=(State<<1) | !RawKeyPressed() | 0xe000;

Why don't you just do this:
Code:


volatile char state;
....
ISR code
state<<=1;
if (PINC & (1<<2))  /we'll assume portc.2 as the input
   {
    State |= 1;
   }


To read the switch state assuming your 5mS tick,
Code:


 if (State ==0xff)
    {
    //switch is pressed - has been active for the last 8 ticks (40ms)
    }
 
 View user's profile Send private message  
Reply with quote Back to top
Kartman
PostPosted: Apr 10, 2009 - 12:55 PM
10k+ Postman


Joined: Dec 30, 2004
Posts: 11872
Location: Melbourne,Australia

morpheous, was there not assembler code presented?

Also your question is badly worded - "you hardly need"??? means you really don't need it - not quite what you were trying to say methinks.
 
 View user's profile Send private message  
Reply with quote Back to top
morpheous87
PostPosted: Apr 10, 2009 - 06:29 PM
Newbie


Joined: Apr 09, 2009
Posts: 3


Kartman wrote:
morpheous, was there not assembler code presented?

Also your question is badly worded - "you hardly need"??? means you really don't need it - not quite what you were trying to say methinks.


hardly means that i need this code a lot. Yes i saw an assembler code but i think it's not for ATmega8515, sry for my noobish... I want to put this debouncing fragment in a program for a BCD Clock.
 
 View user's profile Send private message  
Reply with quote Back to top
SFLG35
PostPosted: Jun 30, 2009 - 05:58 PM
Newbie


Joined: Jun 04, 2009
Posts: 9
Location: Tampa, FL

hello i was wondering if you guys wouldnt mind helping me. i am trying to debounce a button using danni's example code, since its been said to be the best for doing multiple buttons at one time. what im trying to do is have the button act as a momentary button. so if you want the output to stay on you have to hold the button down. with the orginal code if you pushed the button it would toggle the input because it used:
Code:
if(get_key_press(1 << SW0))
      {
         OUTPUT_PORT ^= (1 << OUT0);       //Turn OUT0 On
      }


below if the code that i currently have.

Code:
#define F_CPU 8000000UL   //Define CPU Clock Speed 8MHz

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <util/atomic.h>   // need "--std=c99"

typedef unsigned char   u8;
typedef signed short   s16;

#define INPUT_PIN    PIND
#define INPUT_PORT   PORTD
#define INPUT_DDR    DDRD

#define SWO   PD0
#define SW1   PD1
#define SW2   PD2
#define SW3   PD3
#define SW4   PD4
#define SW5   PD5
#define SW6   PD6
#define SW7   PD7
      
#define OUTPUT_DDR    DDRB
#define OUTPUT_PORT   PORTB

#define OUT0   PB0
#define OUT1   PB1
#define OUT2   PB2
#define OUT3   PB3
#define OUT4   PB4
#define OUT5   PB5
#define OUT6   PB6
#define OUT7   PB7

u8 input_state;      //Debounced and inverted key state:
                     //Bit = 1: key pressed
u8 input_press;      //Key Press Detected


ISR(TIMER1_COMPA_vect)            //every 10ms
{
   static u8 ct0 = 0xFF, ct1 = 0xFF;  // 8 * 2bit counters
   u8 i;

   i = ~INPUT_PIN;              // read keys (low active)
   i ^= input_state;            // key changed ?
   ct0 = ~(ct0 & i);            // reset or count ct0
   ct1 = ct0 ^ (ct1 & i);       // reset or count ct1
   i &= ct0 & ct1;              // count until roll over ?
   input_state ^= i;            // then toggle debounced state
   input_press |= input_state & i;   // 0->1: key press detect
}


u8 get_key_press(u8 input_mask)
{
   ATOMIC_BLOCK(ATOMIC_FORCEON)   // read and clear atomic!
   {
   input_mask &= input_press;         // read key(s)
   input_press ^= input_mask;         // clear key(s)
   }
   return input_mask;
}


int main(void)
{
   TCCR1B |=   (1 << WGM12);         //Timer1 Mode 2: CTC
   TCCR1B |=   (1 << CS12);          //Divide by 256
   OCR1A    =   F_CPU / 256 * 10e-3; //Set CTC compare value to 10ms at 8MHz AVR clock, with a prescaler of 256
   TIMSK1 =   (1 << OCIE1A);         //Enable T1 interrupt

   INPUT_DDR  = 0x00;                //Sets INPUT_DDR to be input
   INPUT_PORT = 0xFF;                //Enables pull up resistors on INPUT_PORT
   
   OUTPUT_DDR    = 0xFF;             //Sets OUTPUT_DDR to be output
   
   input_state    = ~INPUT_PIN;      //no action on keypress during reset
   
   sei();

   while(1)
   {
      if(get_key_press(1 << SW0))
      {
         OUTPUT_PORT |= (1 << OUT0);       //Turn OUT0 On
      }
      else if(get_key_press(1 << SW1))
      {
         OUTPUT_PORT |= (1 << OUT1);       //Turn OUT1 On
      }
      else if(get_key_press(1 << SW2))
      {
         OUTPUT_PORT |= (1 << OUT2);       //Turn OUT2 On
      }
      else if(get_key_press(1 << SW3))
      {
         OUTPUT_PORT |= (1 << OUT3);       //Turn OUT3 On
      }
      else if(get_key_press(1 << SW4))
      {
         OUTPUT_PORT |= (1 << OUT4);       //Turn OUT4 On
      }
      else if(get_key_press(1 << SW5))
      {
         OUTPUT_PORT |= (1 << OUT5);       //Turn OUT5 On
      }
      else if(get_key_press(1 << SW6))
      {
         OUTPUT_PORT |= (1 << OUT6);       //Turn OUT6 On
      }
      else if(get_key_press(1 << SW7))
      {
         OUTPUT_PORT |= (1 << OUT7);       //Turn OUT7 On
      }
      else
      {
         OUTPUT_PORT &= ~(1 << OUT0);      //Turn OUT0 Off
         OUTPUT_PORT &= ~(1 << OUT1);      //Turn OUT1 Off
         OUTPUT_PORT &= ~(1 << OUT2);      //Turn OUT2 Off
         OUTPUT_PORT &= ~(1 << OUT3);      //Turn OUT3 Off
         OUTPUT_PORT &= ~(1 << OUT4);      //Turn OUT4 Off
         OUTPUT_PORT &= ~(1 << OUT5);      //Turn OUT5 Off
         OUTPUT_PORT &= ~(1 << OUT6);      //Turn OUT6 Off
         OUTPUT_PORT &= ~(1 << OUT7);      //Turn OUT7 Off
      }
   }
}


if i leave the final else statement in there and push a button, the output never turns on. if i comment out the last else statement, the output will turn on, but i can not turn it back off since it is using an OR instead of XOR

also could someone please explain what is happening in these to sections, as i do not fully understand what is happening inside this interrupt routine and what atomic_block does.

Code:
ISR(TIMER1_COMPA_vect)            //every 10ms
{
   static u8 ct0 = 0xFF, ct1 = 0xFF;  // 8 * 2bit counters
   u8 i;

   i = ~INPUT_PIN;              // read keys (low active)
   i ^= input_state;            // key changed ?
   ct0 = ~(ct0 & i);            // reset or count ct0
   ct1 = ct0 ^ (ct1 & i);       // reset or count ct1
   i &= ct0 & ct1;              // count until roll over ?
   input_state ^= i;            // then toggle debounced state
   input_press |= input_state & i;   // 0->1: key press detect
}


u8 get_key_press(u8 input_mask)
{
   ATOMIC_BLOCK(ATOMIC_FORCEON)   // read and clear atomic!
   {
   input_mask &= input_press;         // read key(s)
   input_press ^= input_mask;         // clear key(s)
   }
   return input_mask;
}


i would also like to use timer1 to flash a light at a 1Hz rate. so say out3 was an led, how would i use timer1 to do both the debouncing at 10ms and then flash an led on out3. im not quite sure how to set that up, or how to use one timer to do multiple things in general.

i am sorry for such a long post, and hope you guys dont mind. as you can tell i am fairly new to c programming and the microcontroller world, so any help is greatly appreciated.

edit: forgot to add that i am using an ATMega644 and that it is running at 8MHz

thanks
dan
 
 View user's profile Send private message  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits