| ??? 06/23/03 13:08 Read: times |
#49076 - RE: Rob Redding and Michael Karas Responding to: ???'s previous message |
I have re-written the code so that it is working (on timer2 of an 8052 at 24mhz...
its been tested using an R2R network on P1 fed into an opamp...the ouptut of which could be connected to your 600ohm transformer.
#include <reg52.h>
#include <stdio.h>
#include <stdlib.h>
#define SAMPLE_RATE 10000 //10 kHz sample rate
#define MAX_PHASE_ACCUM 0x10000 //16-bit phase accumulator overflow value
#define DURATION_100MS 1000 //100 ms tone duration
/* Enumeration to identify DTMF characters */
bit dtmf_done; // end of tone flag
enum DTMF_CHAR
{
DTMF_0, // digit 0
DTMF_1, // digit 1
DTMF_2, // digit 2
DTMF_3, // digit 3
DTMF_4, // digit 4
DTMF_5, // digit 5
DTMF_6, // digit 6
DTMF_7, // digit 7
DTMF_8, // digit 8
DTMF_9, // digit 9
DTMF_STAR, // char *
DTMF_POUND, // char #
DTMF_A, // char A
DTMF_B, // char B
DTMF_C, // char C
DTMF_D // char D
};
/* Table of sine waveform points. These are unsigned integers that vary */
/* around 128 and range as high as 255 and as low as 1. Values in this */
/* range are suitable for an 8-bit PWM register or unipolar DAC. For */
/* a bipolar DAC use signed values in whatever format works best. Bear */
/* in mind that you may need to average the two tones' sample values */
/* together to keep from overranging the DAC with the sum of both */
/* signals. */
/* The number of entries in this table corresponds to the number of */
/* bits of the phase accumulator used to index it. */
unsigned char code sine_table[] =
{
0x80, 0x83, 0x86, 0x89, 0x8C, 0x8F, 0x92, 0x95,
0x98, 0x9B, 0x9E, 0xA1, 0xA4, 0xA7, 0xAA, 0xAD,
0xB0, 0xB3, 0xB6, 0xB9, 0xBB, 0xBE, 0xC1, 0xC3,
0xC6, 0xC9, 0xCB, 0xCE, 0xD0, 0xD2, 0xD5, 0xD7,
0xD9, 0xDB, 0xDE, 0xE0, 0xE2, 0xE4, 0xE6, 0xE7,
0xE9, 0xEB, 0xEC, 0xEE, 0xF0, 0xF1, 0xF2, 0xF4,
0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFB,
0xFC, 0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xFD,
0xFC, 0xFB, 0xFB, 0xFA, 0xF9, 0xF8, 0xF7, 0xF6,
0xF5, 0xF4, 0xF2, 0xF1, 0xF0, 0xEE, 0xEC, 0xEB,
0xE9, 0xE7, 0xE6, 0xE4, 0xE2, 0xE0, 0xDE, 0xDB,
0xD9, 0xD7, 0xD5, 0xD2, 0xD0, 0xCE, 0xCB, 0xC9,
0xC6, 0xC3, 0xC1, 0xBE, 0xBB, 0xB9, 0xB6, 0xB3,
0xB0, 0xAD, 0xAA, 0xA7, 0xA4, 0xA1, 0x9E, 0x9B,
0x98, 0x95, 0x92, 0x8F, 0x8C, 0x89, 0x86, 0x83,
0x80, 0x7C, 0x79, 0x76, 0x73, 0x70, 0x6D, 0x6A,
0x67, 0x64, 0x61, 0x5E, 0x5B, 0x58, 0x55, 0x52,
0x4F, 0x4C, 0x49, 0x46, 0x44, 0x41, 0x3E, 0x3C,
0x39, 0x36, 0x34, 0x31, 0x2F, 0x2D, 0x2A, 0x28,
0x26, 0x24, 0x21, 0x1F, 0x1D, 0x1B, 0x19, 0x18,
0x16, 0x14, 0x13, 0x11, 0x0F, 0x0E, 0x0D, 0x0B,
0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x04,
0x03, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
0x03, 0x04, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
0x0A, 0x0B, 0x0D, 0x0E, 0x0F, 0x11, 0x13, 0x14,
0x16, 0x18, 0x19, 0x1B, 0x1D, 0x1F, 0x21, 0x24,
0x26, 0x28, 0x2A, 0x2D, 0x2F, 0x31, 0x34, 0x36,
0x39, 0x3C, 0x3E, 0x41, 0x44, 0x46, 0x49, 0x4C,
0x4F, 0x52, 0x55, 0x58, 0x5B, 0x5E, 0x61, 0x64,
0x67, 0x6A, 0x6D, 0x70, 0x73, 0x76, 0x79, 0x7C
};
/* Tone pairs that correspond to DTMF characters in enumeration above */
struct DTMF_FREQ
{
unsigned short low_tone;
unsigned short high_tone;
} idata dtmf_freq[] =
{
941, 1336, //digit 0
697, 1209, //digit 1
697, 1336, //digit 2
697, 1477, //digit 3
770, 1209, //digit 4
770, 1336, //digit 5
770, 1477, //digit 6
852, 1209, //digit 7
852, 1336, //digit 8
852, 1477, //digit 9
941, 1209, //char *
941, 1477, //char #
697, 1633, //char A
770, 1633, //char B
852, 1633, //char C
941, 1633 //char D
};
/* Structure containing phase accumulators and phase increment */
/* values for the desired tone pair. Once this structure is */
/* initialized for a given DTMF digit or character, it can be */
/* used to keep generating tones indefinitely. */
struct DTMF_TONE
{
unsigned short low_phase_accum; //low tone phase accumulator
unsigned short high_phase_accum; //high tone phase accumulator
unsigned short low_phase_incr; //low tone phase increment
unsigned short high_phase_incr; //high tone phase increment
unsigned short duration; //tone duration
} dtmf_tone;
/* Initialize DTMF tone structure with new character */
void
new_tone(enum DTMF_CHAR dtmf_char)
{
unsigned long temp_increment;
/* Zeroing phase accumulators makes both sine waves start at zero. */
/* If you want to transition smoothly from one tone to the next */
/* without the glitch caused by dropping to zero at the end of the */
/* previous tone, don't clear the phase accumulators. */
dtmf_tone.low_phase_accum = 0;
dtmf_tone.high_phase_accum = 0;
/* Calculate phase increments for low and high tones based on */
/* frequencies of each tone, phase accumulator size, and */
/* sample rate: */
/* phase increment = frequency * accumulator size / sample rate */
/* Use a long temporary because the max phase accumulator size */
/* is already 16 bits. */
temp_increment = dtmf_freq[dtmf_char].low_tone * MAX_PHASE_ACCUM;
dtmf_tone.low_phase_incr = temp_increment / SAMPLE_RATE;
temp_increment = dtmf_freq[dtmf_char].high_tone * MAX_PHASE_ACCUM;
dtmf_tone.high_phase_incr = temp_increment / SAMPLE_RATE;
}
/* Get the next sample of the combined tone signal for the most */
/* recent DTMF character. Ordinarily this would be executed in */
/* a 10 kHz periodic interrupt and the returned value would be */
/* written to a DAC. */
void
next_dtmf_sample(void)
{
unsigned short temp_sample; //for combining both tones' sample values
/* Advance the low tone phase accumulator */
dtmf_tone.low_phase_accum += dtmf_tone.low_phase_incr;
/* Look up the next sample of the sine wave using the upper 8 bits */
/* of the phase accumulator */
temp_sample = sine_table[dtmf_tone.low_phase_accum >> 8];
/* Now repeat the process for the high tone, adding the sample */
/* value to that for the low tone */
dtmf_tone.high_phase_accum += dtmf_tone.high_phase_incr;
temp_sample += sine_table[dtmf_tone.high_phase_accum >> 8];
/* Average the two sample values so it won't overrange an 8-bit DAC */
P1=(temp_sample / 2);
}
void
Timer2(void) interrupt 5 using 2 {
/* 10 kHz sample rate, timer2 interrupt 10k interval on 24mhz 12 clocker
Auto reload 65535 - 200 =65335 RCAP2H=0xff RCAP2L=0x37
This routine takes 43 cycles to complete ,so could be run at 1mips*/
TF2= 0; // Clear INTERRUPT FLAG
dtmf_tone.duration++;
/* Check if tone has been output for required duration */
if(dtmf_tone.duration>DURATION_100MS){
ET2= 0; //disable timer2 - tone ended.
TR2= 0;
dtmf_done=1;
P1=0x128;} // reset port for Pseudo zero output
/* Get the next sample of the combined tone signal */
next_dtmf_sample();
}
void
main(void)
{
/* setup timer hardware and interrupt */
RCAP2H=0xff;
RCAP2L=0x37;
EA = 1; // Enable all interrupts
/* Main Example Routine Loop */
do{
/* Send 1st tone */
dtmf_tone.duration=0;
dtmf_done=0;
new_tone(DTMF_1);
TH2=0xff; //Ensure clean first pass
TL2=0x37;
TR2 = 1;
ET2 = 1;// Enable Timer 2 interrupts
while(!dtmf_done); // wait for tone duration to end
/* Send 2nd tone */
dtmf_tone.duration=0;
dtmf_done=0;
new_tone(DTMF_2);
TH2=0xff; //Ensure clean first pass
TL2=0x37;
TR2 = 1;
ET2 = 1;// Enable Timer 2 interrupts
while(!dtmf_done); // wait for tone duration to end
}while(1);
}
|
| Topic | Author | Date |
| DTMF from 8052 pin | 01/01/70 00:00 | |
| RE: DTMF from 8052 pin | 01/01/70 00:00 | |
| RE: DTMF from 8052 pin | 01/01/70 00:00 | |
| RE: DTMF from 8052 pin | 01/01/70 00:00 | |
| RE:Rob Redding | 01/01/70 00:00 | |
| RE: RE:Rob Redding | 01/01/70 00:00 | |
| RE: Rob Redding and Michael Karas | 01/01/70 00:00 | |
| RE: Rob Redding and Michael Karas | 01/01/70 00:00 | |
| RE: Rob Redding and Michael Karas | 01/01/70 00:00 | |
| RE: Rob Redding and Michael Karas | 01/01/70 00:00 | |
| RE: Rob Redding and Michael Karas | 01/01/70 00:00 | |
| RE: Rob Redding and Michael Karas | 01/01/70 00:00 | |
| RE: RE:Rob Redding | 01/01/70 00:00 | |
| RE: DTMF generation from ADuc812 | 01/01/70 00:00 | |
| RE: DTMF generation from ADuc812 | 01/01/70 00:00 | |
RE: DTMF generation from ADuc812 | 01/01/70 00:00 |



