What I've been doing to test is hooking up PB4 directly to either Vcc or GND, and by my understanding of how the ADC works, that should fill the ADC registers with 1023 and 0, respectively. After dropping the two least significant bits, that should represent the LED being fully lit, and fully off. Unfortunately, what is happening is LED2 is remaining at a constant brightness roughly equivalent to a PWM value of 1 or 2, no matter what PB4 is connected to.
I've tried this on two different chips, one brand-new, so I'm pretty sure its not a hardware issue. Clock is running at 8MHz, fuses are E4 for lfuse and DF for hfuse.
Code: Select all
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include <avr/power.h>
int main(void)
{
uint8_t bright1 = 0; // PWM value for LED1
uint8_t bright2 = 0; // PWM value for LED2
int analog = 0; // Storage for 10-bit ADC
wdt_enable(WDTO_8S); // Activate watchdog for 8s
ADCSRA = 0x85; // ADC Status Register A
// ADEN = 1
// Activate ADC
// ADSC = 0
// ADC idle
// ADATE = 0
// Auto-Trigger off
// ADIF = 0;
// ADIE = 0;
// ADC Interrupt Disabled
// ADPS[2:0] = 0b101
// Divide clock by 32 to get 250kHz ADC clock
ADCSRB = 0x00; // ADC Status Register B
// BIN = 0
// Bipolar input disabled
// IPR = 0
// Input Polarity normal
// ADT[2:0]
// Not used
ADMUX = 0x02; // ADC Multiplexer Register
// REFS[2:0] = 0b000
// Voltage Reference = Vcc
// ADLAR = 0
// Right Adjust Result
// MUX[3:0] = 0b0010
// Read from ADC2 (PB4)
DDRB = 0x0F; // Set PB[0:3] to output, others input
TCCR0A = 0xF3; // Activate OC0A and OC0B in fast PWM mode
TCCR0B = 0x01; // Timer 0 clock = system clock with no prescaling
while(1)
{
do // Increase brightness of LED1
{
OCR0A = bright1++;
_delay_ms(40);
} while (bright1 != 14);
do // Decrease brightness of LED1
{
OCR0A = bright1--;
_delay_ms(40);
} while (bright1 != 0);
ADCSRA = (1<<ADSC); // Begin ADC conversion
while(ADCSRA && 0x40); // Wait until conversion completes
analog = ADCL | (ADCH << 8);// Put ADC value into variable
bright2 = (analog >> 2); // Drop two LSB of ADC value
OCR0B = bright2; // Set LED2 Brightness
wdt_reset(); // Reset watchdog
}
}