Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Sa re ga ma notes for avr microcontrollers

Status
Not open for further replies.

bhattaroshan

Member level 1
Joined
Sep 28, 2010
Messages
33
Helped
3
Reputation
6
Reaction score
3
Trophy points
1,288
Activity points
1,531
Hello friends i have made simple codes for generating sound from avr microcontroller.


#include<avr\io.h>
#include<avr\delay.h>
#include<avr\interrupt.h>

uint16_t FREQ_CNT=0;
uint16_t FF_CNT =0;

static volatile uint16_t freq_pb0=20; // initial value of frequency (any value..)

uint16_t note[]={300,337,378,401,451,506,569,603}; // array of frequency that we are
// going to generate
uint16_t j=0;

int main()
{
DDRB=0xff;
PORTB=0x00;
TCCR0=(1<<CS00); //prescalar 1 i.e. F_CPU (8MHZ) in our case
TIMSK=(1<<TOIE0); //enable timer0 overflow interrupt

sei(); //enable global interrupt
while(1); // never ending loop
}


ISR(TIMER0_OVF_vect)
{
FREQ_CNT++;

if(FREQ_CNT>=31250) // FREQ_CNT count 31250 in one second
{
FREQ_CNT=0; // reset FREQ_CNT to 0
FF_CNT=1;

freq_pb0=note[j]; //changing the value of frequency in each second
// that means each note will be played for 1 second

j++; // increase the counter value by one

if(j>7) j=0; // if last note is being played then again start from begining

}

if(FREQ_CNT>=(FF_CNT*(15625/freq_pb0))) // for generating frequency
{ // just flipflop every time we
// enter inside this condition
FF_CNT++;
if(PORTB&(1<<PB0))
{
PORTB&=~(1<<PB0);
}
else
{
PORTB|=(1<<PB0); // so we are getting output from PB0
}
}

}

Everything is working fine except when i first give power supply to microcontroller the sound coming from the microcontroller is 20hz i.e.
the initial value assigned to freq_pb0 for 1 second.
I couldnot understand why this is happening.. friends please help me with
this??????

MICROCONTROLLER i am using is ATMEGA8 with 8Mhz clock frequency for above code.
 
Last edited:

Maybe because the initial value is 20 static volatile uint16_t freq_pb0=20; so the first counter cycle uses that value.
If you want people to read you code you should comment your code, indent it properly and use a C code syntax highlighter.

Alex
 
hello friends i have other question to ask, for the code like above and any other code whenever i try to change the value of variable from main loop that is used in timer interrupt is never changed in timer interrupt. For example in above code:

while(1)
{
_delay_ms(1000);
freq_pb0+=50;
}

but the value of freq_pb0 is never increased. It is always 20 which is the initial value of freq_pb0. But if i increase its value from interrupt function then it gets increased. Friends, what is the problem with the code.Is something going wrong with my concept or that is not possible in case of interrupt.
 

freq_pb0+=50; is fine and should work but in the above code you are doing too many things inside the interrupt and this is not the proper way to write your code, from what you say there is something wrong and you never exit the interrupt.
The code inside the interrupt function should be as fast as possible, usually this can be done with a flag variable which is read in the main loop and does what you want, you should do minimal things like set or read a value or change an output when you netd immediate action etc.
While you are in the interrupt no other interrupt can be called (unless you enable recursive isr), also any delay routine stops and in general you may create lock ups that the code can't get out of.

Alex
 

thanks for your reply Alex....

But,there are no any loops inside overflow interrupt. on top of that, we are getting desired frequencies as output this means interrupt function must exit at required time. Due to this reason, i changed the value of freq_pb0 in interrupt function because while i change the value in main loop it is never changing. Same problem had arise when i coded for multiplexed seven segment display. So, i have done everything inside interrupt function rather than on main function which made the interrupt functions perform larger operation.
Alex, as you said previously i have commented in my code and code is not that much long i would be thankful if you would check on my code and see if you can find any mistake or errors in my code. I think i have misunderstood something may be about interrupts or...... So please help me.

thank you...
 

Can you please tell me the avr mcu you have used.
About the code that wasn't working correctly, was it the same as the original but with
_delay_ms(1000);
freq_pb0+=50;
in the main while loop?
I would like to try with the debugger.

Alex
 

i have used atmega8L with clock frequency 8mhz. yes, i had done the same as mentioned and no changes in that variable from main loop.
 

The first thing I tried was to remove the delay and it worked.
Then I tried with a smaller delay of 1ms and the increment is executed every 158ms , this means that with the original 1000ms delay the value will be incremented every 158 sec.
The cause of this is that you do everything in the interrupt and while you are in the interrupt the delay function stops, this is why I said that the code inside the interrupt should be minimal.

Alex

---------- Post added at 02:14 ---------- Previous post was at 01:59 ----------

You are using your timer at the clock speed (8MHz) and then you count 31250 interrupts, have you tried instead to use a slower timer and count less interrupts?

Alex
 

Actually I think there is a better solution for what you are trying to do, you can use compare match of timer 1 and enable output toggle and interrupt on match.
Then the only thing you need to do is clear the timer counter inside the interrupt (on match) and to load the new match register value when you want a different frequency.
You don't have to toggle pins or count interrupts.
As an additional bonus you can use two intendant channels because timer1 has two compare match registers.

Alex
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top