View previous topic :: View next topic |
Author |
Message |
swapnil
Joined: 15 Dec 2016 Posts: 13 Location: delhi
|
generation of 1 kilohertz siren tone using timer 1 |
Posted: Fri Jan 06, 2023 12:59 pm |
|
|
hi
I want to generate 600 Hz to 700 Hz siren tone using timer 1 in 12f675 mcu, please help.
I generated by delay function but tone is not exactly what i want. _________________ heroswap1981 |
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 480 Location: Montenegro
|
|
Posted: Fri Jan 06, 2023 6:46 pm |
|
|
Post some code and do tell what is wrong with the tone. |
|
|
swapnil
Joined: 15 Dec 2016 Posts: 13 Location: delhi
|
generation of 1 kilohertz siren tone using timer 1 |
Posted: Fri Jan 06, 2023 10:38 pm |
|
|
PrinceNai wrote: | Post some code and do tell what is wrong with the tone. |
Code: | #include <12f675.h>
#fuses INTRC_IO,NOWDT,NOMCLR,PROTECT
#use delay(internal=4000000)
#define TONE_PIN PIN_A0
#define RELAY_PIN PIN_A1
void timer1_isr(void)
{
clear_interrupt(INT_TIMER1);
set_timer1(3036);
output_toggle(PIN_A1);
set_timer1(4036);
output_high(TONE_PIN);
}
//Global Variables:
int16 n; //counting var
void siren(void);
// Main Function
void main(void) {
{ setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_8 ); // Internal clock and prescaler 8
set_timer1(3036); // Preload value
clear_interrupt(INT_TIMER1); // Clear Timer1 interrupt flag bit
enable_interrupts(INT_TIMER1); // Enable Timer1 interrupt
enable_interrupts(GLOBAL); // Enable global interrupts
output_toggle(PIN_A1);
}
output_low(TONE_PIN);
while(TRUE)
{
siren(); timer1_isr();
}
}
//Beep 1: //Short single beep
void siren(void) {
//first beep 50% duty:
for(n=0; n<550; n++) {
output_high(TONE_PIN);
delay_us(750);
output_low(TONE_PIN);
delay_us(750);
}
for(n=0; n<350; n++) {
output_high(TONE_PIN);
delay_us(550);
output_low(TONE_PIN);
delay_us(550);
}
//second beep 10% duty:
for(n=0; n<300; n++) {
output_high(TONE_PIN);
delay_us(400);
output_low(TONE_PIN);
delay_us(400);
}
return;
}
|
In this code, tone is generated by delay but i want by Timer1 function so the frequency can be output from .6 KHz to .7 KHz. Simultaneously the width amplitude should change. _________________ heroswap1981 |
|
|
PrinceNai
Joined: 31 Oct 2016 Posts: 480 Location: Montenegro
|
|
Posted: Sat Jan 07, 2023 7:36 am |
|
|
Quote: |
while(TRUE)
{
siren(); timer1_isr();
}
|
You should never call timer1 interrupt routine. It happens by itself when timer1 overflows, that is the point of an interrupt.
How long do you want each tone to last? |
|
|
swapnil
Joined: 15 Dec 2016 Posts: 13 Location: delhi
|
Re: generation of 1 kilohertz siren tone using timer 1 |
Posted: Sat Jan 07, 2023 8:01 am |
|
|
swapnil wrote: | PrinceNai wrote: | Post some code and do tell what is wrong with the tone. |
Code: | #include <12f675.h>
#fuses INTRC_IO,NOWDT,NOMCLR,PROTECT
#use delay(internal=4000000)
#define TONE_PIN PIN_A0
#define RELAY_PIN PIN_A1
void timer1_isr(void)
{
clear_interrupt(INT_TIMER1);
set_timer1(3036);
output_toggle(PIN_A1);
set_timer1(4036);
output_high(TONE_PIN);
}
//Global Variables:
int16 n; //counting var
void siren(void);
// Main Function
void main(void) {
{ setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_8 ); // Internal clock and prescaler 8
set_timer1(3036); // Preload value
clear_interrupt(INT_TIMER1); // Clear Timer1 interrupt flag bit
enable_interrupts(INT_TIMER1); // Enable Timer1 interrupt
enable_interrupts(GLOBAL); // Enable global interrupts
output_toggle(PIN_A1);
}
output_low(TONE_PIN);
while(TRUE)
{
siren(); timer1_isr();
}
}
//Beep 1: //Short single beep
void siren(void) {
//first beep 50% duty:
for(n=0; n<550; n++) {
output_high(TONE_PIN);
delay_us(750);
output_low(TONE_PIN);
delay_us(750);
}
for(n=0; n<350; n++) {
output_high(TONE_PIN);
delay_us(550);
output_low(TONE_PIN);
delay_us(550);
}
//second beep 10% duty:
for(n=0; n<300; n++) {
output_high(TONE_PIN);
delay_us(400);
output_low(TONE_PIN);
delay_us(400);
}
return;
}
|
In this code, tone is generated by delay but i want by Timer1 function so the frequency can be output from .6 KHz to .7 KHz. Simultaneously the width amplitude should change. |
there is only one tone ,timer1 i have used to toggle a relay which will on/off at 1 hz for flasher(lamp) to be connected.
im my code tone is generated by delay function but i want by timer 1
frequency can be output from .6 KHz to .7 KHz. Simultaneously the width amplitude should change. _________________ heroswap1981 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19540
|
|
Posted: Sat Jan 07, 2023 8:36 am |
|
|
First comment, honestly use a different chip.
If you use for example the 12F1822 or the 1840, these both have PWM
modules. Can develop a tone with almost no software overhead at all.
Also will support different duty cycles simply.
Simple, reliable etc. etc...
Now, to do this with this chip, there will be a significant cost in terms of
software, and it will result in delay functions running slightly slow as the
chip spends some of it's time servicing the interrupt.
You do have to use an interrupt for this, since the timer does not itself
support toggling a pin. What you will have to do is run the timer at
the 'half period' interval, and toggle the pin each time this expires. So:
Code: |
include <12f675.h>
#fuses INTRC_IO,NOWDT,NOMCLR,PROTECT
#use delay(internal=4000000)
#define INTERVAL (125000/2000) //count for a 2000Hz interrupt
#define RELOAD (65536-INTERVAL)
//This is the reload needed for the interrupt at 2000Hz to give a 1KHz
//tone. The timer counts up from the reload and wraps at 65536.
//The timer is fed by 4MHz/(4*8)
#define TONE_PIN PIN_A0
#define RELAY_PIN PIN_A1
void timer1_isr(void)
{
set_timer1(RELOAD);
output_toggle(TONE_PIN);
}
void siren(void);
// Main Function
void main(void) {
setup_timer_1 ( T1_INTERNAL | T1_DIV_BY_8 );
// Internal clock and prescaler 8
set_timer1(RELOAD); // Preload value
clear_interrupt(INT_TIMER1); // Clear Timer1 interrupt flag bit
enable_interrupts(INT_TIMER1); // Enable Timer1 interrupt
enable_interrupts(GLOBAL); // Enable global interrupts
while(TRUE)
{
siren();
}
}
//Beep 1: //Short single beep
void siren(void)
{
output_high(RELAY_PIN); //assume this turns the relay on
delay_ms(1000); //one second
output_low(RELAY_PIN); //and off for one second.
delay_ms(1000);
}
|
That should give you a 50% duty cycle 1KHz tone, for one second, then
relay off for one second, and keep repeating.
As posted, the delays will be about 10% long because of the time spent
in the interrupt handling the tone.
Now if you want to change the duty cycle, you would have to change the
reload value used in alternate calls to the interrupt.
If the timer interrupt is giving you 1000Hz, you can't use this for the
flash as well. If you want timer1 to handle this flash function, then use
timer0 for the tone. Does it really have to be 1KHz?. If you could accept
976Hz, this is easy with timer0, using an /2 prescaler, since it will then
interrupt every 1/1953 second without using any reload. However this
will not then give duty cycle control. |
|
|
|