Beep tone for p18f4520 microcontroller using for loop

I am using C programming to program a beep tone for a P18F4520 microcontroller. I am using a for loop and delays for this. I haven't learned any other way to do this, and furthermore, I need to use a for loop and a delay to generate an audio tone for the target board. Speaker port is in RA4 position. This is what I have done so far.

#include <p18f4520.h>
#include <delays.h>
void tone (float, int);
void main()
{
ADCON1 = 0x0F;
TRISA = 0b11101111;

/*tone(38.17, 262); //C (1)
tone(34.01, 294); //D (2)
tone(30.3, 330); //E (3)
tone(28.57, 350); //F (4)
tone(25.51, 392); //G (5)
tone(24.04, 416); //G^(6)
tone(20.41, 490); //B (7)
tone(11.36, 880); //A (8)*/

tone(11.36, 880); //A (8)

}
void tone(float n, int cycles)
{
unsigned int i;
for(i=0; i<cycles; i++)
        {
            PORTAbits.RA4 = 0;
            Delay10TCYx(n);
            PORTAbits.RA4 = 1;
            Delay10TCYx(n);
        }
}

      

So, as you can see what I did, I created a tone function where n is for the delay and loops for the number of loops in the for loop. I'm not sure if my calculations are correct, but so far this is what I have done and it is causing the tone. I'm just not sure if it is really tone A or G etc. What I calculate is that firstly, I recognize the frequency tone, for example, the tone has a frequency of 440 Hz. Then I will find a period for it in which it will be 1/440 Hz. Then for the duty cycle, I would like the tone to be heard for only half of them, which is 50%, so I will divide the period by 2 which is (1/440 Hz) / 2 = 0.001136 or 1.136ms. Then I calculated the 1 cycle delay for a 4 * microcontroller (1 / 2MHz), which is 2 μs. So this means that in 1 cycle it will be delayed by 2 μs, this ratio will be 2 μs: 1 cycle.So to get the number of cycles for 1.136ms, this would be 1.136ms: 1.136ms / 2μs, which is 568 cycles. Currently in this part I have asked what should be in n, where n is in Delay10TCYx (n). What I got is just multiply 10 by 11.36, and for tone A, that would be Delay10TCYx (11.36). In terms of loops, I would like to delay by 1 second so 1 / 1.136ms, which is 880. That is why in my method for tone A this is tone (11.36, 880). It generates a tone and I found a range of tones, but I'm not sure if they really are tones. CDEFGG ^ B A.and for tone A this will be Delay10TCYx (11.36). In terms of loops, I would like to delay by 1 second so 1 / 1.136ms, which is 880. That is why in my method for tone A this is tone (11.36, 880). It generates a tone, and I found a range of tones, but I'm not sure if they really are tones. CDEFGG ^ B A.and for tone A this will be Delay10TCYx (11.36). In terms of loops, I would like to delay by 1 second so 1 / 1.136ms, which is 880. That is why in my method for tone A this is tone (11.36, 880). It generates a tone, and I found a range of tones, but I'm not sure if they really are tones. CDEFGG ^ B A.

So my questions are 1. How can I calculate the delay and frequency for tone A? 2.for the state of the for loop for loops, the number of loops, but from the answer I get from question 1, how many loops should I use to change the time period for tone A? More cycles will be a longer period of tone A? If so, how do you know how long? 3. When I use a function to reproduce a tone, it somehow generates a different tone than when I used the for loop directly in the main method. Why is this so? 4. Finally, if I want to stop the code, how do I do it? I've tried using a for loop but it doesn't work.

A simple explanation would be great as I'm just a student working on a project to create tones using a for loop and delays. I was looking for another place where people use different things like WAV or similar things, but I just would like to know how to use a for loop and delay for audio tones.

Your help would be greatly appreciated.

+3


source to share


2 answers


How do I calculate the number of delay cycles to obtain a 440 Hz tone? I will assume that your clock speed is 1/2 MHz or 500 kHz as written in your question.

1) A clock frequency of 500 kHz corresponds to a tick every 2 times. Since the cycle is 4 ticks, the cycle is 8 seconds long.

2) 440 Hz corresponds to a period of 2.27 ms, or 2270% or 283 cycles.

3) The delay is called twice in a period, so the delays should be around 141 cycles for A.

About your tone function ... When you compile your code, you should encounter some kind of warning, something like warning: (42) implicit conversion of float to integer

... The prototype of the delay function is void Delay10TCYx(unsigned char);

: it expects an unsigned char, not a float. You won't get floating point precision. You can try something like:

void tone(unsigned char n, unsigned int cycles)
{
  unsigned int i;
  for(i=0; i<cycles; i++)
    {
        PORTAbits.RA4 = 0;
        Delay1TCYx(n);
        PORTAbits.RA4 = 1;
        Delay1TCYx(n);
    }
}

      



I have changed for Delay1TCYx()

accuracy. Now A 1 second A-tone will be on tone(141,440)

. 1 second 880 Hz tone will be tone(70,880)

.

There is always while(1)

- all examples about PIC ... if you only need one beep at startup, do something like:

void main()
{
  ADCON1 = 0x0F;
  TRISA = 0b11101111;

  tone(141,440);
  tone(70,880);
  tone(141,440);

  while(1){

  }
}

      

As for changing the tone when inline in a function, keep in mind that each operation takes at least one cycle. The function call can take several cycles. Perhaps an announcement static inline void tone (unsigned char, int)

would be nice ...

However, as @Dogbert signaled, using delays.h

is a good start for newbies, but no getting used to it! Microcontrollers have many features to avoid counting and save time for useful calculations.

  • timers: think of this as an alarm clock. 18f4520 has 4 of them.
  • interrupt: The PIC stops the current operation, executes the code specified for this interrupt, clears the flag, and returns to its previous task. The timer may cause an interrupt.
  • PWM pulse wave modulation. There are 2 of them in 18f4520. Basically, it generates your signal!
+2


source


First, you need to understand the general approach to how you generate an interrupt at an arbitrary time interval. This lets you know that you can perform a specific action every x

microseconds, [1-2].

There are already projects that reproduce a specific tone (in Hz) on a PIC, like what you are trying to do [3-4].

Then you will want to take an alternative approach to tone generation. In the case of your functions, delay

you are effectively using the CPU for nothing when something else can be done. You would be better off using timer interrupts directly so that you do not "burn the CPU idle".



Once you have done this, you simply need to know the appropriate frequency for the note you are trying to generate, either using a formula to generate a frequency from a specific musical note [5] or using a lookup table [6].

+3


source







All Articles