⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dtmf.c

📁 指南描述了一组用于SPI协议软件实现的低级程序
💻 C
字号:
//***************************************************************************
//* A P P L I C A T I O N   N O T E   F O R   T H E   A V R   F A M I L Y
//*
//* Number               : AVR314
//* File Name            : "dtmf.c"
//* Title                : DTMF Generator
//* Date                 : 00.06.27
//* Version              : 1.0
//* Target MCU           : Any AVR with SRAM, 8 I/O pins and PWM 
//*
//* DESCRIPTION
//* This Application note describes how to generate DTMF tones using a single
//* 8 bit PWM output.
//*
//***************************************************************************

#include <stdio.h>
#define __IAR_SYSTEMS_ASM__   
#include <io4414.h>
#include "ina90.h"

#define  Xtal       8000000          // system clock frequency
#define  prescaler  1                // timer1 prescaler
#define  N_samples  128              // Number of samples in lookup table
#define  Fck        Xtal/prescaler   // Timer1 working frequency
#define  delaycyc   10               // port B setup delay cycles

//************************** SIN TABLE *************************************
// Samples table : one period sampled on 128 samples and
// quantized on 7 bit
//**************************************************************************
flash unsigned char auc_SinParam [128] = {
64,67,
70,73,
76,79,
82,85,
88,91,
94,96,
99,102,
104,106,
109,111,
113,115,
117,118,
120,121,
123,124,
125,126,
126,127,
127,127,
127,127,
127,127,
126,126,
125,124,
123,121,
120,118,
117,115,
113,111,
109,106,
104,102,
99,96,
94,91,
88,85,
82,79,
76,73,
70,67,
64,60,
57,54,
51,48,
45,42,
39,36,
33,31,
28,25,
23,21,
18,16,
14,12,
10,9,
7,6,
4,3,
2,1,
1,0,
0,0,
0,0,
0,0,
1,1,
2,3,
4,6,
7,9,
10,12,
14,16,
18,21,
23,25,
28,31,
33,36,
39,42,
45,48,
51,54,
57,60};

//***************************  x_SW  ***************************************
//Table of x_SW (excess 8): x_SW = ROUND(8*N_samples*f*510/Fck)
//**************************************************************************

//high frequency (coloun)
//1209hz  ---> x_SW = 79
//1336hz  ---> x_SW = 87
//1477hz  ---> x_SW = 96
//1633hz  ---> x_SW = 107

const unsigned char auc_frequencyH [4] = {
107,96,
87,79};

//low frequency (row)
//697hz  ---> x_SW = 46
//770hz  ---> x_SW = 50
//852hz  ---> x_SW = 56
//941hz  ---> x_SW = 61

const unsigned char auc_frequencyL [4] = {
61,56,
50,46};


//**************************  global variables  ****************************
unsigned char x_SWa = 0x00;               // step width of high frequency
unsigned char x_SWb = 0x00;               // step width of low frequency
unsigned int  X_LUTaExt = 0;           	  // position freq. A in LUT (extended format)
unsigned int  X_LUTbExt = 0;              // position freq. B in LUT (extended format)
unsigned int  X_LUTa;                     // position freq. A in LUT (actual position)
unsigned int  X_LUTb;                     // position freq. B in LUT (actual position)

//**************************************************************************
// Timer overflow interrupt service routine
//**************************************************************************
void interrupt [TIMER1_OVF1_vect] ISR_T1_Overflow (void)
{ 
  // move Pointer about step width aheaed
  X_LUTaExt += x_SWa;       
  X_LUTbExt += x_SWb;
  // normalize Temp-Pointer
  X_LUTa  =  (char)(((X_LUTaExt+4) >> 3)&(0x007F)); 
  X_LUTb  =  (char)(((X_LUTbExt+4) >> 3)&(0x007F));
  // calculate PWM value: high frequency value + 3/4 low frequency value
  OCR1A = (auc_SinParam[X_LUTa] + (auc_SinParam[X_LUTb]-(auc_SinParam[X_LUTb]>>2)));
}

//**************************************************************************
// Initialization
//**************************************************************************
void init (void)
{
  TIMSK  = 0x80;                     // Int T1 Overflow enabled
  TCCR1A = (1<<COM1A1)+(1<<PWM10);   // non inverting / 8Bit PWM
  TCCR1B = (1<<CS10);                // CLK/1
  DDRD   = (1 << PD5);               // PD5 (OC1A) as output
  _SEI();                     	     // Interrupts enabled
}

//**************************************************************************
// Time delay to ensure a correct setting of the pins of Port B 
//**************************************************************************
void Delay (void)
{
  int i;
  for (i = 0; i < delaycyc; i++) _NOP();
}

//**************************************************************************
// MAIN
// Read from portB (eg: using evaluation board switch) which
// tone to generate, extract mixing high frequency
// (column) and low frequency (row), and then
// fix x_SWa and x_SWb
// row    -> PINB high nibble
// column -> PINB low nibble
//**************************************************************************

void main (void)
{
  unsigned char uc_Input;
  unsigned char uc_Counter = 0;
  init();
  for(;;){ 
    // high nibble - rows
    DDRB  = 0x0F;                     // high nibble input / low nibble output
    PORTB = 0xF0;                     // high nibble pull up / low nibble low value
    uc_Counter = 0;
    Delay();                          // wait for Port B lines to be set up correctly
    uc_Input = PINB;                  // read Port B
    do 
    {
      if(!(uc_Input & 0x80))          // check if MSB is low
      {
                                      // if yes get step width and end loop
        x_SWb = auc_frequencyL[uc_Counter];  
        uc_Counter = 4;
      }
      else
      {
        x_SWb = 0;                    // no frequency modulation needed
      }
      uc_Counter++;
      uc_Input = uc_Input << 1;       // shift Bits one left
    } while ((uc_Counter < 4));
 
    // low nibble - columns
    DDRB  = 0xF0;                     // high nibble output / low nibble input
    PORTB = 0x0F;                     // high nibble low value / low nibble pull up
    uc_Counter = 0;
    Delay();                          // wait for Port B lines to be set up correctly
    uc_Input = PINB;
    uc_Input = uc_Input << 4;     
    do 
    {
      if(!(uc_Input & 0x80))          // check if MSB is low
      {
                                      // if yes get delay and end loop
        x_SWa = auc_frequencyH[uc_Counter];
        uc_Counter = 4;
      }
      else 
      {
        x_SWa = 0;                 
      }
      uc_Counter++;
      uc_Input = uc_Input << 1;
    } while (uc_Counter < 4);
  } 
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -