F5A95


ATMega88
--------

    Я уверен, никто не заметил. (09:41 I'm sure no one noticed)

    Модная штучка (After the Ball), 2015

Интересы производителя (или продавца) и потребителя (или покупателя) совпадают не во всем. Компромисс определяется механизмами рынка и в последнее время Интернетом. Часто бывает, что полезная информация, неожиданно опубликованная в глобальной Сети, может существенно увеличить ценность продукта для потребителя (ценность это не цена).

Так, давно выпускаемый микроконтроллер ATMega-88 (ATMega-8 с аналогичной архитектурой упоминается в релизах WinAVR 2002 года) сегодня приобретается для ремонта существующих устройств, например

  http://opiobjektid.tptlive.ee/Oppemaketi_tutvustus/

либо найдя интересную поделку в Сети. Далее приводится адаптация к ATMega-88 и VMLab+WinAVR примеров, обнаруженных в (см. ссылки).

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

Пример 1. Тест PB0.

  /* pt.c
   * The following program just keeps toggling pin 0 of port B
   */

  //standard include for ATMega16
  #include <avr/io.h>

  // set bit - using bitwise OR operator
  #define sbi(x,y) x |= _BV(y)
  // clear bit - using bitwise AND operator
  #define cbi(x,y) x &= ~(_BV(y))
  // toggle bit - using bitwise XOR operator
  #define tbi(x,y) x ^= _BV(y)
  // check if the y'th bit of register 'x' is high ...
  // test if its AND with 1 is 1
  #define is_high(x,y) (x & _BV(y) == _BV(y))

  /* _BV(a) is a macro which returns the value
     corresponding to 2 to the power 'a'.
     Thus _BV(PX3) would be 0x08 or 0b00001000 */

  int main(void)
  {
      DDRB=0xff; //PORTB as OUTPUT
      PORTB=0x00; //All pins of PORTB LOW

      unsigned int i;
      while(1==1)
      {
          for(i=0;i<8096;i++); // delay
          tbi(PORTB,PB0);      // here the toggling takes place
      }
      return 0;
  }

Схема в VMLab 3.15

  ; ************************************************************
  ; PROJECT:
  ; AUTHOR:
  ; ************************************************************

  ; Micro + software running
  ; ------------------------------------------------------------
  .MICRO "ATmega88" "CKDIV8=1"
  .TOOLCHAIN "GCC"
  .GCCPATH   "C:\WinAVR"
  .GCCMAKE   AUTO
  .TARGET    "pt.hex"
  .SOURCE    "pt.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
  ; ------------------------------------------------------------

  D1 VDD PB0  ; x: Panel LEDs 1 - 8

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

Пример 2. Таймер 0.

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

  #define outp(a, b) b = a
  uint8_t led;
  /* signal handler for timer interrupt TOV0 */

  ISR(TIMER0_OVF_vect) {
      PORTB = ~led;
      led++;
  }

  int main( void) {
      // use PortB for output (LED)
      DDRB = 0xFF;
      // enable timer overflow interrupt
      TIMSK0 = (1<<TOIE0);
      // set timer counter initial value
      TCNT0=0x00;
      // start timer with presscaler 1024.
      // Bug: TCCR0A and TCCR0B seems to be swapped (VMLAB?).
      TCCR0A = (1<<CS00) | (1<<CS02);
      TCCR0B = 0;
      // enable interrupts
      sei();
      // initia1 led value
      led = 0x00;
      for (;;) ;
  }

Схема в VMLab 3.15

  ; ************************************************************
  ; PROJECT:
  ; AUTHOR:
  ; ************************************************************

  ; Micro + software running
  ; ------------------------------------------------------------
  .MICRO "ATmega88" "CKDIV8=1"
  .TOOLCHAIN "GCC"
  .GCCPATH   "C:\WinAVR"
  .GCCMAKE   AUTO
  .TARGET    "timer0.hex"
  .SOURCE    "timer0.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
  ; ------------------------------------------------------------
  D1 VDD PB0
  D2 VDD PB1
  D3 VDD PB2
  D4 VDD PB3
  D5 VDD PB4
  D6 VDD PB5
  D7 VDD PB6
  D8 VDD PB7

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

Пример 3. Таймер1

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

  #define SLOWNESS  2

  // global variable to count the number of overflows
  volatile uint8_t tot_overflow;

  // initialize timer, interrupt and variable
  void timer1_init()
  {
      // set up timer with prescaler = 8
      TCCR1B |= (1 << CS11);
      // initialize counter
      TCNT1 = 0;
      // enable overflow interrupt
      TIMSK1 |= (1 << TOIE1);
      // enable global interrupts
      sei();
      // initialize overflow counter variable
      tot_overflow = 0;
  }

  // TIMER1 overflow interrupt service routine
  // called whenever TCNT1 overflows
  ISR(TIMER1_OVF_vect)
  {
      tot_overflow++;

      // check for number of overflows here itself
      if (tot_overflow >= SLOWNESS)
      {
          PORTD ^= (1 << 0);
          // no timer reset required here as the timer
          // is reset every time it overflows
          tot_overflow = 0;   // reset overflow counter
      }
  }

  int main(void)
  {
      // connect led to pin PD0
      DDRD |= (1 << 0);
      timer1_init();
      while(1);
  }

Схема в VMLab 3.15

  ; ************************************************************
  ; PROJECT:
  ; AUTHOR:
  ; ************************************************************

  ; Micro + software running
  ; ------------------------------------------------------------
  .MICRO "ATmega88" "CKDIV8=1"
  .TOOLCHAIN "GCC"
  .GCCPATH   "C:\WinAVR"
  .GCCMAKE   AUTO
  .TARGET    "timer1.hex"
  .SOURCE    "timer1.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
  ; ------------------------------------------------------------

  D1 VDD PD0

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

Пример 4. АЦП

  #include <avr/io.h>
  #include <util/delay.h>

  // initialize adc
  void adc_init()
  {
      // AREF = AVcc
      ADMUX = (1<<REFS0);

      // ADC Enable and prescaler of 128
      // 16000000/128 = 125000
      ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
  }

  // read adc value
  uint16_t adc_read(uint8_t ch)
  {
      // select the corresponding channel 0~7
      // ANDing with '7' will always keep the value
      // of 'ch' between 0 and 7
      ch &= 0b00000111;  // AND operation with 7
      // clears the bottom 3 bits before ORing
      ADMUX = (ADMUX & 0xF8)|ch;

      // start single conversion
      // write '1' to ADSC
      ADCSRA |= (1<<ADSC);

      // wait for conversion to complete
      // ADSC becomes '0' again
      // till then, run loop continuously
      while(ADCSRA & (1<<ADSC));

      return (ADC);
  }

  int main()
  {
      uint16_t adc_result1;
      uint8_t leds;
      DDRD=0xFF;
      adc_init();

      _delay_ms(50);

      while(1)
      {
          // read adc value at PC1
          adc_result1 = adc_read(1);
          if (adc_result1 >= 0x3FF) PORTD = ~0x1;
          else if (adc_result1 >= 0x380) PORTD = ~0x2;
          else if (adc_result1 >= 0x2FF) PORTD = ~0x4;
          else if (adc_result1 >= 0x280) PORTD = ~0x8;
          else if (adc_result1 >= 0x1FF) PORTD = ~0x10;
          else if (adc_result1 >= 0x180) PORTD = ~0x20;
          else if (adc_result1 >= 0xFF) PORTD = ~0x40;
          else if (adc_result1 >= 0x80) PORTD = ~0x80;
          else PORTD = ~0;
          _delay_ms(50);
      }
  }

Схема в VMLab 3.15 (левый потенциометр)

  ; ************************************************************
  ; PROJECT:
  ; AUTHOR:
  ; ************************************************************

  ; Micro + software running
  ; ------------------------------------------------------------
  .MICRO "ATmega88" "CKDIV8=1"
  .TOOLCHAIN "GCC"
  .GCCPATH   "C:\WinAVR"
  .GCCMAKE   AUTO
  .TARGET    "adc.hex"
  .SOURCE    "adc.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 10meg         ; 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
  ; ------------------------------------------------------------

  V1 PC1 VSS SLIDER_1(0 5)
  D1 VDD PD0
  D2 VDD PD1
  D3 VDD PD2
  D4 VDD PD3
  D5 VDD PD4
  D6 VDD PD5
  D7 VDD PD6
  D8 VDD PD7

  .PLOT V(PD0) V(PC0) V(PC1)

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

Ссылки:

  1. https://kartikmohta.com/tech/avr/tutorial/
  2. http://www.scienceprog.com
          /two-avr-gcc-examples-of-using-avr-8-bit-timers/
  3. http://maxembedded.com/2011/06/avr-timers-timer1/
  4. http://maxembedded.com/2011/06/the-adc-of-the-avr/

  5. Newer VMLab components with source

       https://sites.google.com/site/thvortex/vmlab

