📄 main.c
字号:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include <avr/delay.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define relay_s PORTD|= 0x01 //继电器吸合, 接到外线
#define relay_c PORTD&=~0x01 //继电器释放, 内线互打
#define PH1_s PORTC|= 0x20 //接通#1
#define PH1_c PORTC&=~0x20 //断开#1
#define PH2_s PORTB|= 0x20 //接通#2
#define PH2_c PORTB&=~0x20 //断开#2
#define PH3_s PORTB|= 0x08 //接通#3
#define PH3_c PORTB&=~0x08 //断开#3
#define PH4_s PORTB|= 0x02 //接通#4
#define PH4_c PORTB&=~0x02 //断开#4
#define RG1_s PH1_c, PORTC|= 0x10 //振铃#1开
#define RG1_c PORTC&=~0x10, PH1_s //振铃#1关
#define RG2_s PH2_c, PORTB|= 0x10 //振铃#2开
#define RG2_c PORTB&=~0x10, PH2_s //振铃#2关
#define RG3_s PH3_c, PORTB|= 0x04 //振铃#3开
#define RG3_c PORTB&=~0x04, PH3_s //振铃#3关
#define RG4_s PH4_c, PORTB|= 0x01 //振铃#4开
#define RG4_c PORTB&=~0x01, PH4_s //振铃#4关
#define GATE 20 //听筒拿起通门槛电压( 50 为 0.125V)
#define L1_s PORTB|= 0x40 //L1 on
#define L1_c PORTB&=~0x40 //L1 off
#define L1_i PORTB^= 0x40 //L1 inver
#define L2_s PORTB|= 0x80 //L2 on
#define L2_c PORTB&=~0x80 //L2 off
#define CPU_CRYSTAL (8.00) //CPU Ck
#define dy(us)\
_delay_loop_2((uint)((us)*CPU_CRYSTAL/4))
volatile uchar adcou=240; //adc 转换计数器
volatile uint adadd=0; //adc 累加值
volatile uchar hu[4]={0,0,0,0}; //听筒合起标志
volatile uchar ringflag[4]={0,0,0,0}; //正在响铃标志
volatile uchar decode[10]={0}; //最近十次解码结果
volatile uchar lms=0; //LED点亮时间计数器
volatile uint ringtime=400; //响铃时间计数器, 当ringtime>400时,铃响, tingtime<=400时,铃不响
volatile uchar L_flash=0; //LED1闪烁标志, =1时闪烁
volatile uchar ringcou=0; //外线振铃计数器
volatile uint ringcoutime=0; //外线振铃时间计数器
volatile uchar out_ringflag=0; //外线振铃标志
void delay(uint t) //delay t mS
{
while(t--)
dy(980);
}
void s_ini(void)
{
OSCCAL= 0xBF;
PORTB = 0x2A;
DDRB = 0xff;
PORTC = 0x20;
DDRC = 0x30;
PORTD = 0x00;
DDRD = 0x01;
MCUCR = 0x0E; //INT1 raising edg cause intterupt, INT0 falling edg
GICR = 0xC0; //enable INT1,INT0
ADCSRA= 0xED; //enabel ADC, enable interrupt, ADCck=fck/128
ADMUX = 0xc0; //CH0
TCCR2 = 0x0f;
OCR2 = 77; //timer for 10mS
TIMSK = 0x80; //enable intterrupt
UCSRB = 0x00; //serial port setting
UCSRA = 0x00;
UCSRC = 0x80 | 0x06;
UBRRL = 51; //set baud rate lo baud rate=9600, fck=8.00MHz
UBRRH = 0x00; //set baud rate hi
UCSRB = 0x08; //enable to sent receive and 8 bits per bits//*/
sei();
}
SIGNAL(SIG_ADC) //adc interrupt
{
uint tmp;
if(((ringtime<395)&&(ringtime>375))||((ringtime<270)&&(ringtime>250))
||((ringtime<145)&&(ringtime>125)) || ((ringtime<20)&&(ringtime>0))) //铃响期间不进行摘机检测
{
adadd+=ADC; //
adcou--;
if(adcou==0) //完成ADC0,切换到ADC3
{
adcou=240;
ADMUX=0xC3;
if((adadd/50)>GATE) //取结果
hu[3]=1;
else
hu[3]=0;
}
else if(adcou==230) //开始记录ADC3
{
adadd=0;
}
else if(adcou==180) //完成ADC3,切换到ADC2
{
ADMUX=0xc2;
if((adadd/50)>GATE) //取结果
hu[0]=1;
else
hu[0]=0;
}
else if(adcou==170) //开始记录ADC2
{
adadd=0;
}
else if(adcou==120) //完成ADC2, 切换到ADC1
{
ADMUX=0xc1;
if((adadd/50)>GATE) //取结果
hu[1]=1;
else
hu[1]=0;
}
else if(adcou==110) //开始记录ADC1
{
adadd=0;
}
else if(adcou==60) //完成ADC1, 切换到ADC0
{
ADMUX=0xc0;
if((adadd/50)>GATE)
hu[2]=1;
else
hu[2]=0;
}
else if(adcou==50) //开始记录ADC0
{
adadd=0;
}
}
else
tmp=ADC;
}
SIGNAL(SIG_OUTPUT_COMPARE2) //time 2 compare interrupt for display 10mS
{
if(ringcoutime) //外线振铃计时器
{
ringcoutime--;
if(ringcoutime==0) //时间到
{
ringcou=0;
out_ringflag=0;
}
}
ringtime--;
if(ringtime==0)
{
ringtime=500;
}
if((ringtime==500)||(ringtime==440)) //内线振铃,响0.4S,停0.2S, 响0.4S 停4S
{
if(ringflag[0]) //查标志位,看是否需要响铃
RG1_s;
if(ringflag[1])
RG2_s;
if(ringflag[2])
RG3_s;
if(ringflag[3])
RG4_s;
}
else if((ringtime==460)||(ringtime==400)) //关闭所有振铃
{
if(ringflag[0]) //只有启动了的振铃才关,
RG1_c;
if(ringflag[1])
RG2_c;
if(ringflag[2])
RG3_c;
if(ringflag[3])
RG4_c;
}
if(out_ringflag) //外线振铃标志
{
if(ringtime==500) //#1响铃
{
RG1_s;
}
else if(ringtime==400) //#1关闭响铃
{
RG1_c;
}
else if(ringtime==375) //#2响铃
{
RG2_s;
}
else if(ringtime==275) //#2关闭响铃
{
RG2_c;
}
else if(ringtime==250) //#3响铃
{
RG3_s;
}
else if(ringtime==150) //#3关闭响铃
{
RG3_c;
}
else if(ringtime==125) //#4响铃
{
RG4_s;
}
else if(ringtime==25) //#4关闭响铃
{
RG4_c;
}
}
if(L_flash==0) //L2 flash 电源指示
{
if(ringtime%100==0)
L2_s;
else if(ringtime%100==80)
L2_c;
}
else if(L_flash==1) //LED flash fast
{
if((ringtime%15)==0)
L1_i;
}
else if(L_flash==2) //LED flash slow
{
if((ringtime%50)==0)
L1_i;
}
if(lms)
{
lms--;
if(lms==0)
L1_c; //time up turn off led
}
}
SIGNAL(SIG_INTERRUPT0) //外线振铃
{
if(ringcou<10)
ringcou++;
ringcoutime=500; //设定为5S
}
SIGNAL(SIG_INTERRUPT1) //DTMF decode sussess cause this interrup
{
uchar i;
lms=12; //turn on led for 120mS
L1_s;
for(i=9;i;i--) //保存最近十次解码结果
{
decode[i]=decode[i-1];
}
decode[0]=PIND>>4; //读解码结果
}
void clr_decode(void) //解码数组全部填0
{
uchar i;
for(i=0;i<10;i++)
decode[i]=0;
}
//检测哪个分机拿起了听筒, 但不检测num 号机,
uchar test_hu(uchar num) //若num为0则检查所有分机, 无返回0, 有返回分机号1-4
{
uchar i;
for(i=0;i<4;i++) //检测有没有分机拿起
{
if(hu[i]&&((i+1)!=num))
{
return(i+1);
}
}
return 0; //返回分机号
}
void lock(uchar num) //封锁除num外的分机, 分机号为0则不取消封锁
{
if(num==0) //取消封锁
{
PH1_s;
PH2_s;
PH3_s;
PH4_s;
}
else if(num==1) //封锁2,3,4
{
PH2_c;
PH3_c;
PH4_c;
}
else if(num==2) //封锁1,3,4
{
PH1_c;
PH3_c;
PH4_c;
}
else if(num==3) //封锁1,2,4
{
PH1_c;
PH2_c;
PH4_c;
}
else if(num==4) //封锁1,2,3
{
PH1_c;
PH2_c;
PH3_c;
}
}
int main(void)
{
uchar i;
uchar num=0; //num # 分机拿起
uchar num1=0;
uchar calln=0; //被叫机号
s_ini();
for(;;)
{
num=test_hu(0); //检查哪个分机拿起
if(num) //有分机拿起
{
L_flash=3;
L2_s;
lock(num); //封锁除num外的分机
// UDR=num;
while(num==test_hu(0)) //直到放下听筒
{
if((decode[1]==8)&&(decode[0]>0&&decode[0]<5
&&decode[0]!=num)) //拨号条件, 不能打自己
{
calln=decode[0]; //保存被叫机号
*(ringflag+(calln-1))=1; //响铃
L_flash=1; //LED闪烁
while((num==test_hu(calln))&&(calln != test_hu(num))) //等等被叫接电话或主叫放下听筒
{
}
*(ringflag+(calln-1))=0;//停止响铃
clr_decode(); //清除解码阵列
if(calln==test_hu(num)) //被叫接电话
{
L_flash=2; //LED慢速闪烁
while(test_hu(0)) //等待通话完毕
{ //在这里加入多方通话功能
}
L_flash=3;
L1_c;
}
if(num!=test_hu(calln)) //主叫放下电话
{
L_flash=3; //停止LED闪烁
L1_c;
}
clr_decode(); //清除解码阵列
}
if(decode[0]==9) //打外线条件
{
delay(100); //延时, 不让'9'拨出去
relay_s; // 接通外线
delay(100);
while(test_hu(0))//等待听筒放下
{ //在这里加入多方通话功能
if((decode[2]==11)&&(decode[1]==8)&&
(decode[0]>0&&decode[0]<5&&decode[0]!=num))//拨号条件, 不能打自己
{
calln=decode[0]; //保存被叫机号
*(ringflag+(calln-1))=1; //响铃
L_flash=1; //LED闪烁
while((num==test_hu(calln))&&(calln != test_hu(num))) //等等被叫接电话或主叫放下听筒
{
}
*(ringflag+(calln-1))=0;//停止响铃
if(calln==test_hu(num)) //被叫接电话
{
L_flash=2; //LED慢速闪烁
}
clr_decode(); //清除解码阵列
}
}
L1_c;
relay_c; //返回内线
clr_decode(); //清除解码阵列
}
}
L2_c;
L_flash=0;
lock(0); //解除封锁
}
else //没分机拿起
{
if(ringcou>5) //有外线电话
{
L1_s; //点亮L1
out_ringflag=1;
num1=0;
while(num1==0&&ringcou>5) //等等有人接电话
{
num1=test_hu(0); //等待num1接到了电话
}
L1_c;
if(num1) //有人接电话
{
L_flash=3;
L2_s;
out_ringflag=0; //清除标志
RG1_c;RG2_c;RG3_c;RG4_c; //取消所有响铃
lock(num1); //封锁其它机
relay_s; //接到外线,和对方通话
while(test_hu(0))//等待听筒放下
{ //在这里加入多方通话功能
if((decode[2]==11)&&(decode[1]==8)&&
(decode[0]>0&&decode[0]<5&&decode[0]!=num1))//拨号条件, 不能打自己
{
calln=decode[0]; //保存被叫机号
*(ringflag+(calln-1))=1; //响铃
L_flash=1; //LED闪烁
while((num1==test_hu(calln))&&(calln != test_hu(num1))) //等等被叫接电话或主叫放下听筒
{
}
*(ringflag+(calln-1))=0;//停止响铃
if(calln==test_hu(num1)) //被叫接电话
{
L_flash=2; //LED慢速闪烁
}
clr_decode(); //清除解码阵列
}
}
relay_c; // 返回内线
lock(0); //解除封锁
}
else //主叫放下听筒
{
out_ringflag=0; //清除标志
RG1_c;RG2_c;RG3_c;RG4_c; //取消所有响铃
}
ringcou=0;
ringcoutime=0;
L1_c;
L2_c;
L_flash=0; //LED flash
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -