GB7Jo

      -- Чего вы боитесь больше, нетрезвого водителя
         или робота за рулем?
      -- Пьяного робота..

Kнопка K0 инициирует внешнее прерывание INT0
--------------------------------------------

Пример найден в [1]. Немного адаптировал под ATMega8 и симулятор VMLAB (близкий аналог используемого в макете ATMega88, но проще и дешевле: 0.75USD в китайских онлайн магазинах), добавил обработчик INT1 (кнопка K1 на PD3), в примере ошибка* (DDRD = 1 << PD2;, при нажатии кнопки закоротить выход PD2, должно быть DDRD = ~(1 << PD2);).Чтобы обезопасить себя от коротких замыканий, рекомендуется добавить ограничительный резистор 1K (последовательно с переключателем).

----------

*) http://www.avrfreaks.net/forum/avr-io-short-circuit

There is no real protection for short-circuits per-say. However if you short the pin the AVR isn't going to blow up or break, as the current is somewhat limited. It will get hot if the pin is shorted for a while, and eventually may break. Depending on the application you could limit the short-circuit current to acceptable values (ie: use a resistor in-line with the pin, so a short only draws 20mA).

-Colin

int0.prj

` .MICRO "ATmega8"
` .TOOLCHAIN "GCC"
` ; Bug: 1. erase everything, but 7SEG.c, 7SEG.prj
` ;      2. use GCC, compile with errors;
` ;      3. use GENERIC
` .GCCPATH   "C:\WinAVR"
` .GCCMAKE   AUTO
` .TARGET    "int0.hex"
` .SOURCE    "int0.c"
`
` .TRACE              ; Activate micro trace
`
` ; Following lines are optional; if not included
` ; exactly these values are taken by default
` ; ------------------------------------------------------------
` .POWER VDD=5 VSS=0  ; Power nodes
` .CLOCK 1meg         ; Micro clock
` .STORE 250m         ; Trace (micro+signals) storage time
`
` ; Micro nodes: RESET, AREF, PB0-PB7, PC0-PC6, PD0-PD7, ACO, TIM1OVF, ADC6, ADC7
` ; Define here the hardware around the micro
` ; ------------------------------------------------------------
`
` RK0 PD2 NPD2 1K
` K0  NPD2 VSS
` RK1 PD3 NPD3 1K
` K1  NPD3 VSS
`
` D1  VDD NPB0
` D2  VDD NPB1
` D3  VDD NPB2
` D4  VDD NPB3
` D5  VDD NPB4
` D6  VDD NPB5
` D7  VDD NPB6
` D8  VDD NPB7
`
` R0  PB0 N0 10
` X0  ND2 N0 N0 NPB0
` R1  PB1 N1 10
` X1  ND2 N1 N1 NPB1
` R2  PB2 N2 10
` X2  ND2 N2 N2 NPB2
` R3  PB3 N3 10
` X3  ND2 N3 N3 NPB3
` R4  PB4 N4 10
` X4  ND2 N4 N4 NPB4
` R5  PB5 N5 10
` X5  ND2 N5 N5 NPB5
` R6  PB6 N6 10
` X6  ND2 N6 N6 NPB6
` R7  PB7 N7 10
` X7  ND2 N7 N7 NPB7

-----------------

int0.c

` #include <avr/io.h>
` #include <avr/interrupt.h>
` #include <util/delay.h>
`
` #define DataPort  PORTB  // Using PortC as our Dataport
` #define DataDDR   DDRB
`
` #define DELAY0    200
`
` //Interrupt Service Routine for INT0
` ISR(INT0_vect)
` {
`   unsigned char i, temp;
`
`   // Software debouncing control
`   _delay_ms(DELAY0);
`
`   // Save current value on DataPort
`   temp = DataPort;
`
`   /* This for loop blink LEDs on Dataport 5 times*/
`   for(i = 0; i<5; i++)
`   {
`     DataPort = 0x00;
`     _delay_ms(DELAY0);  // Wait 5 seconds
`     DataPort = 0xFF;
`     _delay_ms(DELAY0);  // Wait 5 seconds
`   }
`
`   //Restore old value to DataPort
`   DataPort = temp;
` }
`
` //Interrupt Service Routine for INT1
` ISR(INT1_vect)
` {
`   unsigned char i, temp;
`
`   // Software debouncing control
`   _delay_ms(DELAY0);
`
`   // Save current value on DataPort
`   temp = DataPort;
`
`   /* This for loop blink LEDs on Dataport 5 times*/
`   for(i = 0; i<5; i++)
`   {
`     DataPort = 0x55;
`     _delay_ms(DELAY0);  // Wait 5 seconds
`     DataPort = 0xAA;
`     _delay_ms(DELAY0);  // Wait 5 seconds
`   }
`
`   //Restore old value to DataPort
`   DataPort = temp;
` }
`
` int main(void)
` {
`   // Set PD2, PD3 as inputs (Using for interupts INT0, INT1)
`   DDRD &= ~(1 << PD2);
`   DDRD &= ~(1 << PD3);
`   // Enable PD2, PD3 pull-up resistors
`   PORTD = 1<<PD2 | 1<<PD3;
`
`   // Configure Dataport as output
`   DataDDR = 0xFF;
`   // Initialise Dataport to 1
`   DataPort = 0x01;
`
`   // Enable INT0 and INT1
`   GICR = 1<<INT0 | 1<<INT1;
`   // Trigger INT0 and INT1 on rising edge
`   MCUCR = 1<<ISC01 | 1<<ISC00 | 1<<ISC11 | 1<<ISC10;
`
`   //Enable Global Interrupt
`   sei();
`
`     while(1)
`     {
`     if(DataPort >= 0x80)
`       DataPort = 1;
`     else
`       // Shift to the left
`       DataPort = DataPort << 1;
`
`     _delay_ms(DELAY0);  // Wait 5 seconds
`     }
` }

Клавиатурная матрица ( 4x4, ATMega8, VMLAB)
-------------------------------------------

Схема пародирует работу макета 118й лаборатории на симуляторе VMLAB + WinAVRC. (но 16 кнопок, но на защелках 74373 инверсная логика -- проблемы симулятора..)

    PC3     PC2     PC1     PC0               PC0..PC3 входы
     |       |       |       |
  -------+---|---+-------+---|---+------ PD0
     |   |   |   |   |   |   |   |
     +--K0   +--K1   +--K2   +--K3
     |       |       |       |
  -------+-------+-------+-------+------ PD1  PD0..PD3 выходы
     |   |   |   |   |   |   |   |
     +--K4   +--K5   +--K6   +--K7
     |       |       |       |
  -------+-------+-------+-------+------ PD2            KX
     |   |   |   |   |   |   |   |                     ----
     +--K8   +--K9   +--KA   +--KB                   --o  o--
     |       |       |       |
  -------+-------+-------+-------+------ PD3  кнопка без фиксации
     |   |   |   |   |   |   |   |            контакты замыкаются
     +--KC   +--KD   +--KE   +--KF            на момент нажатия

buttons.prj

` .MICRO "ATmega8"
` .TOOLCHAIN "GCC" ; Bug: 1. erase everything, but 7SEG.c, 7SEG.prj
`                  ;      2. use GCC, compile with errors;
`                  ;      3. use GENERIC
` .GCCPATH   "C:\WinAVR"
` .GCCMAKE   AUTO
` .TARGET    "buttons.hex"
` .SOURCE    "buttons.c"
`
` .TRACE              ; Activate micro trace
`
` ; Following lines are optional; if not included
` ; exactly these values are taken by default
` ; ------------------------------------------------------------
` .POWER VDD=5 VSS=0  ; Power nodes
` .CLOCK 1meg         ; Micro clock
` .STORE 250m         ; Trace (micro+signals) storage time
`
` ; Micro nodes: RESET, AREF, PB0-PB7, PC0-PC6, PD0-PD7, ACO,
` ;              TIM1OVF, ADC6, ADC7
` ; Define here the hardware around the micro
` ; ------------------------------------------------------------
`
` R0    N0   PD0    10
` R1    N1   PD1    10
` R2    N2   PD2    10
` R3    N3   PD3    10
` R4    N4   PD4    10
` R5    N5   PD5    10
` R6    N6   PD6    10
` R7    N7   PD7    10
`
` R8    N8   PB0    10
` R9    N9   PB1    10
` RA    NA   PB2    10
` RB    NB   PB3    10
` RC    NC   PB4    10
` RD    ND   PB5    10
` RE    NE   PB6    10
` RF    NF   PB7    10
`
` X001  ND2  N0     NX004  NX001
` X002  ND2  NX003  NX004  NX002
` X003  ND2  N0     N0     NX003
` X004  ND2  N8     N8     NX004
` X005  ND2  NX001  Z001   Z000
` X006  ND2  NX002  Z000   Z001
`
` X011  ND2  N1     NX014  NX011
` X012  ND2  NX013  NX014  NX012
` X013  ND2  N1     N1     NX013
` X014  ND2  N8     N8     NX014
` X015  ND2  NX011  Z011   Z010
` X016  ND2  NX012  Z010   Z011
`
` X021  ND2  N2     NX024  NX021
` X022  ND2  NX023  NX024  NX022
` X023  ND2  N2     N2     NX023
` X024  ND2  N8     N8     NX024
` X025  ND2  NX021  Z021   Z020
` X026  ND2  NX022  Z020   Z021
`
` X031  ND2  N3     NX034  NX031
` X032  ND2  NX033  NX034  NX032
` X033  ND2  N3     N3     NX033
` X034  ND2  N8     N8     NX034
` X035  ND2  NX031  Z031   Z030
` X036  ND2  NX032  Z030   Z031
`
` X041  ND2  N4     NX044  NX041
` X042  ND2  NX043  NX044  NX042
` X043  ND2  N4     N4     NX043
` X044  ND2  N8     N8     NX044
` X045  ND2  NX041  Z041   Z040
` X046  ND2  NX042  Z040   Z041
`
` X051  ND2  N5     NX054  NX051
` X052  ND2  NX053  NX054  NX052
` X053  ND2  N5     N5     NX053
` X054  ND2  N8     N8     NX054
` X055  ND2  NX051  Z051   Z050
` X056  ND2  NX052  Z050   Z051
`
` X061  ND2  N6     NX064  NX061
` X062  ND2  NX063  NX064  NX062
` X063  ND2  N6     N6     NX063
` X064  ND2  N8     N8     NX064
` X065  ND2  NX061  Z061   Z060
` X066  ND2  NX062  Z060   Z061
`
` X071  ND2  N7     NX074  NX071
` X072  ND2  NX073  NX074  NX072
` X073  ND2  N7     N7     NX073
` X074  ND2  N8     N8     NX074
` X075  ND2  NX071  Z071   Z070
` X076  ND2  NX072  Z070   Z071
`
` R00  Z000  NX00   1K
` R01  Z010  NX01   1K
` R02  Z020  NX02   1K
` R03  Z030  NX03   1K
` R04  Z040  NX04   1K
` R05  Z050  NX05   1K
` R06  Z060  NX06   1K
` R07  Z070  NX07   1K
`
` X17 _led7cc NX00 NX01 NX02 NX03 NX04 NX05 NX06 NX07  GND
`
` R20 VDD PC0 10K
` K0  PD0 PC0
` R21 VDD PC1 10K
` K1  PD0 PC1
` R22 VDD PC2 10K
` K2  PD0 PC2
` R23 VDD PC3 10K
` K3  PD0 PC3
`
` R24 VDD PC0 10K
` K4  PD1 PC0
` R25 VDD PC1 10K
` K5  PD1 PC1
` R26 VDD PC2 10K
` K6  PD1 PC2
` R27 VDD PC3 10K
` K7  PD1 PC3
`
` R28 VDD PC0 10K
` K8  PD2 PC0
` R29 VDD PC1 10K
` K9  PD2 PC1
` R30 VDD PC2 10K
` KA  PD2 PC2
` R31 VDD PC3 10K
` KB  PD2 PC3
`
` R32 VDD PC0 10K
` KC  PD3 PC0
` R33 VDD PC1 10K
` KD  PD3 PC1
` R34 VDD PC2 10K
` KE  PD3 PC2
` R35 VDD PC3 10K
` KF  PD3 PC3

--------------------------

buttons.c

` #include <avr/io.h>
` #include <util/delay.h>
`
` unsigned char font[] = {
`  0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07,
`  0x7f, 0x6f, 0x77, 0x7c, 0x58, 0x5e, 0x79, 0x71,
`  0
` };
`
` unsigned char rows[]    = { 0xFE, 0xFD, 0xFB, 0xF7 };
` unsigned char columns[] = { 0, 1, 0, 2, 0, 0, 0, 3 };
`
` int main( void) {
`   DDRD = 0xff;
`   DDRB = 0xff;
`   DDRC = 0x00;
`   PORTC= 0x7f;
`
`   unsigned char i;
`   unsigned char x;
`   unsigned char c;
`
`   while (1) {
`     c = 16; // " "
`
`     for (i=0; i<4; i++) {
`       PORTD = rows[i];
`       x = ~(0xf0 | (0x0f & PINC));
`       if ( x) {
`         c = 4 * i + columns[ x - 1];
`         break;
`       }
`     }
`
`     PORTB=0xff;
`     PORTD = font[c];
`     _delay_ms(1);
`     PORTB = ~1;
`     _delay_ms(1);
`     PORTB = 0xff;
`     _delay_ms(1);
`   }
`
`   return 0;
` }

Links
-----

1. http://www.avr-tutorials.com/interrupts/avr-external-interrupt-c-programming
