Fire alaram sound using PWM signal

How to send PWM signal during turn on time of Timer1

  • pwm,PIC,

    Votes: 0 0.0%
  • pwm,pic

    Votes: 0 0.0%

  • Total voters
    0

Thread Starter

ajitnayak87

Joined Dec 30, 2013
9
I am using PIC16F886 . I am trying to build fire alaram sound using PWM signal. Currently I could able to generate PWM signal for desired frequency,

I have used 2kHz with prescallar 16.Below code genrate 50% duty cycle,

Now using Timer1 Interrupt, In TOn time i need to pass PWM signal and TOFF pwm signal i like to make it zero. The code will keep repeating .
Can someone suggest how it can modfied.




#include <htc.h>
#include <stdio.h>
#include<pic.h>
#include<stdint.h>
#define _XTAL_FREQ 20000000
unsigned int i=0;
#define TMR2PRESCALE 16
long freq;
unsigned int x;
#define LED RC7
#define LED1 RC6
#define LED2 RC2
unsigned short int cnt, num,Dgt=0;
unsigned int i;
unsigned int j;

void out_p(int l , int k);
int PWM_Max_Duty()
{
return(_XTAL_FREQ/(freq*TMR2PRESCALE);
}
PWM1_Init(long fre)
{
PR2 = (_XTAL_FREQ/(freq*4*TMR2PRESCALE)) - 1;
freq = fre;
}

PWM1_Duty(unsigned int duty)
{
if(duty<1024)
{
duty = ((float)duty/1023)*PWM_Max_Duty();
CCP1X = duty & 2;
CCP1Y = duty & 1;
CCPR1L = duty>>2;
}
}

PWM1_Start()
{
CCP1M3 = 1;
CCP1M2 = 1;
#if TMR2PRESCALE == 1
T2CKPS0 = 0;
T2CKPS1 = 0;
#elif TMR2PRESCALE == 4
T2CKPS0 = 1;
T2CKPS1 = 0;
#elif TMR2PRESCALE == 16
T2CKPS0 = 1;
T2CKPS1 = 1;
#endif
TMR2ON = 1;
TRISC2 = 0;
}

PWM1_Stop()
{
CCP1M3 = 0;
CCP1M2 = 0;
}


void SetPWMDutyCycle(unsigned int DutyCycle) // Give a value in between 0 and 1024 for DutyCycle
{
CCPR1L = DutyCycle>>2; // Put MSB 8 bits in CCPR1L
CCP1CON &= 0xCF; // Make bit4 and 5 zero
CCP1CON |= (0x30&(DutyCycle<<4)); // Assign Last 2 LSBs to CCP1CON
}


void InitPWM(void)
{
TRISC2 = 0; // Make CCP1 pin as output
CCP1CON = 0x0C; // Configure CCP1 module in PWM mode
PR2 = 0xFF; // Configure the Timer2 period
T2CON = 0x01; // Set Prescaler to be 4, hence PWM frequency is set to 4.88KHz.
SetPWMDutyCycle(0); // Intialize the PWM to 0 duty cycle
T2CON |= 0x04; // Enable the Timer2, hence enable the PWM.
}


void Delay(int k)
{
for(j=0;j<k;j++);
}
void tone(int Frequency,int duration)
{
SetPWMDutyCycle(Frequency);
Delay(duration);

}


void Timer1_Interrupt()
{

INTCON = 0b00000000;
PIE1=0b00000001;
PIR1=0x01;
TMR1H=0x0B;
TMR1L=0xDC;
T1CON=0x31;
// T1CON=0x01;
}



void Init_Controller()
{
cnt=100;
TRISC=0b00000000;
PORTC=0b00000000;
TRISB=0b10000000;
PORTB = 0b00000000;
TRISA=0b00000000;
PORTA=0X00;
ADCON0 = 0b00000000;
ANSEL = 0b00000000;
Timer1_Interrupt();
LED=0;
LED1=0;
LED2=0;

}


void interrupt isr(void)
{
if(TMR1IF==1)
{
TMR1H=0xEA; // Load the time value(0x0BDC) for 100ms delay
TMR1L=0x60; //Timer1 Interrupt for 65000
TMR1IF=0; // Clear timer interrupt flag
Dgt++;

LED=!LED;
LED1=!LED1;


}

}

void main(void)
{
Init_Controller();
Timer1_Interrupt();
GIE=1;
PEIE=1;
TMR1IE=1;
PWM1_Init(5000);
PWM1_Start();

while(1)
{

PWM1_Duty(500);

}

}
 

geekoftheweek

Joined Oct 6, 2013
1,429
Are you trying to change frequencies at a given rate, trying to go between sound and no sound, or what exactly?

If you're always going to be at the same frequency the easiest way is to change the duty cycle to 0 for off and 50% for on... that way you don't have to set up the PWM every time.

What is the purpose of the tone function? I don't see it being called anywhere in your code. If it's meant to change the sound it won't work. You have to set both the PWM period and PWM duty cycle for every different sound you wish to create. The PWM frequency is the overall length of your wave, while the duty cycle is the length of the on time of the wave.

You can eliminate the PWM1_Duty(500) in your program loop since once you set this it will remain until you change it... move it to before the while().

Your code is a bit confusing. From what I can see the tone stays the same and the only change being made is if the led is on or off.

I would eliminate the checks for the timer pre-scale myself. Since you have it set to 16 it will probably need to stay there to be able to produce audible tones. (any less and you won't hear it anyways)

You also need to set TMR1IF to 0 before leaving the interrupt routine otherwise it will either keep repeating the interrupt or freeze altogether (it depends on the mood it's in)

You seem to have several global variables defined that are never used. I would suggest going back over you code, eliminate what you can, add some comments so we (and you) know what you're trying to accomplish really, and trying again. I think you're close to what you're after, but it's a touch confusing.
 
Top