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

📄 dtmfgenerator.c

📁 pic18的一个例子 希望对正在学PIC单片机的朋友有所帮助
💻 C
字号:
#include <p18cxxx.h>

//************************************************************
// 初始化CPU系统时钟为内部RC=8MHz,经过4倍频PLL,FOSC=32MHz
//************************************************************
void Initize_PIC18_OSCillator(void)
{
  OSCCON=0x70;//选择内部8MHz的主振荡器
  OSCTUNE=0x40;//使能4xPLL--->Fosc=32MHz	
}

//************************************************************
// 初始化使用到的I/O端口的方向与初始电平函数
//************************************************************
void Initize_PIC18_Port(void)
{
  ADCON1|=0x0F;//配置RA0..5,RE0..3全部为数字I/O口
  TRISE=0;//配置RE0..3口为输出方向
  LATE=0;//RE端口的输出电平全为0
  
  TRISD=0;//配置RD0..7口为输出方向
  LATD=0;//RD端口的输出电平全为0
  
  TRISCbits.TRISC1=0;//配置RC1端口为输出方向
  LATCbits.LATC1=0;//RC1口的输出电平为0
  
  INTCON2bits.RBPU=0;//启用RB端口的内部弱上拉功能
  TRISB=0xFF;//RB0..7口为输入方向
  PORTB=0xFF;//RB0..7的引脚电平全为高电平
}

//************************************************************
// 初始化TMR0为定时1mS,FOSC=32MHz,预分频为1:256
//************************************************************
void Initize_PIC18_TMR0(void)
{
  T0CONbits.TMR0ON=0;//TMR0停止工作
  T0CONbits.T08BIT=1;//选择8位的定时/计数器
  T0CONbits.T0CS=0;//选择内部CLKO时钟源作为定时
  T0CONbits.PSA=0;//选择预分频器                    T0CONbits.TMR0ON=0
  T0CONbits.T0PS2=1;//预分频比为1:256               T0CONbits.T0BIT=1
  T0CONbits.T0PS1=1;                             //   T0CONbits.T0CS=0
  T0CONbits.T0PS0=1;                             // T0CONbits.PSA=0    
  TMR0L=256-32;//装入定时1mS的初值                 T0CONbits.TOPS2=1;T0CONbits.T0PS1=1;T0CONbits.T0PS0=1
  T0CONbits.TMR0ON=1;//开始定时工作              T0CON=0x47;
}

//************************************************************
// 初始化TMR2,FOSC=32MHz
//************************************************************
void Initize_PIC18_TMR2(void)
{
  T2CON=0x00;//配置TMR2的预分频为1:1,后分频为1:1
  T2CONbits.TMR2ON=1;//启动TMR2开始工作
}

//************************************************************
// 初始化CCP模块为PWM模式,PWM周期为31.2KHz,FOSC=32MHz
//************************************************************
void Initize_PIC18_CCP(void)
{
  PR2=0xFF;//F=FOSC/((PR2+1)*4*N)=31.2KHz
  CCPR1L=0x00;//占空比为0
  CCP1CON=0x0F;//配置CCP模块工作于PWM模式
}

//************************************************************
// 初始化PIC18单片机的中断系统
//************************************************************
void Initize_PIC18_Interrupt(void)
{  
  INTCONbits.TMR0IF=0;//清TMR0溢出中断标志             INTCONbits.TMR0IF=0 INTCONbits.TMR0IE=1 INTCONbits.TMR0IP=0 外部中断寄存器
  INTCONbits.TMR0IE=1;//允许TMR0溢出中断响应
  INTCON2bits.TMR0IP=0;//设置TMR0为低中断优先级
  
  PIR1bits.TMR2IF=0;//清TMR2匹配中断标志              PIR1bits.TMR2IF=0 PIRbits.TMR2IE=1 IRP1bits.TMR2IP=1         外设中断寄存器
  PIE1bits.TMR2IE=1;//允许TMR2匹配中断响应
  IPR1bits.TMR2IP=1;//设置TMR2为高中断优先级
  
  RCONbits.IPEN=1;//允许中断嵌套                     RCONbits.IPEN=1 INTCONbits.GEIE=1 INTCONbits.PEIE =1 允许所有低优先级中断
  INTCONbits.GIE=1;//CPU开中断
  INTCONbits.PEIE=1;//CPU响应第二梯队中断
}

//************************************************************
// 高优先级中断和低优先级中断函数声明
//************************************************************
void PIC18F_High_isr (void);
void PIC18F_Low_isr (void);
#pragma code high_vector_section=0x08
void high_vector (void)
{
  _asm goto PIC18F_High_isr _endasm
}
#pragma code low_vector_section=0x18
void low_vector (void)
{
  _asm goto PIC18F_Low_isr _endasm
}
#pragma code


//************************************************************
// LED数码管显示代码定义及相关变量及缓冲区的定义
//************************************************************
const unsigned char LEDDATA[]=
{
  0x3F,0x06,0x5B,0x4F,	//0,1,2,3,
  0x66,0x6D,0x7D,0x07,	//4,5,6,7,
  0x7F,0x6F,0x77,0X7C,	//8,9,A,b,
  0x39,0x5E,0x79,0x71,	//C,d,E,F,
  0x00,0x40,	
};
unsigned char LEDBuffer[8];
unsigned char LEDScanPointer;
#define LED8PORT LATD
#define LEDBPORT LATE


//************************************************************
// 正弦波量化表定义,量化系数为128
//************************************************************
const 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 ,
};
//************************************************************
// 量化DTMF的高频群和低频群正弦信号的XSW步长
//************************************************************
const unsigned char auc_frequencyH[4]=
{
  107,96 ,
  87 ,79 ,
};
const unsigned char auc_frequencyL[4]=
{
  61 ,56 ,
  50 ,46 ,
};

//************************************************************
//  定义相关DTMF全局变量
//************************************************************
unsigned char x_SWa = 0x00;		//高频群步长变量
unsigned char x_SWb = 0x00;     //低频群步长变量
unsigned int  i_CurSinValA = 0; //
unsigned int  i_CurSinValB = 0; //
unsigned int  i_TmpSinValA;     //
unsigned int  i_TmpSinValB;     //


//************************************************************
//延时函数Delay()
//************************************************************
void Delay(unsigned int t)
{
  while(t--);	
}

//************************************************************
// 按键代码表
//************************************************************
//键盘0-9及A-F排列代码表
const unsigned char KEYCODE[]=
{
  0x7e,0xbe,0xde,0xee,//
  0x7d,0xbd,0xdd,0xed,
  0x7b,0xbb,0xdb,0xeb,
  0x77,0xb7,0xd7,0xe7,
};							 							 




//************************************************************
// 主程序入口main()函数
//************************************************************
void main(void)
{
  unsigned char KeyTemp;
  unsigned char Key;
  unsigned char i;
  
  Initize_PIC18_OSCillator();
  Initize_PIC18_Port();
  Initize_PIC18_TMR0();
  Initize_PIC18_TMR0();
  Initize_PIC18_TMR2();
  Initize_PIC18_CCP();
  Initize_PIC18_Interrupt();
  
  while(1)
    {
	  //****************************************************** 
      TRISB = 0x0F;//置PORTB的高4位为输出,低4位为输入
      PORTB = 0x0F;//PORTB的高4位输出全为0
  	  if((PORTB & 0x0F)!=0x0F)//判断是否有键按下
  	    {
    	  Delay(1000);//延时,消除按键抖动
    	  if((PORTB & 0x0F)!=0x0F)//再判断是否真得有键按下
    	    {
      	      KeyTemp=PORTB & 0x0F;//保存当前按键的状态
      	      Key=KeyTemp;//将当前列结果存储到变量
      	      i=0;
      	      //列的最低位是否为0,以及四个列全检查完毕
      	      while((Key & 0x01)&&(i<4))
      	        {
	      	      i++;//如果当前列不为低电平,指向中一列
	      	      Key>>=1;//右移一位
	      	    }
	      	  //找到之后读取该列低频群的步长给x_SWb变量
      	      if(i<4)x_SWb=auc_frequencyL[i];
      	        else x_SWb=0;
      		  TRISB = 0xF0;//置PORTB的高4位为输入,低4位为输出
              PORTB = 0xF0;//PORTB的低4位输出全为0
      		  Delay(1000);//延时,消除按键的抖动
      		  KeyTemp|=(PORTB & 0xF0);//读取当前按键的状态
      		  Key=KeyTemp;//将当前行结果存储到变量
      		  Key>>=4;//将行线内容移到低四位上
      		  i=0;
      		  //行的最低位是否为0,以及四个行全检查完毕
      		  while((Key & 0x01)&&(i<4))
      		    {
	      		  i++;//如果当前行不为低电平,指向中一行
	      		  Key>>=1;//右移一位    
	      		}
	      	  //找到之后读取该行高频群的步长给x_SWa变量
	      	  if(i<4)x_SWa=auc_frequencyH[i];
	      	    else x_SWa=0;
      		  Key=0;
      		  //将两次读取的按键状态与按键排列的代码表比较,
      		  //找到相匹配的按键数值
      		  while(KeyTemp!=KEYCODE[Key])Key++;
      		  //将LEDBuffer显示缓冲区的内容整体左移一个单元
	          for(i=sizeof(LEDBuffer)-1;i>0;i--)
	            LEDBuffer[i]=LEDBuffer[i-1];
	          //将最新按下的按键号码送到LEDBuffer[0]缓冲区单元
      		  LEDBuffer[0]=Key;
      		  while((PORTB & 0xF0)!=0xF0);//等待按键释放
    		}
    	}
      //****************************************************** 
	}
}




//************************************************************
// 高优先中断服务程序入口函数void PIC18F_High_isr(void)
//************************************************************
void PIC18F_High_isr(void)
{
  if(1==PIR1bits.TMR2IF)//TMR2与PR2的内容相匹配,产生TMR2溢出
    {
	  PIR1bits.TMR2IF=0;//清TMR2溢出中断标志位
      
      //根据所得的步长重新计算正弦取表指针
      i_CurSinValA+=x_SWa;
      i_CurSinValB+=x_SWb;
      //重新规格化临时取表指针
      i_TmpSinValA=(char)(((i_CurSinValA+4) >> 3)&(0x007F)); 
      i_TmpSinValB=(char)(((i_CurSinValB+4) >> 3)&(0x007F));
      //计算PWM的值:高频群值 + 3/4低频群值
      CCPR1L=(auc_SinParam[i_TmpSinValA]+ 
             (auc_SinParam[i_TmpSinValB]-
             (auc_SinParam[i_TmpSinValB]>>2)));	      
	}	
}

//************************************************************
// 低优先中断服务程序入口函数void PIC18F_Low_isr(void)
//************************************************************
void PIC18F_Low_isr(void)
{
  if(1==INTCONbits.TMR0IF)//TMR0定时1ms溢出了
    {
	  INTCONbits.TMR0IF=0;//清TMR0溢出中断标志位
	  TMR0L=256-32;//重新装入初值
	  
	  //根据扫描指针对应的显示缓冲区的内容的显示代码送到PD端口
	  LED8PORT=LEDDATA[LEDBuffer[LEDScanPointer]];
	  //将当前扫描指针送到RE端口由HC138进行译码选通当前的LED数码管
	  LEDBPORT=LEDScanPointer;
	  LEDScanPointer++;//扫描指针加1
	  //如果显示缓冲区的内容全部送完,则清扫描指针重新开始新的扫描
	  if(sizeof(LEDBuffer)==LEDScanPointer)LEDScanPointer=0;
	}
}

⌨️ 快捷键说明

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