|
发表于 2005-11-28 17:13:25
|
显示全部楼层
/*****************************************************
Project : phone
Version :
Date : 2005-11-26
Author :
Company :
Comments:
Chip type : ATmega16L
Program type : Application
Clock frequency : 8.000000 MHz
Memory model : Small
External SRAM size : 0
Data Stack size : 256
Description
DTMF generator
*****************************************************/
#include <mega16.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
// Function prototype
void init(void);
void delay(void);
void keypad_scan(void);
/************************** 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 i_CurSinValA = 0; // position freq. A in LUT (extended format)
unsigned int i_CurSinValB = 0; // position freq. B in LUT (extended format)
unsigned int i_TmpSinValA; // position freq. A in LUT (actual position)
unsigned int i_TmpSinValB; // position freq. B in LUT (actual position)
/****** Main *******/
void main (void)
{
init();
keypad_scan();
}
/******************************
Initialization
*******************************/
void init (void)
{
TIMSK = 0x04; // Timer1 溢出中断允许
TCCR1A = 0x81; // 正相8位PWM输出
TCCR1B = 0x01; // Timer1工作频率 = 系统时钟频率/1
DDRD = 0x20; // PD5 (OC1A) 用于输出信号
#asm("sei") // 全局中断使能
}
/*****************************
4*4 keypad scanner
******************************/
void keypad_scan(void)
{
unsigned char uc_Input;
unsigned char uc_Counter = 0;
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);
}
}
/********************************
Time delay to ensure a correct
setting of the pins of Port B
*********************************/
void delay (void)
{
int i;
for (i = 0; i < delaycyc; i++)
#asm("nop")
}
/**********************************************
Timer1 Overflow Interrupt Service Routine
***********************************************/
interrupt [TIM1_OVF] void ISR_T1_Overflow (void)
{
// move Pointer about step width aheaed
i_CurSinValA += x_SWa;
i_CurSinValB += x_SWb;
// normalize Temp-Pointer
i_TmpSinValA = (char)(((i_CurSinValA + 4) >> 3)&(0x007F));
i_TmpSinValB = (char)(((i_CurSinValB + 4) >> 3)&(0x007F));
// calculate PWM value: high frequency value + 3/4 low frequency value
OCR1A = (auc_SinParam[i_TmpSinValA] + (auc_SinParam[i_TmpSinValB] - (auc_SinParam[i_TmpSinValB] >> 2)));
} |
|