📄 dtmf.c
字号:
/********************************************************
键盘布置图:
1 2 3 A--PB4
4 5 6 B--PB5
7 8 9 C--PB6
* 0 # D--PB7
| | | |
P P P P
B B B B
0 1 2 3
喇叭接线图:PD5(OC1A)--1K电阻--喇叭
********************************************************/
#include <ioM8v.h>
#include <macros.h>
#define Xtal 8000000 // 系统时钟频率
#define prescaler 1 // T1预分频系数
#define N_samples 128 // 在查找表中的样本数
#define Fck Xtal/prescaler // T1工作频率
#define delaycyc 2 // 读取port C口延时循环数
#pragma interrupt_handler ISR_T1_Overflow:9
/*************************** 正弦表 *****************************
样本表: 一个周期分成128个点,每点按7位进行量化
****************************************************************/
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 *************************
// x_SW 表(8倍): x_SW = ROUND(8*N_samples*f*510/Fck)
//************************************************************
const unsigned char tab_sw[32]={
79,46,//1
87,46,//2
96,46,//3
79,50,//4
87,50,//5
96,50,//6
79,56,//7
87,56,//8
96,56,//9
79,61,//*
87,61,//0
96,61,//#
107,46,//a
107,50,//b
107,56,//c
107,61//d
};
//高频(列)
//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};
//const unsigned char auc_frequencyH [4] = {
//106,100,
//94,89};
//低频(行)
//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};
/*
//高频(列)
//1209hz ---> x_SW = 79
//1336hz ---> x_SW = 87
//1477hz ---> x_SW = 96
//1633hz ---> x_SW = 107
const unsigned char auc_frequencyH [4] = {
106,100,
94,89};
//低频(行)
//697hz ---> x_SW = 46
//770hz ---> x_SW = 50
//852hz ---> x_SW = 56
//941hz ---> x_SW = 61
const unsigned char auc_frequencyL [4] = {
60,57,
56,52};///55
*/
//************************** 全局变量 ****************************
unsigned char x_SWa = 0x00; // 高频信号脉冲宽度
unsigned char x_SWb = 0x00; // 低频信号脉冲宽度
unsigned int X_LUTaExt = 0;
unsigned int X_LUTbExt = 0;
unsigned int X_LUTa;
unsigned int X_LUTb;
unsigned char num=0;
unsigned int cnt=0;
/*****************************************************************
定时器溢出中断服务程序
******************************************************************/
void ISR_T1_Overflow (void)
{
if(cnt>0) {cnt--;}
x_SWa = tab_sw[num+num];//取高音脉冲宽度并结束循环
x_SWb = tab_sw[num+num+1];//取低音脉冲宽度并结束循环
X_LUTaExt += x_SWa;
X_LUTbExt += x_SWb;
// 数据规格化
X_LUTa = (char)(((X_LUTaExt+4) >> 3)&(0x007F));
X_LUTb = (char)(((X_LUTbExt+4) >> 3)&(0x007F));
// 计算 PWM 值: 高频值 + 3/4 低频值
OCR1A = (auc_SinParam[X_LUTa] + (auc_SinParam[X_LUTb]-(auc_SinParam[X_LUTb]>>2)));
//OCR1A = auc_SinParam[X_LUTa];
if(cnt==0) {OCR1A =0;PORTB&=0xfe;_CLI();}
}
/***********************************************************
初始化
***********************************************************/
void init (void)
{
MCUCR=0x00;
TIMSK = 0x04; // T1 溢出中断使能
TCCR1A = (1<<COM1A1)+(1<<WGM10); // 不翻转、8位PWM
TCCR1B = (1<<CS10); // 预分频系数为1、即CLK/1
DDRB = (1 <<PB1); // PD5 (OC1A)用作输出
_SEI(); // 全局中断使能
}
/*********************************************************************
为从PORT C口读取稳定的按键数据,所必须的延时程序(消抖延时)
*********************************************************************/
void Delay (void)
{
int i;
for (i = 0; i < delaycyc; i++) {_NOP();_NOP();_NOP();}
}
//////////////////////
void Delay_05s(void)
{ unsigned int sec0=0;
unsigned char sec1=0;
for(sec1=0;sec1<125;sec1++)
{
for(sec0=0;sec0<5000;sec0++)
{;}
}
}
//////////////////////
void dile(void)
{
num=0;start_PWM();//1
Delay_05s();
num=2;start_PWM();//3
Delay_05s();
num=6;start_PWM();//7
Delay_05s();
num=4;start_PWM();//5
Delay_05s();
num=10;start_PWM();//0
Delay_05s();
num=2;start_PWM();//3
Delay_05s();
num=2;start_PWM();//3
Delay_05s();
num=5;start_PWM();//6
Delay_05s();
num=1;start_PWM();//2
Delay_05s();
num=1;start_PWM();//2
Delay_05s();
num=2;start_PWM();//3
Delay_05s();
//num=4;start_PWM();
//Delay_05s();
}
//////////////////////
void start_PWM(void)
{
//cnt=60000;
cnt=1000;
x_SWa = 0x00; // 高频信号脉冲宽度
x_SWb = 0x00; // 低频信号脉冲宽度
X_LUTaExt = 0;
X_LUTbExt = 0;
_SEI();
}
/********************************************************************
主程序
从PORT C口读取按键数据(如:SL?AVR实验板) ,来确定产生哪个
高频(列)和低频(行)信号的混合信号,并且修正 x_SWa 和 x_SWb。
行 -> PINC 高四位
列 -> PINC 低四位
*********************************************************************/
void main (void)
{
unsigned char uc_Input,keycode,keybuff,keycnt,keytemp,is_key=0;
unsigned char uc_Counter = 0;
init();
DDRD = 0x00;
PORTD = 0xFF;
DDRC = 0xff;
while(1)
{
if((PIND&0X01)==0X00)
{
Delay();
Delay();
Delay();
Delay();
Delay();
if((PIND&0X01)==0X00)
{
Delay();
Delay();
Delay();
Delay();
Delay();
if((PIND&0X01)==0X00)
{
while((PIND&0X01)==0X00)
{;}
PORTC=0Xff;
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
dile();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
Delay_05s();
PORTC=0X00;
}
}
}
}
for(;;){
// 高四位 - 行
DDRD = 0x0F; // 高四位输入、低四位输出
PORTD = 0xF0; // 高四位打开上位、低四位输出低电平
//uc_Counter = 0;
Delay(); // 延时等待 Port C 电平稳定
keytemp=0;
uc_Input = PIND; // 读取 Port C
uc_Input &=0xf0;
if(uc_Input!=0xf0)
{
keytemp=uc_Input;
}
// 低四位 - 列
DDRD = 0xF0; // 高四位输出、低四位输入
PORTD = 0x0F; // 高四位输出低电平、低四位打开上拉
//uc_Counter = 0;
Delay(); // 延时等待 Port C 电平稳定
uc_Input = PIND; // 读取 Port C
uc_Input &=0x0f;
if(uc_Input!=0x0f)
{
keytemp|=uc_Input;
}
if((keytemp==keybuff)&&(keytemp!=0xff))
{
if(++keycnt>20)
{
//have key
keycode=keybuff;
is_key=1;
keycnt=0;
}
}
else
{
keycnt=0;
is_key=0;
}
keybuff=keytemp;
if((is_key==1)&&(cnt==0)){
switch(keycode){
case 0b11101110 : num=0;start_PWM(); break;
case 0b11101101 : num=1;start_PWM(); break;
case 0b11101011 : num=2;start_PWM(); break;
case 0b11011110 : num=3;start_PWM(); break;
case 0b11011101 : num=4;start_PWM(); break;
case 0b11011011 : num=5;start_PWM(); break;
case 0b10111110 : num=6;start_PWM(); break;
case 0b10111101 : num=7;start_PWM(); break;
case 0b10111011 : num=8;start_PWM(); break;
case 0b01111110 : num=9;start_PWM(); break;
case 0b01111101 : num=10;start_PWM(); break;
case 0b01111011 : num=11;start_PWM(); break;
case 0b11100111 : num=12;start_PWM(); break;
case 0b11010111 : num=13;start_PWM(); break;
case 0b10110111 : num=14;start_PWM(); break;
case 0b01110111 : num=15;start_PWM(); break;
default : break;
}
}///////////////////////
dile();
}//for(;;) ---end
}//main() ---end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -