Stap 4: Microcontroller code
Ik heb mijn werken code omhoog op Github. Het heeft een paar onderdelen:Deze #defines en const verklaringen doen compile-time berekeningen, zodat de code alleen moet doen eenvoudige uint8_t vergelijkingen in plaats van zwevende punt dat niet haalbaar in een microcontroller is. Met behulp van const moedigt de compiler om te doen de berekening tijdens het compileren en dwingt het type van het resultaat aan uint8_t.
#define PWM_FREQ 62500
#define PWM_RESOLUTION (F_CPU / PWM_FREQ)
#define MIN_DUTY_CYCLE 0.40
#define MAX_DUTY_CYCLE 0,80
Const uint8_t MIN_PWM_LEVEL = PWM_RESOLUTION * MIN_DUTY_CYCLE;
Const uint8_t MAX_PWM_LEVEL = PWM_RESOLUTION * MAX_DUTY_CYCLE;#define VREF 1.1
#define DESIRED_VOUT 20,0
#define DIVIDER_RATIO 30,0
#define DESIRED_ADC_IN_V (DESIRED_VOUT / DIVIDER_RATIO)Const uint8_t DESIRED_ADC_RESULT = 255 * DESIRED_ADC_IN_V / VREF;
Deze definiëren sommige nuttig utility macro's, zodat de code eenvoudiger te volgen is:
#define DUTY_CYCLE_REG OCR0B
#define ADC_ENABLE() (ADCSRA | = _BV(ADEN))
#define ADC_START_CONVERSION() (ADCSRA | = _BV(ADSC))
De belangrijkste functie heeft een eerste installatiefase waar blijkt op de verschillende randapparatuur die we nodig hebben:
int main(void) {}
/ * A7 stellen als een uitvoerapparaat. (Nodig voor PWM.) */
DDRA | = _BV(DD7);
PORTA = 0;/ * Ingangsvermogen stabiliseren... laat * /
_delay_ms(500);/*
* Configureren Timer0 als een snelle PWM. Het zal
* - inschakelen van de pin van de uitvoer aan het begin van elke cyclus
* - zwenking op vandoor wanneer de waarde DUTY_CYCLE_REG hits
* -, beschikken over regelterugloop 0 als het hits OCR0A
*/
TCCR0A = _BV(COM0B1) | _BV(WGM01) | _BV(WGM00);
OCR0A = PWM_RESOLUTION;
/ * Start met 40% taakcyclus en oprit te vermijden inrush. */
DUTY_CYCLE_REG = (uint8_t)(PWM_RESOLUTION * 0.40);
/ * Stel Timer0 klokbron als belangrijkste oscillator. Hierdoor wordt de timer. */
TCCR0B = _BV(CS00) | _BV(WGM02);/*
* Zet de ADC,
* - interne spanning ref gebruiken.
* - ADC0 als onze bron configureren
* - links-aanpassen van het resultaat, 8 bits is genoeg voor ons
* - uitschakelen van digitale invoerbuffer op pin
* - inschakelen van de ADC.
*/
ADMUX = / * REF = * / _BV(REFS1) | / * INPUT = * / 0;
ADCSRA | = / * PRESCALER = 16 = 2 ^ * / 4;
ADCSRB | = / * LINKS-AANPASSEN * / _BV(ADLAR);
DDRA & = ~ _BV(DD0);
DIDR0 | = _BV(ADC0D);
ADC_ENABLE();
_delay_ms(1);
Vervolgens loops het gewoon, het lezen van de analoge waarde van de potentiometer en vergelijken met haar doelstelling:
terwijl (1) {}
/ * Wachten op de Timer0 om overloop... * /
loop_until_bit_is_set (TIFR0, TOV0);
/ * Einde van onze OFF periode moet piek spanning... * /
TIFR0 | = _BV(TOV0); / * De markering wissen. *// * De uitgangsspanning controleren. */
ADC_START_CONVERSION();
loop_until_bit_is_clear (ADCSRA, ADSC);
uint8_t adc_result = ADCH;Als (adc_result < DESIRED_ADC_RESULT & &
DUTY_CYCLE_REG < MAX_PWM_LEVEL) {}
DUTY_CYCLE_REG ++;
}
anders als (adc_result > DESIRED_ADC_RESULT & &
DUTY_CYCLE_REG > MIN_PWM_LEVEL) {}
DUTY_CYCLE_REG--;
}
}
}