Atmega8 LTO (перенос кода с ардуино)

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Да уж, откуда только эта мания «гигантизма» берётся? 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Кажется разобрался.

Данные макросы (PBx, PCx, PDx), как я понял, используются в конструкциях обращения к регистрам, например:

if (PORTB&(1 << PB0)) {
  // что-что делаем
}

Соответственно имеют значения от 0 до 7 (максимум)?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Да, эксперимент тоже это подтвердил. Век живи - век учись.

void setup() {
  pinMode(PIN_PB0, OUTPUT);
  digitalWrite(PIN_PB0, HIGH);          // Выключаю диод (он подключен анодом на плюс)
  delay(3000);                          // Подождем 3 секунды

  for (uint8_t i = 0; i < PB4; i++) {
    digitalWrite(PIN_PB0, LOW);         // Включаем диод
    delay(1000);                        // Ждем 1 секунду
    digitalWrite(PIN_PB0, HIGH);        // Выключаем диод
    delay(1000);                        // Ждем 1 секунду
  }
  // Все, посчитали сколько раз моргнул диод (он моргнул на PB4 - 4 раза, на PD7 - 7 раз и т.д.
}

void loop() { }

Но где это все описано я так и не нашел ((

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

BOOM Ищите файл iom8a.h в папке ...\hardware\tools\avr\avr\include\avr- там всё описано...

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

iom8a.h в папке ...\hardware\tools\avr\avr\include\avr- там всё описано...

Ничего я там не нашел. Вот содержимое файла:

/*****************************************************************************
 *
 * Copyright (C) 2015 Atmel Corporation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in
 *   the documentation and/or other materials provided with the
 *   distribution.
 *
 * * Neither the name of the copyright holders nor the names of
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/


#ifndef _AVR_ATMEGA8A_H_INCLUDED
#define _AVR_ATMEGA8A_H_INCLUDED


#ifndef _AVR_IO_H_
#  error "Include <avr/io.h> instead of this file."
#endif

#ifndef _AVR_IOXXX_H_
#  define _AVR_IOXXX_H_ "iom8a.h"
#else
#  error "Attempt to include more than one <avr/ioXXX.h> file."
#endif

/* Registers and associated bit numbers */

#define TWBR    _SFR_IO8(0x00)

#define TWSR    _SFR_IO8(0x01)
#define TWPS0   0
#define TWPS1   1
#define TWS3    3
#define TWS4    4
#define TWS5    5
#define TWS6    6
#define TWS7    7

#define TWAR    _SFR_IO8(0x02)
#define TWGCE   0
#define TWA0    1
#define TWA1    2
#define TWA2    3
#define TWA3    4
#define TWA4    5
#define TWA5    6
#define TWA6    7

#define TWDR    _SFR_IO8(0x03)

/* Combine ADCL and ADCH */
#ifndef __ASSEMBLER__
#define ADC     _SFR_IO16(0x04)
#endif
#define ADCW    _SFR_IO16(0x04)

#define ADCL    _SFR_IO8(0x04)
#define ADCH    _SFR_IO8(0x05)

#define ADCSRA  _SFR_IO8(0x06)
#define ADPS0   0
#define ADPS1   1
#define ADPS2   2
#define ADIE    3
#define ADIF    4
#define ADFR    5
#define ADSC    6
#define ADEN    7

#define ADMUX   _SFR_IO8(0x07)
#define MUX0    0
#define MUX1    1
#define MUX2    2
#define MUX3    3
#define ADLAR   5
#define REFS0   6
#define REFS1   7

#define ACSR    _SFR_IO8(0x08)
#define ACIS0   0
#define ACIS1   1
#define ACIC    2
#define ACIE    3
#define ACI     4
#define ACO     5
#define ACBG    6
#define ACD     7

#define UBRRL   _SFR_IO8(0x09)

#define UCSRB   _SFR_IO8(0x0A)
#define TXB8    0
#define RXB8    1
#define UCSZ2   2
#define TXEN    3
#define RXEN    4
#define UDRIE   5
#define TXCIE   6
#define RXCIE   7

#define UCSRA   _SFR_IO8(0x0B)
#define MPCM    0
#define U2X     1
#define UPE     2
#define DOR     3
#define FE      4
#define UDRE    5
#define TXC     6
#define RXC     7

#define UDR     _SFR_IO8(0x0C)

#define SPCR    _SFR_IO8(0x0D)
#define SPR0    0
#define SPR1    1
#define CPHA    2
#define CPOL    3
#define MSTR    4
#define DORD    5
#define SPE     6
#define SPIE    7

#define SPSR    _SFR_IO8(0x0E)
#define SPI2X   0
#define WCOL    6
#define SPIF    7

#define SPDR    _SFR_IO8(0x0F)

#define PIND    _SFR_IO8(0x10)
#define PIND7   7
#define PIND6   6
#define PIND5   5
#define PIND4   4
#define PIND3   3
#define PIND2   2
#define PIND1   1
#define PIND0   0

#define DDRD    _SFR_IO8(0x11)
#define DDRD7   7
// Inserted "DDD7" from "DDRD7" due to compatibility
#define DDD7    7
#define DDRD6   6
// Inserted "DDD6" from "DDRD6" due to compatibility
#define DDD6    6
#define DDRD5   5
// Inserted "DDD5" from "DDRD5" due to compatibility
#define DDD5    5
#define DDRD4   4
// Inserted "DDD4" from "DDRD4" due to compatibility
#define DDD4    4
#define DDRD3   3
// Inserted "DDD3" from "DDRD3" due to compatibility
#define DDD3    3
#define DDRD2   2
// Inserted "DDD2" from "DDRD2" due to compatibility
#define DDD2    2
#define DDRD1   1
// Inserted "DDD1" from "DDRD1" due to compatibility
#define DDD1    1
#define DDRD0   0
// Inserted "DDD0" from "DDRD0" due to compatibility
#define DDD0    0

#define PORTD   _SFR_IO8(0x12)
#define PORTD7  7
#define PORTD6  6
#define PORTD5  5
#define PORTD4  4
#define PORTD3  3
#define PORTD2  2
#define PORTD1  1
#define PORTD0  0

#define PINC    _SFR_IO8(0x13)
#define PINC6   6
#define PINC5   5
#define PINC4   4
#define PINC3   3
#define PINC2   2
#define PINC1   1
#define PINC0   0

#define DDRC    _SFR_IO8(0x14)
#define DDRC6   6
// Inserted "DDC6" from "DDRC6" due to compatibility
#define DDC6    6
#define DDRC5   5
// Inserted "DDC5" from "DDRC5" due to compatibility
#define DDC5    5
#define DDRC4   4
// Inserted "DDC4" from "DDRC4" due to compatibility
#define DDC4    4
#define DDRC3   3
// Inserted "DDC3" from "DDRC3" due to compatibility
#define DDC3    3
#define DDRC2   2
// Inserted "DDC2" from "DDRC2" due to compatibility
#define DDC2    2
#define DDRC1   1
// Inserted "DDC1" from "DDRC1" due to compatibility
#define DDC1    1
#define DDRC0   0
// Inserted "DDC0" from "DDRC0" due to compatibility
#define DDC0    0

#define PORTC   _SFR_IO8(0x15)
#define PORTC6  6
#define PORTC5  5
#define PORTC4  4
#define PORTC3  3
#define PORTC2  2
#define PORTC1  1
#define PORTC0  0

#define PINB    _SFR_IO8(0x16)
#define PINB7   7
#define PINB6   6
#define PINB5   5
#define PINB4   4
#define PINB3   3
#define PINB2   2
#define PINB1   1
#define PINB0   0

#define DDRB    _SFR_IO8(0x17)
#define DDRB7   7
// Inserted "DDB7" from "DDRB7" due to compatibility
#define DDB7    7
#define DDRB6   6
// Inserted "DDB6" from "DDRB6" due to compatibility
#define DDB6    6
#define DDRB5   5
// Inserted "DDB5" from "DDRB5" due to compatibility
#define DDB5    5
#define DDRB4   4
// Inserted "DDB4" from "DDRB4" due to compatibility
#define DDB4    4
#define DDRB3   3
// Inserted "DDB3" from "DDRB3" due to compatibility
#define DDB3    3
#define DDRB2   2
// Inserted "DDB2" from "DDRB2" due to compatibility
#define DDB2    2
#define DDRB1   1
// Inserted "DDB1" from "DDRB1" due to compatibility
#define DDB1    1
#define DDRB0   0
// Inserted "DDB0" from "DDRB0" due to compatibility
#define DDB0    0

#define PORTB   _SFR_IO8(0x18)
#define PORTB7  7
#define PORTB6  6
#define PORTB5  5
#define PORTB4  4
#define PORTB3  3
#define PORTB2  2
#define PORTB1  1
#define PORTB0  0

/* Reserved [0x19..0x1B] */

#define EECR    _SFR_IO8(0x1C)
#define EERE    0
#define EEWE    1
#define EEMWE   2
#define EERIE   3

#define EEDR    _SFR_IO8(0x1D)

/* Combine EEARL and EEARH */
#define EEAR    _SFR_IO16(0x1E)

#define EEARL   _SFR_IO8(0x1E)
#define EEARH   _SFR_IO8(0x1F)

#define UCSRC   _SFR_IO8(0x20)
#define UCPOL   0
#define UCSZ0   1
#define UCSZ1   2
#define USBS    3
#define UPM0    4
#define UPM1    5
#define UMSEL   6
#define URSEL   7

#define UBRRH   _SFR_IO8(0x20)

#define WDTCR   _SFR_IO8(0x21)
#define WDP0    0
#define WDP1    1
#define WDP2    2
#define WDE     3
#define WDCE    4

#define ASSR    _SFR_IO8(0x22)
#define TCR2UB  0
#define OCR2UB  1
#define TCN2UB  2
#define AS2     3

#define OCR2    _SFR_IO8(0x23)

#define TCNT2   _SFR_IO8(0x24)

#define TCCR2   _SFR_IO8(0x25)
#define CS20    0
#define CS21    1
#define CS22    2
#define WGM21   3
#define COM20   4
#define COM21   5
#define WGM20   6
#define FOC2    7

/* Combine ICR1L and ICR1H */
#define ICR1    _SFR_IO16(0x26)

#define ICR1L   _SFR_IO8(0x26)
#define ICR1H   _SFR_IO8(0x27)

/* Combine OCR1BL and OCR1BH */
#define OCR1B   _SFR_IO16(0x28)

#define OCR1BL  _SFR_IO8(0x28)
#define OCR1BH  _SFR_IO8(0x29)

/* Combine OCR1AL and OCR1AH */
#define OCR1A   _SFR_IO16(0x2A)

#define OCR1AL  _SFR_IO8(0x2A)
#define OCR1AH  _SFR_IO8(0x2B)

/* Combine TCNT1L and TCNT1H */
#define TCNT1   _SFR_IO16(0x2C)

#define TCNT1L  _SFR_IO8(0x2C)
#define TCNT1H  _SFR_IO8(0x2D)

#define TCCR1B  _SFR_IO8(0x2E)
#define CS10    0
#define CS11    1
#define CS12    2
#define WGM12   3
#define WGM13   4
#define ICES1   6
#define ICNC1   7

#define TCCR1A  _SFR_IO8(0x2F)
#define WGM10   0
#define WGM11   1
#define FOC1B   2
#define FOC1A   3
#define COM1B0  4
#define COM1B1  5
#define COM1A0  6
#define COM1A1  7

#define SFIOR   _SFR_IO8(0x30)
#define ACME    3
#define PSR2    1
#define PSR10   0
#define PUD     2
#define ADHSM   4

#define OSCCAL  _SFR_IO8(0x31)
#define OSCCAL0 0
#define OSCCAL1 1
#define OSCCAL2 2
#define OSCCAL3 3
#define OSCCAL4 4
#define OSCCAL5 5
#define OSCCAL6 6
#define OSCCAL7 7

#define TCNT0   _SFR_IO8(0x32)

#define TCCR0   _SFR_IO8(0x33)
#define CS00    0
#define CS01    1
#define CS02    2

#define MCUCSR  _SFR_IO8(0x34)
#define PORF    0
#define EXTRF   1
#define BORF    2
#define WDRF    3

#define MCUCR   _SFR_IO8(0x35)
#define ISC00   0
#define ISC01   1
#define ISC10   2
#define ISC11   3
#define SM0     4
#define SM1     5
#define SM2     6
#define SE      7

#define TWCR    _SFR_IO8(0x36)
#define TWIE    0
#define TWEN    2
#define TWWC    3
#define TWSTO   4
#define TWSTA   5
#define TWEA    6
#define TWINT   7

#define SPMCR   _SFR_IO8(0x37)
#define SPMEN   0
#define PGERS   1
#define PGWRT   2
#define BLBSET  3
#define RWWSRE  4
#define RWWSB   6
#define SPMIE   7

#define TIFR    _SFR_IO8(0x38)
#define TOV0    0
#define TOV1    2
#define OCF1B   3
#define OCF1A   4
#define ICF1    5
#define TOV2    6
#define OCF2    7

#define TIMSK   _SFR_IO8(0x39)
#define TOIE0   0
#define TOIE1   2
#define OCIE1B  3
#define OCIE1A  4
#define TICIE1  5
#define TOIE2   6
#define OCIE2   7

#define GIFR    _SFR_IO8(0x3A)
#define INTF0   6
#define INTF1   7

#define GICR    _SFR_IO8(0x3B)
#define IVCE    0
#define IVSEL   1
#define INT0    6
#define INT1    7

/* Reserved [0x3C] */

/* SP [0x3D..0x3E] */

/* SREG [0x3F] */



/* Values and associated defines */


#define SLEEP_MODE_IDLE (0x00<<4)
#define SLEEP_MODE_ADC (0x01<<4)
#define SLEEP_MODE_PWR_DOWN (0x02<<4)
#define SLEEP_MODE_PWR_SAVE (0x03<<4)
#define SLEEP_MODE_STANDBY (0x06<<4)

/* Interrupt vectors */
/* Vector 0 is the reset vector */
/* External Interrupt Request 0 */
#define INT0_vect            _VECTOR(1)
#define INT0_vect_num        1

/* External Interrupt Request 1 */
#define INT1_vect            _VECTOR(2)
#define INT1_vect_num        2

/* Timer/Counter2 Compare Match */
#define TIMER2_COMP_vect            _VECTOR(3)
#define TIMER2_COMP_vect_num        3

/* Timer/Counter2 Overflow */
#define TIMER2_OVF_vect            _VECTOR(4)
#define TIMER2_OVF_vect_num        4

/* Timer/Counter1 Capture Event */
#define TIMER1_CAPT_vect            _VECTOR(5)
#define TIMER1_CAPT_vect_num        5

/* Timer/Counter1 Compare Match A */
#define TIMER1_COMPA_vect            _VECTOR(6)
#define TIMER1_COMPA_vect_num        6

/* Timer/Counter1 Compare Match B */
#define TIMER1_COMPB_vect            _VECTOR(7)
#define TIMER1_COMPB_vect_num        7

/* Timer/Counter1 Overflow */
#define TIMER1_OVF_vect            _VECTOR(8)
#define TIMER1_OVF_vect_num        8

/* Timer/Counter0 Overflow */
#define TIMER0_OVF_vect            _VECTOR(9)
#define TIMER0_OVF_vect_num        9

/* Serial Transfer Complete */
#define SPI_STC_vect            _VECTOR(10)
#define SPI_STC_vect_num        10

/* USART, Rx Complete */
#define USART_RXC_vect            _VECTOR(11)
#define USART_RXC_vect_num        11

/* USART Data Register Empty */
#define USART_UDRE_vect            _VECTOR(12)
#define USART_UDRE_vect_num        12

/* USART, Tx Complete */
#define USART_TXC_vect            _VECTOR(13)
#define USART_TXC_vect_num        13

/* ADC Conversion Complete */
#define ADC_vect            _VECTOR(14)
#define ADC_vect_num        14

/* EEPROM Ready */
#define EE_RDY_vect            _VECTOR(15)
#define EE_RDY_vect_num        15

/* Analog Comparator */
#define ANA_COMP_vect            _VECTOR(16)
#define ANA_COMP_vect_num        16

/* 2-wire Serial Interface */
#define TWI_vect            _VECTOR(17)
#define TWI_vect_num        17

/* Store Program Memory Ready */
#define SPM_RDY_vect            _VECTOR(18)
#define SPM_RDY_vect_num        18

#define _VECTORS_SIZE 38


/* Constants */

#define SPM_PAGESIZE 64
#define FLASHSTART   0x0000
#define FLASHEND     0x1FFF
#define RAMSTART     0x0060
#define RAMSIZE      1024
#define RAMEND       0x045F
#define E2START     0
#define E2SIZE      512
#define E2PAGESIZE  4
#define E2END       0x01FF
#define XRAMEND      RAMEND


/* Fuses */

#define FUSE_MEMORY_SIZE 2

/* Low Fuse Byte */
#define FUSE_SUT_CKSEL0  (unsigned char)~_BV(0)
#define FUSE_SUT_CKSEL1  (unsigned char)~_BV(1)
#define FUSE_SUT_CKSEL2  (unsigned char)~_BV(2)
#define FUSE_SUT_CKSEL3  (unsigned char)~_BV(3)
#define FUSE_SUT_CKSEL4  (unsigned char)~_BV(4)
#define FUSE_SUT_CKSEL5  (unsigned char)~_BV(5)
#define FUSE_BODEN       (unsigned char)~_BV(6)
#define FUSE_BODLEVEL    (unsigned char)~_BV(7)
#define LFUSE_DEFAULT    (FUSE_SUT_CKSEL1 & FUSE_SUT_CKSEL2 & FUSE_SUT_CKSEL3 & FUSE_SUT_CKSEL4)


/* High Fuse Byte */
#define FUSE_BOOTRST     (unsigned char)~_BV(0)
#define FUSE_BOOTSZ0     (unsigned char)~_BV(1)
#define FUSE_BOOTSZ1     (unsigned char)~_BV(2)
#define FUSE_EESAVE      (unsigned char)~_BV(3)
#define FUSE_CKOPT       (unsigned char)~_BV(4)
#define FUSE_SPIEN       (unsigned char)~_BV(5)
#define FUSE_WTDON       (unsigned char)~_BV(6)
#define FUSE_RSTDISBL    (unsigned char)~_BV(7)
#define HFUSE_DEFAULT    (FUSE_BOOTSZ0 & FUSE_BOOTSZ1 & FUSE_SPIEN)



/* Lock Bits */
#define __LOCK_BITS_EXIST
#define __BOOT_LOCK_BITS_0_EXIST
#define __BOOT_LOCK_BITS_1_EXIST


/* Signature */
#define SIGNATURE_0 0x1E
#define SIGNATURE_1 0x93
#define SIGNATURE_2 0x07


#endif /* #ifdef _AVR_ATMEGA8A_H_INCLUDED */

 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Там же лежит файл portpins.h они все подтягиваются по цепочке Arduino.h-io.h-файл под конкретный камень-portpins.h...

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Ладно, не суть. Разобрался для чего и на том хорошо. Не буду в эти дебри лезть пока.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Читаю книгу Евстифеева, и мне кажется в ней ошибка:

Страница 241, Таблица 2.63 Разряды регистров GICR (GIMSK), читаю о INT0 и INT1

А книгу все нахваливают в интернете...

PS: Странно, ссылку на файл заменяет на хрен пойми что.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

А что не нравится то ? ISC11 ISC10 ISC01 ISC00 это ?

А смысл читать не даташит ? -

https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2486-8-bit-AVR-mi...

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

А что не нравится то ? ISC11 ISC10 ISC01 ISC00 это ?

))) Вот ты все знаешь и понимаешь, поэтому сразу видно - не читал. Не нравится мне "Описание" у INT0 и INT1. Прочти внимательно (скрин выше).

Стараюсь для начала понять что к чему и почему. А это мне на русском удобнее (да и не особо я с англицким дружу).

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

When the INT1 bit is set (one) and the I-bit in the Status Register (SREG) is set (one), the external pin interrupt is enabled.

Всё четко. Только для INT1 надо использовать биты ISC11 and ISC10...

• Bit 7 – INT1: External Interrupt Request 1 Enable When the INT1 bit is set (one) and the I-bit in the Status Register (SREG) is set (one), the external pin interrupt is enabled. The Interrupt Sense Control1 bits 1/0 (ISC11 and ISC10) in the MCU general Control Register (MCUCR) define whether the external interrupt is activated on rising and/or falling edge of the INT1 pin or level sensed. Activity on the pin will cause an interrupt request even if INT1 is configured as an output. The corresponding interrupt of External Interrupt Request 1 is executed from the INT1 Interrupt Vector.

• Bit 6 – INT0: External Interrupt Request 0 Enable When the INT0 bit is set (one) and the I-bit in the Status Register (SREG) is set (one), the external pin interrupt is enabled. The Interrupt Sense Control0 bits 1/0 (ISC01 and ISC00) in the MCU general Control Register (MCUCR) define whether the external interrupt is activated on rising and/or falling edge of the INT0 pin or level sensed. Activity on the pin will cause an interrupt request even if INT0 is configured as an output. The corresponding interrupt of External Interrupt Request 0 is executed from the INT0 Interrupt Vector.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Не троль меня )) В книге Евстифеева описания для INT0 и INT1 идентичны как под копирку.

Уже боюсь эту книгу, но ничего другого русскоязычного не знаю...

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Думаю это ошибка копи-паста ...

Green
Offline
Зарегистрирован: 01.10.2015

Это мелочи. В даташитах тоже попадается. Просто логику нужно включать.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

Думаю это ошибка копи-паста ...

Я тоже так думаю, читаю дальше с осторожностью. Собственно полез в эти, еще пока для меня дебри, во-первых немного по разбираться, а во-вторых энкодер на внешнем прерывании (отлично работающий на Arduino Nano с Atmega328):

  PCICR |= (1 << PCIE2);                              // |
  PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);          // | Нужно для работы прерываний ISR (PCINT2_vect) ATmega88/ATmega168/ATmega328
  sei();                                              // |

ISR(PCINT2_vect) {

Не заработал на Atmega8:

  GICR |= (1 << INT0) | (0 << INT1);                                           // | Нужно для работы прерываний ISR - ATmega8A/ATmega16/ATmega32
  MCUCR &= ~((1 << ISC00) | (1 << ISC01) | (1 << ISC10) | (1 << ISC11));       // | Сбрасываем биты ISCxx в "ноль"
  MCUCR |= (1 << ISC00) | (0 << ISC01) | (1 << ISC10) | (0 << ISC11);          // | Устанавливаем срабатывание по любому изменению логического уровня (для Encoder это же самое "то"?)
  sei();      

ISR(INT0_vect) {

 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

PCIINT одно на обе ноги, а INT0 и INT1 это разные прерывания

А:

MCUCR &= ~((1 << ISC00) | (1 << ISC01) | (1 << ISC10) | (1 << ISC11));

MCUCR |= (1 << ISC00) | (0 << ISC01) | (1 << ISC10) | (0 << ISC11);

принято писать от старшего бита к младшему

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

А:

MCUCR &= ~((1 << ISC00) | (1 << ISC01) | (1 << ISC10) | (1 << ISC11));

MCUCR |= (1 << ISC00) | (0 << ISC01) | (1 << ISC10) | (0 << ISC11);

принято писать от старшего бита к младшему

Вот так?

  GICR |= (0 << INT1) | (1 << INT0);                                           // | Нужно для работы прерываний ISR - ATmega8A/ATmega16/ATmega32
  MCUCR &= ~((1 << ISC11) | (1 << ISC10) | (1 << ISC01) | (1 << ISC00));       // | Сбрасываем биты ISCxx в "ноль"
  MCUCR |= (0 << ISC11) | (0 << ISC10) | (0 << ISC01) | (1 << ISC00);          // | Устанавливаем срабатывание по любому изменению логического уровня (для Encoder это же самое "то"?)
  sei();                                                                       // | Разрешаем глобальные прерывания

Собственно я тут пытаюсь изобразить следующую логику: Включаем прерывание на PD2, как только происходит любое  изменение уровня - происходит прерывание INT0_vect (может не правильно последнее назвал).

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Вам надо отслеживать прерывание на двух каналах ? Тогда надо оба разрешать и оба отслеживать !

PCINT разбиты на группы по этому там было одно прерывание на два канала сразу

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Нет, у меня на энкодер только PD2 (INT0) подключено. PD3 (INT1) вообще пока не задействовано.

Странно вот что, в книге написано, что ISC01=0, ISC00=1 - "ЗАРЕЗЕРВИРОВАНО". А в даташите как "Any logical change on INT0 generates an interrupt request."

Я выставлял по даташиту. Может стоит сменить?

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018
MCUCR &= ~(1 << ISC01);
MCUCR |= (1 << ISC00);
GICR |= (1 << INT0);     
sei();      

Atmega8 нет в наличии, а на Atmega328p код:

ISR(INT0_vect) {
}

void setup () {
	EICRA &= ~(1 << ISC01);
	EICRA |= (1 << ISC00);
	EIMSK |= (1 << INT0); 
}

void loop() {
}

четко входит в прерывание на каждое изменение.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir, огромное спасибо за участие. Но, блин, где-то косяк - не работает. Приведу весь код:

#include "Rotary.h"

// список выводов для подключения к разрядам A, B, C, D, E, F, G, H
uint8_t pinSegments[8] = {PIN_PB1, PIN_PB2, PIN_PB3, PIN_PB5, PIN_PB0, PIN_PB7, PIN_PB6, PIN_PB4};
// выводы на МК   =      { 15,      16,       17,       19,      14,      10,      9,       18}

// значения для вывода цифр 0-9

Rotary r = Rotary(PIN_PD2, PIN_PC5);
uint32_t number = 1234000;

byte numbers[] = {
  0B11111100,  // | '0'             // Байт: ABCDEFGH
  0B01100000,  // | '1'             //      A
  0B11011010,  // | '2'             //    -----
  0B11110010,  // | '3'             //   |     |
  0B01100110,  // | '4'             //  F|  G  |B
  0B10110110,  // | '5'             //   |-----|
  0B10111110,  // | '6'             //  E|     |C
  0B11100000,  // | '7'             //   |  D  |
  0B11111110,  // | '8'             //    -----   * H
  0B11110110,  // | '9'
};

// аноды/катоды семисегментного индикатора
uint8_t pinAnode[4] = {PIN_PC2, PIN_PC0, PIN_PC3, PIN_PC1};
//        выводы МК = { 25,     23,       26,       24   }

void setup() {
  // Сконфигурировать контакты как выходы
  DDRB = 0B11111111;
  /*
    for (uint8_t i = 0; i < 8; i++) {
      pinMode(pinSegments[i], OUTPUT);
    }
  */
  for (uint8_t i = 0; i < 4; i++) {
    pinMode(pinAnode[i], OUTPUT);
    digitalWrite(pinAnode[i], HIGH); // Выключаю
  }
/*
  GICR |= (0 << INT1) | (1 << INT0);                                           // | Нужно для работы прерываний ISR - ATmega8A/ATmega16/ATmega32
  MCUCR &= ~((1 << ISC11) | (1 << ISC10) | (1 << ISC01) | (1 << ISC00));       // | Сбрасываем биты ISCxx в "ноль"
  MCUCR |= (0 << ISC11) | (0 << ISC10) | (0 << ISC01) | (1 << ISC00);          // | Устанавливаем срабатывание по любому изменению логического уровня (для Encoder это же самое "то"?)
  sei();                                                                       // | Разрешаем глобальные прерывания
*/
/*
  Komandir:
*/
  MCUCR &= ~(1 << ISC01);
  MCUCR |= (1 << ISC00);
  GICR |= (1 << INT0);
  sei();

  r.begin();
}

ISR(INT0_vect) {      // Это для Atmega8/16/32
  unsigned char result = r.process();

  if (result) {
    if (result == DIR_CW) {
      number += 10000;
    } else {
      number -= 10000;
    }
  }
}

void printNum (uint16_t num) {
  uint16_t bitNum;
  uint16_t temp = 1000;
  for (uint8_t i = 0; i < 4; i++) {
    bitNum = (uint16_t)(num / temp);
    for (int j = 0; j < 8; j++) {
      digitalWrite(pinSegments[j], bitRead(numbers[bitNum], 7 - j));
    }

    digitalWrite(pinAnode[i], LOW);     // | Зажигаю цифру позиции i
    delayMicroseconds(500);
    digitalWrite(pinAnode[i], HIGH);    // | Гашу цифру позиции i
    num = num - temp * bitNum;
    temp = temp / 10;
  }
}

void loop() {
  printNum (number / 1000);
}

Библиотека Rotary.h (использовал ее в 2х проектах на Arduino Nano v2, лежит в той же папке): https://github.com/brianlow/Rotary

Переносил код из ISR() в loop(), срабатывало, но как-то непонятно. Медленно крутишь - срабатывает, покрутил быстро - нет, потом опять медленно крутишь - опять нет. Немного погодя - опять начинает "работать". Непонятка.

ЗЫ: Энкодер новый, но на всякий случай смотрел осциллографом - отличное качество энкодера, даже дребезга нет. Четкие "импульсы".

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Насколько я вижу из примеров библиотеки - используются прерывания с обоих каналов энкодера ! То есть надо настраивать и разрешать оба прерывания. А из ISR(INT0_vect) и ISR(INT1_vect) вызывать общий обработчик.

MCUCR &= ~(1 << ISC01) | (1 << ISC11);
MCUCR |= (1 << ISC00) | (1 << ISC10); 
GICR |= (1 << INT0) | (1 << INT1);    
void INTROTARY {
  unsigned char result = r.process();

  if (result) {
    if (result == DIR_CW) {
      number += 10000;
    } else {
      number -= 10000;
    }
  }
}

ISR(INT0_vect) {
  INTROTARY()
}
ISR(IN1_vect) {
  INTROTARY()
}

P.S. я перелопатил массив в теме про Фантомное свечение...код будет сильно меньше !

http://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/fantomnaya-zasvetka-na-semisegmentnike?page=1#comment-642821

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

Насколько я вижу из примеров библиотеки - используются прерывания с обоих каналов энкодера ! То есть надо настраивать и разрешать оба прерывания. А из ISR(INT0_vect) и ISR(INT1_vect) вызывать общий обработчик.

Так как у меня уже готовая плата, использовать эту библиотеку мне просто не получится значит.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Rotary(PIN_PD2, PIN_PC5); - так нет. На PIN_PC5 нет внешнего прерывания.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Я попробовал ради эксперимента код Kakmyc'а:

#include "Rotary.h"

// список выводов для подключения к разрядам A, B, C, D, E, F, G, H
uint8_t pinSegments[8] = {PIN_PB1, PIN_PB2, PIN_PB3, PIN_PB5, PIN_PB0, PIN_PB7, PIN_PB6, PIN_PB4};
// выводы на МК   =      { 15,      16,       17,       19,      14,      10,      9,       18}

// значения для вывода цифр 0-9

Rotary r = Rotary(PIN_PD2, PIN_PC5);
uint32_t number = 1234000;

byte numbers[] = {
  0B11111100,  // | '0'             // Байт: ABCDEFGH
  0B01100000,  // | '1'             //      A
  0B11011010,  // | '2'             //    -----
  0B11110010,  // | '3'             //   |     |
  0B01100110,  // | '4'             //  F|  G  |B
  0B10110110,  // | '5'             //   |-----|
  0B10111110,  // | '6'             //  E|     |C
  0B11100000,  // | '7'             //   |  D  |
  0B11111110,  // | '8'             //    -----   * H
  0B11110110,  // | '9'
};

// аноды/катоды семисегментного индикатора
uint8_t pinAnode[4] = {PIN_PC2, PIN_PC0, PIN_PC3, PIN_PC1};
//        выводы МК = { 25,     23,       26,       24   }

void setup() {
  // Сконфигурировать контакты как выходы
  DDRB = 0B11111111;
  /*
    for (uint8_t i = 0; i < 8; i++) {
      pinMode(pinSegments[i], OUTPUT);
    }
  */
  for (uint8_t i = 0; i < 4; i++) {
    pinMode(pinAnode[i], OUTPUT);
    digitalWrite(pinAnode[i], HIGH); // Выключаю
  }
  /*
    GICR |= (0 << INT1) | (1 << INT0);                                           // | Нужно для работы прерываний ISR - ATmega8A/ATmega16/ATmega32
    MCUCR &= ~((1 << ISC11) | (1 << ISC10) | (1 << ISC01) | (1 << ISC00));       // | Сбрасываем биты ISCxx в "ноль"
    MCUCR |= (0 << ISC11) | (0 << ISC10) | (0 << ISC01) | (1 << ISC00);          // | Устанавливаем срабатывание по любому изменению логического уровня (для Encoder это же самое "то"?)
    sei();                                                                       // | Разрешаем глобальные прерывания
  */
  /*
    Komandir:
  */
  MCUCR &= ~(1 << ISC00);
  MCUCR |= (1 << ISC01);
  GICR |= (1 << INT0);
  sei();

  r.begin();
}

ISR(INT0_vect) {      // Это для Atmega8/16/32
  int8_t tick;
  digitalRead(PIN_PD2) ? tick = 1 : tick = -1;
  number += (int16_t)tick * 10000;
  /*
    unsigned char result = r.process();

    if (result) {
      if (result == DIR_CW) {
        number += 10000;
      } else {
        number -= 10000;
      }
    }
  */
}

void printNum (uint16_t num) {
  uint16_t bitNum;
  uint16_t temp = 1000;
  for (uint8_t i = 0; i < 4; i++) {
    bitNum = (uint16_t)(num / temp);
    for (int j = 0; j < 8; j++) {
      digitalWrite(pinSegments[j], bitRead(numbers[bitNum], 7 - j));
    }

    digitalWrite(pinAnode[i], LOW);     // | Зажигаю цифру позиции i
    delayMicroseconds(500);
    digitalWrite(pinAnode[i], HIGH);    // | Гашу цифру позиции i
    num = num - temp * bitNum;
    temp = temp / 10;
  }
}

void loop() {
  printNum (number / 1000);
}

Эффект следующий - при повороте в любую сторону срабатывает только одно (в моем случае - уменьшение значения). Но это уже прогресс!!! Срабатывает чётко (почти как "пацанчики", это шутка)) )!

Его бы допилить и отлично будет! )

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

Rotary(PIN_PD2, PIN_PC5); - так нет. На PIN_PC5 нет внешнего прерывания.

Я знаю, поэтому и сказал, что библиотека Rotary мне не подойдет. Плата уже в железе имеется.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Как вариант использовать для прерываний таймер - на частоте, достаточной для обслуживания энкодера ...

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

BOOM пишет:

Я попробовал ради эксперимента код Kakmyc'а:

#include "Rotary.h"

// список выводов для подключения к разрядам A, B, C, D, E, F, G, H
uint8_t pinSegments[8] = {PIN_PB1, PIN_PB2, PIN_PB3, PIN_PB5, PIN_PB0, PIN_PB7, PIN_PB6, PIN_PB4};
// выводы на МК   =      { 15,      16,       17,       19,      14,      10,      9,       18}

// значения для вывода цифр 0-9

Rotary r = Rotary(PIN_PD2, PIN_PC5);
uint32_t number = 1234000;

byte numbers[] = {
  0B11111100,  // | '0'             // Байт: ABCDEFGH
  0B01100000,  // | '1'             //      A
  0B11011010,  // | '2'             //    -----
  0B11110010,  // | '3'             //   |     |
  0B01100110,  // | '4'             //  F|  G  |B
  0B10110110,  // | '5'             //   |-----|
  0B10111110,  // | '6'             //  E|     |C
  0B11100000,  // | '7'             //   |  D  |
  0B11111110,  // | '8'             //    -----   * H
  0B11110110,  // | '9'
};

// аноды/катоды семисегментного индикатора
uint8_t pinAnode[4] = {PIN_PC2, PIN_PC0, PIN_PC3, PIN_PC1};
//        выводы МК = { 25,     23,       26,       24   }

void setup() {
  // Сконфигурировать контакты как выходы
  DDRB = 0B11111111;
  /*
    for (uint8_t i = 0; i < 8; i++) {
      pinMode(pinSegments[i], OUTPUT);
    }
  */
  for (uint8_t i = 0; i < 4; i++) {
    pinMode(pinAnode[i], OUTPUT);
    digitalWrite(pinAnode[i], HIGH); // Выключаю
  }
  /*
    GICR |= (0 << INT1) | (1 << INT0);                                           // | Нужно для работы прерываний ISR - ATmega8A/ATmega16/ATmega32
    MCUCR &= ~((1 << ISC11) | (1 << ISC10) | (1 << ISC01) | (1 << ISC00));       // | Сбрасываем биты ISCxx в "ноль"
    MCUCR |= (0 << ISC11) | (0 << ISC10) | (0 << ISC01) | (1 << ISC00);          // | Устанавливаем срабатывание по любому изменению логического уровня (для Encoder это же самое "то"?)
    sei();                                                                       // | Разрешаем глобальные прерывания
  */
  /*
    Komandir:
  */
  MCUCR &= ~(1 << ISC00);
  MCUCR |= (1 << ISC01);
  GICR |= (1 << INT0);
  sei();

  r.begin();
}

ISR(INT0_vect) {      // Это для Atmega8/16/32
  int8_t tick;
  digitalRead(PIN_PD2) ? tick = 1 : tick = -1;
  number += (int16_t)tick * 10000;
  /*
    unsigned char result = r.process();

    if (result) {
      if (result == DIR_CW) {
        number += 10000;
      } else {
        number -= 10000;
      }
    }
  */
}

void printNum (uint16_t num) {
  uint16_t bitNum;
  uint16_t temp = 1000;
  for (uint8_t i = 0; i < 4; i++) {
    bitNum = (uint16_t)(num / temp);
    for (int j = 0; j < 8; j++) {
      digitalWrite(pinSegments[j], bitRead(numbers[bitNum], 7 - j));
    }

    digitalWrite(pinAnode[i], LOW);     // | Зажигаю цифру позиции i
    delayMicroseconds(500);
    digitalWrite(pinAnode[i], HIGH);    // | Гашу цифру позиции i
    num = num - temp * bitNum;
    temp = temp / 10;
  }
}

void loop() {
  printNum (number / 1000);
}

Эффект следующий - при повороте в любую сторону срабатывает только одно (в моем случае - уменьшение значения). Но это уже прогресс!!! Срабатывает чётко (почти как "пацанчики", это шутка)) )!

Его бы допилить и отлично будет! )

Для данного метода прерывание надо настроить на отслеживание RISING ! Анализировать не digitalRead(PIN_PD2) ? tick = 1 : tick = -1;

а digitalRead(PIN_PС5) ? tick = 1 : tick = -1;

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

Для данного метода прерывание надо настроить на отслеживание RISING ! Анализировать не digitalRead(PIN_PD2) ? tick = 1 : tick = -1;

а digitalRead(PIN_PС5) ? tick = 1 : tick = -1;

Попробовал сделать вот так:

  MCUCR |= (1 << ISC01);
  MCUCR |= (1 << ISC00);
  GICR |= (1 << INT0);
  sei();
=====================
ISR(INT0_vect) {      // Это для Atmega8/16/32
  int8_t tick;
//  digitalRead(PIN_PD2) ? tick = 1 : tick = -1;
  digitalRead(PIN_PС5) ? tick = 1 : tick = -1;
  number += (int16_t)tick * 10000;
  /*
    unsigned char result = r.process();

    if (result) {
      if (result == DIR_CW) {
        number += 10000;
      } else {
        number -= 10000;
      }
    }
  */
}

Получил ошибку при компиляции:

LED-TEST-ENCODER:61:20: error: stray '\320' in program

   digitalRead(PIN_PС5) ? tick = 1 : tick = -1;

                    ^

LED-TEST-ENCODER:61:21: error: stray '\241' in program

   digitalRead(PIN_PС5) ? tick = 1 : tick = -1;

                     ^

D:\Data\AVR\LED-TEST-ENCODER\LED-TEST-ENCODER.ino: In function 'void __vector_1()':

LED-TEST-ENCODER:61:15: error: 'PIN_P' was not declared in this scope

   digitalRead(PIN_PС5) ? tick = 1 : tick = -1;

               ^~~~~

D:\Data\AVR\LED-TEST-ENCODER\LED-TEST-ENCODER.ino:61:15: note: suggested alternative: 'PIN_PD7'

   digitalRead(PIN_PС5) ? tick = 1 : tick = -1;

               ^~~~~

               PIN_PD7

exit status 1
stray '\320' in program

То есть, как я понимаю - ругается на то, что в прерывании я обрабатываю вообще "левую ногу". Я прав?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Скорее всего я не верно понял #78 (((

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Может у меня русская С попала ?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

BOOM пишет:

 ругается на то, что в прерывании я обрабатываю вообще "левую ногу". Я прав?

Нет, я не прав тут. "Тупо скопировал", "С" была русской. Заменил на английскую - то же самое. Нужно оба состояния сравнивать.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

Может у меня русская С попала ?

Да, так и было. Но не работает. Состояние обоих контактов нужно анализировать.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

https://www.customelectronics.ru/arduino-vneshnie-preryivaniya-podklyuchenie-enkodera/

Тут по RISING на канале A, проверяют канал B и все работает ... (второй же канал на PC5 ?)

Может конечно у вас какой то хитрый энкодер 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir! Вот так заработало "в обе стороны":

ISR(INT0_vect) {      // Это для Atmega8/16/32
  int8_t tick;
  if ( ((digitalRead(PIN_PC5) ? tick = 1 : tick = -1) == 1) && ((digitalRead(PIN_PD2) ? tick = 1 : tick = -1) == -1 )) {
    number += (int16_t)tick * 10000;
  } else {
    number -= (int16_t)tick * 10000;
  }
}

Но, видимо, дребезг все-же есть, так как не точно по 1 единице уменьшается/прибавляется, а бывает через несколько.

Я думаю и сам "if" проще можно записать и как-то еще дребезг нужно погасить.

ОГРОМНОЕ ТЕБЕ СПАСИБО! Долго тупил бы один.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

Может конечно у вас какой то хитрый энкодер 

Вот такие энкодеры у меня: https://aliexpress.ru/item/1005003084166943.html

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Странно ... по RISING - PD2 должен быть ВСЕГДА в HIGH

B все что касается tick в крайнем скетче ЛИШНЕЕ !

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

Странно ... по RISING - PD2 должен быть ВСЕГДА в HIGH

А как так то? Коммутация идет энкодером на GND, при покое VCC (HIGH) на выводе энкодера всегда (на обоих выводах, смотрел осциллографом). При вращении "пульсации" идут к GND как раз.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

BOOM пишет:

Но, видимо, дребезг все-же есть, так как не точно по 1 единице уменьшается/прибавляется, а бывает через несколько.

Да, заметил, что при уменьшении иногда прибавляется. И наоборот. Думаю это все же дребезг.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Тогда может проверить FALLING ?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Komandir пишет:

Тогда может проверить FALLING ?

Только поменялось направление. То есть было влево - меньше, стало больше и все.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Проанализировал сам энкодер более глубже - при одном "тике" происходит дребезг контактов (считай уже когда почти 360гр). Как победить можно дребезг?

Последний вариант кода:

ISR(INT0_vect) {      // Это для Atmega8/16/32
  int8_t tick, res1, res2;
  //  digitalRead(PIN_PD2) ? tick = 1 : tick = -1;
  delay(1);                                             // Не помогает
  res1 = digitalRead(PIN_PC5);
  delay(1);                                             // Не помогает
  res2 = digitalRead(PIN_PD2);
  if ( ((res1 ? tick = 1 : tick = -1) == 1) && (((res2) ? tick = 1 : tick = -1) == -1 ) ) {
    number += (int16_t)tick * 1000;
  } else {
    number -= (int16_t)tick * 1000;
  }
}

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Я на самом деле удивлен - Почему в решении этого вопроса мне откликнулся помогать только komandir?

На вопрос о ветре и его обгоне уже сотни комментариев - а вы же даже это проверить не сможете (одни умозаключения, на сколько я смог увидеть). Мой пример (и его решение)  можно проверить в реальном железе. Но никого. ))

Наверное решение (как обычно) простое и всем просто лень отвечать. А на "сотрясание ветра" потратить часть жизни только в радость )))

ЗЫ: Я без негатива, просто интересное наблюдение. )

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Надо в прерывании сохранять текущий micros или millis и на входе проверять сколько прошло от последнего срабатывания - если мало (опытным путем), то сразу на выход ... Как то так...

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

надо апаратно устранять дребезг от энкодера и не е@ать мозги себе и контролеру.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

xDriver

BOOM пишет:

Плата уже в железе имеется.

Green
Offline
Зарегистрирован: 01.10.2015

BOOM пишет:

Я на самом деле удивлен - Почему в решении этого вопроса мне откликнулся помогать только komandir?


Наверно потому, что Komandir с детьми/внуками ещё не наняньчился.)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

BOOM пишет:

На вопрос о ветре и его обгоне уже сотни комментариев - а вы же даже это проверить не сможете (одни умозаключения, на сколько я смог увидеть).

какие умозаключения? просто вспомнить курс Теоретической механики )))

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Странно, но даже с задержкой в обработке прерывания (доводил до неприличных 250мс) не поменялось в лучшую сторону. Даже стало не через 1-2 "перепрыгивать", а срузу через 4-5. Я вообще ленивый человек, но... Hantek DSO5102P к выводам энкодера подключен (даже второй шнурок для наглядности достал), работа самого энкодера:

(Да, ему для таких измерений не сильно хватает памяти, DSO5102B с 2Мб был бы предпочтительнее, но и такие измерения я за несколько лет делаю второй или третий раз).

Я не совсем понимаю почему разные интервалы, это неисправность самого энкодера? Поменять не проблема - штук 20-30 есть в "запасе".

И код (последний вариант):

#include "Rotary.h"
#include "kakmyc_btn.h"
// список выводов для подключения к разрядам A, B, C, D, E, F, G, H
uint8_t pinSegments[8] = {PIN_PB1, PIN_PB2, PIN_PB3, PIN_PB5, PIN_PB0, PIN_PB7, PIN_PB6, PIN_PB4};
// выводы на МК   =      { 15,      16,       17,       19,      14,      10,      9,       18}

Rotary r = Rotary(PIN_PD2, PIN_PC5);

uint32_t number = 1234000;

uint16_t prevTime = millis();       // | Для устранения дребезга энкодера
const uint8_t Rotary1 = PIN_PD2;    // | Первый пин энкодера
const uint8_t Rotary2 = PIN_PC5;    // | Второй пин энкодера
const uint16_t rtInterval = 250;     // | Интервал между срабатыванием энкодера (устранение дребезга контактов энкодера)

// значения для вывода цифр 0-9
byte numbers[] = {
  0B11111100,  // | '0'             // Байт: ABCDEFGH
  0B01100000,  // | '1'             //      A
  0B11011010,  // | '2'             //    -----
  0B11110010,  // | '3'             //   |     |
  0B01100110,  // | '4'             //  F|  G  |B
  0B10110110,  // | '5'             //   |-----|
  0B10111110,  // | '6'             //  E|     |C
  0B11100000,  // | '7'             //   |  D  |
  0B11111110,  // | '8'             //    -----   * H
  0B11110110,  // | '9'
};

// аноды/катоды семисегментного индикатора
uint8_t pinAnode[4] = {PIN_PC2, PIN_PC0, PIN_PC3, PIN_PC1};
//        выводы МК = { 25,     23,       26,       24   }

void setup() {
  // Сконфигурировать контакты как выходы
  DDRB = 0B11111111;
  /*
    for (uint8_t i = 0; i < 8; i++) {
      pinMode(pinSegments[i], OUTPUT);
    }
  */
  for (uint8_t i = 0; i < 4; i++) {
    pinMode(pinAnode[i], OUTPUT);
    digitalWrite(pinAnode[i], HIGH); // Выключаю
  }
  /*
    GICR |= (0 << INT1) | (1 << INT0);                                           // | Нужно для работы прерываний ISR - ATmega8A/ATmega16/ATmega32
    MCUCR &= ~((1 << ISC11) | (1 << ISC10) | (1 << ISC01) | (1 << ISC00));       // | Сбрасываем биты ISCxx в "ноль"
    MCUCR |= (0 << ISC11) | (0 << ISC10) | (0 << ISC01) | (1 << ISC00);          // | Устанавливаем срабатывание по любому изменению логического уровня (для Encoder это же самое "то"?)
    sei();                                                                       // | Разрешаем глобальные прерывания
  */
  /*
    Komandir:
  */
  MCUCR |= (1 << ISC01);
  MCUCR |= (1 << ISC00);
  GICR |= (1 << INT0);
  sei();

  r.begin();
}

ISR(INT0_vect) {      // Это для Atmega8/16/32
  int8_t tick, res1, res2;
  uint16_t currentTime = millis();

  if (currentTime - prevTime > rtInterval) {
    res1 = digitalRead(PIN_PC5);
    res2 = digitalRead(PIN_PD2);
    if ( (( digitalRead(PIN_PC5) ? tick = 1 : tick = -1) == 1) && ((digitalRead(PIN_PD2) ? tick = 1 : tick = -1) == -1 ) ) {
      number += (int16_t)tick * 1000;
    } else {
      number -= (int16_t)tick * 1000;
    }
  }
}

void printNum (uint16_t num) {
  uint16_t bitNum;
  uint16_t temp = 1000;
  for (uint8_t i = 0; i < 4; i++) {
    bitNum = (uint16_t)(num / temp);
    for (int j = 0; j < 8; j++) {
      digitalWrite(pinSegments[j], bitRead(numbers[bitNum], 7 - j));
    }

    digitalWrite(pinAnode[i], LOW);     // | Зажигаю цифру позиции i
    delayMicroseconds(500);
    digitalWrite(pinAnode[i], HIGH);    // | Гашу цифру позиции i
    num = num - temp * bitNum;
    temp = temp / 10;
  }
}

void loop() {
  printNum (number / 1000);
}

 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Что то вы совсем поплыли ...

1 Интервалы обратно пропорционально зависят от скорости вращения энкодера !!!

2 Где обновление prevTime ?

3 Дребезг по паспорту энкодера - около 2 мс !!!

4 На осциллограмме дребезга не видно СОВСЕМ.

5 Внешняя подтяжка выходов энкодера есть ?

Код:

#define printVar(x) do { Serial.print(#x);  Serial.print('='); Serial.print(x); Serial.println(';'); } while (false)

int volatile num(0);
int oldnum(1);

ISR(INT0_vect) {
	digitalRead(3) ? num-- : num++;
}

void setup () {
	Serial.begin(9600);
	Serial.println("Start");
	EICRA |= (1 << ISC01) | (1 << ISC00);
	EIMSK |= (1 << INT0); 
}

void loop() {
	while (num==oldnum);
	printVar(num);
	oldnum=num;
}

работает идеально на 328 (энкодер подключен на 2 3)

const uint16_t rtInterval = 2;


ISR(INT0_vect) {
  uint16_t currentTime = millis();
  if (currentTime - prevTime > rtInterval) {
    prevTime = currentTime ;
    digitalRead(PIN_PC5) ? number += 1000 :number -= 1000) ;
  }
}