attiny13 PWM привело в выключенном состоянии - PullRequest
0 голосов
/ 20 марта 2020

Извините за мой английский sh. У меня есть некоторые проблемы на attiny13 с PWM. ШИМ отлично работает на настройке. Однако, пока значение OCR0B становится равным нулю или максимуму, светодиод не выключается или не горит. Я пытался использовать «PORTB & = ~ (1 <<);», пока OCROX был нулевым, но он не работает. потом я обнаружил, что должен добавить «ISR (TIM0_COMPA_vect)» для прерывания. Я недавно начал работать над крошечным, так что это слишком сложно, особенно для меня, и, пожалуйста, игнорируйте мою неграмотность. Это код, который я использовал. </p>

#define F_CPU 1200000
#define LED PB1 

#include <avr/io.h>

const int  buttonPin = 4;    // the pin that the pushbutton is attached to

int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 1;
int model; // previous state of the button

void setup() {
  // initialize the button pin as a input:
  pinMode(buttonPin, INPUT);
  // initialize the LED as an output:

}

void adc_setup (void)
{
    // Set the ADC input to PB2/ADC1
    ADMUX |= (1 << MUX0);
    ADMUX |= (1 << ADLAR);

    // Set the prescaler to clock/128 & enable ADC
    // At 9.6 MHz this is 75 kHz.
    // See ATtiny13 datasheet, Table 14.4.
    ADCSRA |= (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN);
}

void pwm_setup (void)
{
    // Set Timer 0 prescaler to clock/8.
    // At 9.6 MHz this is 1.2 MHz.
    // See ATtiny13 datasheet, Table 11.9.
    TCCR0B |= (1 << CS01);

    // Set to 'Fast PWM' mode
    TCCR0A |= (1 << WGM01) | (1 << WGM00);

    // Clear OC0B output on compare match, upwards counting.
    TCCR0A |= (1 << COM0B1);
}

void pwm_write (int val)
{
    OCR0B = val;
}

void button()
{
buttonState = digitalRead(buttonPin);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // if the current state is HIGH then the button went from off to on:
      buttonPushCounter++;
      model = buttonPushCounter % 5 ;
    } else {
      // if the current state is LOW then the button went from on to off:
    }
    // Delay a little bit to avoid bouncing
    delay(250);
  }
  lastButtonState = buttonState;
}

int main (void)
{
    int adc_in;

    // LED is an output.
    DDRB |= (1 << LED);  

    adc_setup();
    pwm_setup();

    while (1) {
        // Get the ADC value
        button();
        //adc_in = adc_read();
        // Now write it to the PWM counter
        switch(model)
        {
         case 0:
         pwm_write(0);
         //PORTB &= ~ (1<<PB3);
         break;
         case 1:
         pwm_write(50);
         break;
         case 2:
         pwm_write(100);
         break;
         case 3:
         pwm_write(150);
         break;
         case 4:
         pwm_write(255);
         //PORTB |= (1<<PB3);
         break;
        }

}
}

Я считаю, что другой код успешно включается, выключается и настраивается светодиод с помощью прерывания с двумя кнопками, но я не понимаю, как код записывает значения в OCR0X. Может кто-нибудь объяснить мне связь между OCR0X и долгом (count, pwm value) во втором коде. Потому что мне нужно записать постоянные значения в этих OCR0X.

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


#define PWM_PIN      PB0
#define KEY_UP_PIN    PB1
#define KEY_DOWN_PIN    PB2

#define PWM_DUTY_MIN    (0)
#define PWM_DUTY_MAX    (100)
#define PWM_DUTY_STEP   (1)
#define KEY_UP      (1 << 1)
#define KEY_DOWN    (1 << 2)

static volatile uint8_t duty = 0;
static uint8_t counter = 0;
static void process(void);
static uint8_t read_keys(void);

ISR(TIM0_COMPA_vect)
{

  if (duty > PWM_DUTY_MIN && duty < PWM_DUTY_MAX) {
    if (counter == 0) {
      PORTB |= _BV(PWM_PIN);
    } else if (counter == duty) {
      PORTB &= ~_BV(PWM_PIN);
    }
    if (++counter == PWM_DUTY_MAX) {
      counter = 0;
    }
  }
}

int
main(void)
{

  /* setup */
  DDRB |= _BV(PWM_PIN); // set PWM pin as OUTPUT
  PORTB |= _BV(KEY_UP_PIN)|_BV(KEY_DOWN_PIN);
  TCCR0A |= _BV(WGM01); // set timer counter mode to CTC
  TCCR0B |= _BV(CS00); // set prescaler
  OCR0A = 95; // set Timer's counter max value (96 - 1)
  TIMSK0 |= _BV(OCIE0A); // enable Timer CTC interrupt
  sei(); // enable global interrupts

  _delay_ms(100); // time of debounce

  /* loop */
  while (1) {
    process();
    _delay_ms(8);
  }
}

void
process(void)
{
  uint8_t keys;

  if (!(keys = read_keys())) {
    return;
  }

  if ((keys & KEY_UP) && duty < PWM_DUTY_MAX) {
    duty += PWM_DUTY_STEP;
  }

  if ((keys & KEY_DOWN) && duty > PWM_DUTY_MIN) {
    duty -= PWM_DUTY_STEP;
  }

  if (duty == PWM_DUTY_MIN) {
    PORTB &= ~_BV(PWM_PIN);
  } else if (duty == PWM_DUTY_MAX) {
    PORTB |= _BV(PWM_PIN);
  }
}

static uint8_t
read_keys(void)
{
  uint8_t result = 0;

  if ((PINB & _BV(KEY_UP_PIN)) == 0) {
    result |= KEY_UP;
  }

  if ((PINB & _BV(KEY_DOWN_PIN)) == 0) {
    result |= KEY_DOWN;
  }

  return result;
}
...