TIFR & TIFR0 difference

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Hello to all :)
I am newbie in MC programming field.
And found interesting project here
http://blog.vinu.co.in/2012/05/i...
It is DFT spectrometer with LCD display. Code written for Atmega32.
I test this code, with compile by atmel studio 7, and paste .elf file in proteus project. Simulation works well.
But i don't have Atmega32, i have a Atmega328P, and i want to try run this code in Atmega328P.
I can't just switch MC in atmel studio 7 and compile the code, because Atmega328P don't have a TIFR register.
Reading datasheet for 328P, i found register with same (as TIFR) description and functionality (Timer InterruptFlag Register). It is TIFR0. The code can be compiled after changing TIFR to TIFR0, but changing leads to the fact that nothing works (it is possible to see in the simulation, zeros in all LCD display data variables).
Checking other bits in other registers give me nothing.
ADMUX set same basic voltage, alignment, and channel on this two MC.
ADCSRA set same frequency divisor (Clock/4)
CTC mode are same.
MC clocks are same.
What i am doing wrong, and where i do a mistake?

 

 

_________Other things, which i try, and got nothing_________
1. Setting bits in register correctly. Use ADCSRA = (1<<ADSC); instead of ADCSRA |= 1<<ADSC; and etc.
2. Change CLK8 Fuse in Proteus from 0 to 1, and conversely.
3. Just comment fragment with TIFR in code like a this
http://arduino.ru/forum/proekty/...
It gives falling spectrum at all frequencies. DFT dont work.

 

Code for Atmega 328P (i know about wrong LCD part of code, i fix this after fixing DHT part).
(And i attach .zip archive with atmel studio and proteus projects files.)

#include <avr/io.h>
#define F_CPU 16000000
#include <util/delay.h>
#define N 32
#include "lookup.h"

void adc_init();
uint16_t adc_read();
void TRANSFORM();
void timer1_init();

uint8_t lcd_buf1[16];
uint8_t lcd_buf2[16];
int32_t fx[N];
int32_t Fu[N/2][2];

void main()
{
	uint8_t mag;
	int i,j, temp_value;
	uint8_t temp_index;
	adc_init();
	//_delay_ms(5000);
	timer1_init();
	while(1) {
		TCNT1 = 0;
		TIFR0 |= 1<<OCF1A;
		for(i=0;i<N;i++) {
			while((TIFR0 & (1<<OCF1A)) == 0);
			fx[i] = ((int16_t)adc_read());
			TIFR0 |= 1<<OCF1A;
		}
		TRANSFORM();
		//lcd_cmd(0xc0);
		for(i =1; i<N/2; i++) {
			if(Fu[i][0]<0)Fu[i][0]*=-1;
			if(Fu[i][1]<0)Fu[i][1]*=-1;
			mag = (uint8_t)(Fu[i][0] + Fu[i][1])/4;
			if((mag)>7) {
				lcd_buf1[i] = (mag) - 7 - 1;
				if(lcd_buf1[i] > 7)
				lcd_buf1[i] = 7;
				lcd_buf2[i] = 7;
			}
			else {
				lcd_buf1[i] = ' ';
				lcd_buf2[i] = mag;
			}
		}

	}
}

void TRANSFORM()
{
	int16_t count,degree;
	uint8_t u,k;
	count = 0;
	for (u=0; u<N/2; u++) {
		for (k=0; k<N; k++) {
			degree = (uint16_t)pgm_read_byte_near(degree_lookup + count)*2;
			count++;
			Fu[u][0] +=  fx[k] * (int16_t)pgm_read_word_near(cos_lookup + degree);
			Fu[u][1] += -fx[k] * (int16_t)pgm_read_word_near(sin_lookup + degree);
		}
		Fu[u][0] /= N;
		Fu[u][0] /= 10000;
		Fu[u][1] /= N;
		Fu[u][1] /= 10000;
	}
}

void timer1_init()
{
	TCCR1B = (1<<WGM12)|(1<<CS10);
	OCR1A = 800;
}

void adc_init()
{
	ADMUX = 0b11000000;
	ADCSRA = 0b10000010;
}

uint16_t adc_read()
{
	volatile uint16_t retl,reth;
	ADCSRA |= (1<<ADSC);
	while ((ADCSRA & (1 << ADIF)) == 0);
	//while(!ADIF);
	//ADCSRA |= 1<<ADIF;
	retl = ADCL;
	reth = ADCH;
	reth<<=8;
	reth|=retl;
	return reth;
}

 

 

Last Edited: Sat. Mar 17, 2018 - 07:20 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Newbie12 wrote:
ADMUX set same basic voltage
Nope.

"Internal Reference" is selected for both, but the voltage of the internal reference is different for the two chips.

 

Newbie12 wrote:
And found interesting project here

... 

ADCSRA |= 1<<ADSC;
while(!ADIF);
ADCSRA |= 1<<ADIF;

#BadCodeOnTheInternet

 

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sternst

Very appreciated to you for answer.

sternst wrote:
"Internal Reference" is selected for both, but the voltage of the internal reference is different for the two chips.

Yes, i mean use the "Internal Reference" in code, it is 2.5v for atmega32, and 1.1v for 328P. Of course, i shift input voltage in proteus via changing "offset" value in generator options.

_____________

I was update adc read function (and clean first post from useless at this time LCD part). Code is still working on Atmega32, but nothing work on Atmega328P.

 

uint16_t adc_read()
{
    volatile uint16_t retl,reth;
    ADCSRA |= (1<<ADSC);
    while ((ADCSRA & (1 << ADIF)) == 0);
    //while(!ADIF);
    //ADCSRA |= 1<<ADIF;
    retl = ADCL;
    reth = ADCH;
    reth<<=8;
    reth|=retl;
    return reth;
}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

First place in proteus, where i can see trouble - it is fx[] array. All are same, except TIFR/TIFR0 changing.

Last Edited: Sat. Mar 17, 2018 - 07:44 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

The ATmega328P has multiple timers, hence the need for a digit to differentiate between.  One problem I see is you appear to be using TC1, but are setting the register for TC0:

 

	timer1_init();
	while(1) {
		TCNT1 = 0;
		TIFR0 |= 1<<OCF1A;
		for(i=0;i<N;i++) {
			while((TIFR0 & (1<<OCF1A)) == 0);
			fx[i] = ((int16_t)adc_read());
			TIFR0 |= 1<<OCF1A;
		}
.
.
.
.
.
void timer1_init()
{
    TCCR1B = (1<<WGM12)|(1<<CS10);
    OCR1A = 800;
}

 

Change TIFR0 to TIFR1.

 

Greg Muth

Portland, OR, US

Xplained/Pro/Mini Boards mostly

 

Make Xmega Great Again!

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Greg_Muth

Very appreciated to you for answer.

I added an array to the code ("S") in which you can see the signal spectrum, and changed TIFR0 to TIFR1.

The result appeared, but in a highly distorted form.

And i attach last version of changes (Atmel studio & Proteus project files).

Attachment(s):