Author Topic: ATmega328P C Code  (Read 1562 times)

0 Members and 1 Guest are viewing this topic.

Offline strawberry

  • Frequent Contributor
  • **
  • Posts: 279
  • Country: lv
ATmega328P C Code
« on: February 21, 2017, 05:35:29 pm »
Atmel studio7 => Arduino uno.
How this code is functioning and why it doen't? Why timer do not read ADC register?
Code: [Select]
#define F_CPU 1000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

void adc_setup (void)
ADMUX |= (1<<MUX0) | (1<<REFS0) | (1<<REFS1);                         // Set the ADC input, internal REF
ADMUX |= (1<<ADLAR);                                                                   //shift ADC to 8bit
ADCSRA|= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0) | (1<<ADEN);// Prescaler to clock/128 & enable ADC

int adc_read (void)
ADCSRA |= (1 << ADSC); // Start the conversion
_delay_ms(10);             // Wait for it to finish

return ADCH;

void pwm_setup (void)

TCCR0A |= (1<<CS01);                              // Set Timer 0 prescaler to clock/8.
TCCR0A |= (1<<WGM01) | (1<<WGM00); // Set to 'Fast PWM' mode
TCCR0A |= (1<<COM0A1);                        // Clear OC0A output on compare match, upwards counting.

void pwm_write (int val)
OCR0A = val;

int main (void)
int adc_in;

DDRD |= (0b11111111); // LED is an output.


while (1) {
adc_in = adc_read(); // Get the ADC value
pwm_write(adc_in);  // Now write it to the PWM counter

Offline Lajon

  • Contributor
  • Posts: 31
  • Country: se
Re: ATmega328P C Code
« Reply #1 on: February 21, 2017, 09:02:57 pm »
Code: [Select]
TCCR0A |= (1<<CS01);                              // Set Timer 0 prescaler to clock/8.
TCCR0B would be better, that is where the clock select bits are.

« Last Edit: February 21, 2017, 09:04:57 pm by Lajon »

Offline HwAoRrDk

  • Frequent Contributor
  • **
  • Posts: 773
  • Country: gb
Re: ATmega328P C Code
« Reply #2 on: February 22, 2017, 05:34:19 am »
A couple of other comments about the code:

First, if you are running this on an actual Arduino Uno board, why are you declaring the CPU clock frequency as 1MHz? Unless you have changed the crystal, it should be 16MHz.

Code: [Select]
#define F_CPU 16000000UL
Second, you should not use a delay for a fixed period of time to wait for the ADC to finish. (And especially when you are incorrectly specifying F_CPU - _delay_ms() will be highly inaccurate then.) The ATmega328P datasheet says this about what happens when the conversion is finished:

A single conversion is started by ... writing a logical one to the ADC Start Conversion bit, ADSC. This bit stays high as long as the conversion is in progress and will be cleared by hardware when the conversion is completed.

So you should instead wait until the ADSC bit is zero, like so:

Code: [Select]
loop_until_bit_is_clear(ADCSRA, ADSC);

Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo