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

📄 main.c

📁 电话远程控制的想法已有一段是时间
💻 C
字号:
/*********************
	电话遥控开关测试程序
	文件名:main.c
	MCU   :ATMEGA8
	时 钟 : 外部4MHz
	
	芯艺 2005-01-21
*********************/

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <avr/delay.h>

#define uchar unsigned char
#define uint unsigned int

#define LIGHT_BIT 	PB1	//控制灯引脚位
#define LED_BIT		PC0	//发光管引脚位
#define TEL_BIT		PB2	//摘机控制引脚位

#define SET_LED	PORTC|=_BV(PC0)
#define CLR_LED PORTC&=~_BV(PC0)

#define OPEN_LIGHT	PORTB|=_BV(PB1)
#define CLOSE_LIGHT PORTB&=~_BV(PB1)

// C 调各音频码
const uchar g_aMusicTab[] ={0,238,225,220,200,189,179,168,159,150,142,134,126, \
							118,112,108,100,94,89,84,79,75,71,67,63, \
							59,56,53,50,47,44,42,39,37,35,33,31};

				
// "生日快乐" 曲码									
const uchar g_aMusic[] PROGMEM = { 20,02,00,01,20,01,22,04,20,04,25,04,24,04,00,04,
									20,02,00,01,20,01,22,04,20,04,27,04,25,04,00,04,
									20,02,00,01,20,01,32,04,29,04,25,04,24,04,22,04,
									30,02,00,01,30,01,29,04,25,04,27,04,25,04,00,04,
									20,02,00,01,20,01,22,04,20,04,25,04,24,04,00,04,
									20,02,00,01,20,01,22,04,20,04,27,04,25,04,00,04,
									20,02,00,01,20,01,32,04,29,04,25,04,24,04,22,04,
									30,02,00,01,30,01,29,04,25,04,27,04,25,04,00,04,
									00,00};
									
uchar g_flag=0;//判断是否有DTMF码接收到的全局标记

//误差不会太大的延时1ms函数  
void DelayMs(uint ms)
{
	uint i;

	for(i=0;i<ms;i++)
		_delay_loop_2(4 *250);
}

//外部中断0,MT8870接收到了一个DTMF码
SIGNAL(SIG_INTERRUPT0)
{
	uchar tmp;
	PORTB|=_BV(PB0); //TOE置位,MT8870数据输出允许
	tmp++;
	tmp=PIND;
	tmp>>=4;
	g_flag=tmp;
	PORTB&=~_BV(PB0);//TOE清零,MT8870数据输出禁止
}

//T/C2 比较匹配中断
SIGNAL(SIG_OUTPUT_COMPARE2)
{
	static uchar flag=0;
	if(flag)
		PORTC|=_BV(PC5);
	else
		PORTC&=~_BV(PC5);
		
	flag=!flag;
}

//检测一次振铃信号
//铃流信号通过硬件整形后在PD3口输入低电平
//无铃流信号时PD3保持高
void PassPlus(void)
{
	while(1)
	{
		if(PIND&_BV(PD3))
		{
			DelayMs(1);
			continue;
		}
		else
		{
			DelayMs(100);//延时消抖
			if((PIND&_BV(PD3))==0)
				break;
		}
	}

	while(1)
	{
		if((PIND&_BV(PD3))==0)
		{
			DelayMs(1);
			continue;
		}
		else
		{
			DelayMs(100);//延时消抖
			if((PIND&_BV(PD3)))
				break;				
		}
	}
}

//提示音输出函数,num 提示音响数,frq:提示音频率
void Beep(uchar num,uint frq)
{
	uchar i;
	TCCR2=_BV(WGM21)|_BV(CS21)|_BV(CS20); //CTC 模式  32分频
	OCR2=62500/frq;
	TIMSK=_BV(OCIE2);			//比较匹配中断允许
	
	for(i=0;i<num;i++)
	{
		DelayMs(500);
		cli();
		PORTC&=~_BV(PC5);
		DelayMs(500);
		sei();
	}
	
	TCCR2=0;
	TIMSK=0;
	PORTC&=~_BV(PC5);//关闭音乐信号
	sei();	
}

//结合T/C2中断程序 从PC5播放音乐,调用之前总中断必须允许
void PlayMusic(void)
{
	int i=0;
	uchar msc[2];
	
	TCCR2=_BV(WGM21)|_BV(CS21)|_BV(CS20); //CTC 模式  32分频
	OCR2=0XFF;
	TIMSK=_BV(OCIE2);			//比较匹配中断允许
	
	while(1)
	{
		msc[0]=pgm_read_byte(g_aMusic+i++);
		msc[1]=pgm_read_byte(g_aMusic+i++);
		if(msc[1]==0)
			break;
		
		//调整频率	
		cli();
		if(msc[0]==0)//如果是休止符
		{
			PORTC&=~_BV(PC5);
			DelayMs(187*msc[1]);
			continue;
		}
		TCNT2=0;
		OCR2=g_aMusicTab[msc[0]];
		sei();
		
		//按节拍延时
		DelayMs(187*msc[1]);
	}
	
	//关闭T/C2
	TCCR2=0;
	TIMSK=0;
	PORTC&=~_BV(PC5);//关闭音乐信号
	sei();
}

int main(void)
{
	uchar i;
	uint j;
	
	DelayMs(1000);
	
	PORTC=0;
	PORTB=0;
	PORTD=0;
	
	DDRD=0;
	DDRC=_BV(LED_BIT)|_BV(PC5);
	DDRB=_BV(LIGHT_BIT)|_BV(TEL_BIT)|_BV(PB0);//PB0为MT8870输出允许引脚

	MCUCR=_BV(ISC00)|_BV(ISC01);//INT0在MT8870 STD脚上升沿触发 
	GICR=_BV(INT0);				//外部中断0允许
	
	SET_LED;					//发光管亮
	
	while(1)
	{
		for(i=0;i<2;i++)
		{
			PassPlus();
		}
		PORTB=_BV(TEL_BIT);//摘机
		
		sei();//总中断允许
		Beep(3,1000);//摘机提示
		for(j=0;j<3000;j++)	//约半分钟无按键自动挂机
		{
			if(g_flag)	//有DTMF码收到
			{
				j=0;
				switch(g_flag)
				{
					case 8:	//'1'键
						PORTB|=_BV(LIGHT_BIT);//开灯
						Beep(2,500);
						break;
					case 4: //'2'键
						PORTB&=~_BV(LIGHT_BIT);//关灯
						Beep(2,1000);
						break;
					case 2: //'4'键
						PlayMusic();	//播放音乐
						DelayMs(1000);
						Beep(2,300);	//结束提示
						break;
					case 0x0c: //'3'键
						j=3000;		//退出挂机
						break;
					default:
						break;
				}
				g_flag=0;
			}
			//
			if(j%100==0)
			{
				if(PORTC&_BV(LED_BIT))
					CLR_LED;
				else
					SET_LED;
			}
			DelayMs(10);
		}
		
		SET_LED;
		PORTB&=~_BV(TEL_BIT);//挂机
		cli();
	}
}//main

⌨️ 快捷键说明

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