//ICC-AVR application builder : 2008-6-29 16:23:43
// Target : M16
// Crystal: 10.0000Mhz
#include <iom16v.h>
#include <macros.h>
#include <eeprom.h>
#define uchar unsigned char
#define uint unsigned int
#define ulon unsigned long
unsigned char num[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,
0x6f,0x77,0x7c,0x39,0x5e,0x7b,0x71,0x00,0x40}; //0-f
unsigned char num_p[] = {0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; //0.-9.
uchar k_fuction=0;//加减标志
uint add_dec;//增减变量
uchar lu_shu=1;//路数变量
uchar f02_flag,f03_flag,f04_flag;//增加显示变量
uchar flag_jiange,jiange_begin;//开始,间隔标志
uchar time_start_end;//循环标志
uint start,end,jiange,lushu; //参数EEPROM保存
uint key,star_prior;//键盘数值
uchar light_flag=0;//定义小灯启动停止状态闪烁标志
uchar start_end_flag=0;//手动自动,待机切换
uchar count,count1;//小灯闪烁取反计数,//每隔6秒技术
uint time,count_01min;//开始0.1s时间,0.6s=0.1分时间到标志,
//延时1ms
void delay(uint ms)
{
uint i,j;
for(i=0;i<ms;i++)
{
for(j=0;j<1141;j++);
}
}
void port_init(void)//端口初始化,ad口做初始化为高电平输出口
{
PORTA = 0xff;
DDRA = 0xff;
PORTB = 0xff;
DDRB = 0xFF;
DDRC = 0x00;//输入口
DDRC|=BIT(2);//小灯指示口,仿真模式要取消,否则带不动
PORTC = 0xff;
PORTD = 0xff;
DDRD = 0xff;
}
//TIMER1 initialize - prescale:256//内部晶振不准确,采用外部10M晶振
// WGM: 0) Normal, TOP="0xFFFF"
// desired value: 10Hz
// actual value: 10.000Hz (0.0%)
void timer1_init(void)
{
TCCR1B = 0x00; //stop
TCNT1H = 0xC2; //setup
TCNT1L = 0xF7;
OCR1AH = 0x3D;
OCR1AL = 0x09;
OCR1BH = 0x3D;
OCR1BL = 0x09;
ICR1H = 0x3D;
ICR1L = 0x09;
TCCR1A = 0x00;
TCCR1B = 0x03; //start Timer
}
///定时器1中断,因为10hz进入一次中断,且考虑到脉冲准确性,做的比较大
#pragma interrupt_handler timer1_ovf_isr:iv_TIM1_OVF
void timer1_ovf_isr(void)
{
//TIMER1 has overflowed
TCNT1H = 0xC2; //setup
TCNT1L = 0xF7;
count++;
count1++;
time++;
if(count>=3)
{
count="0";
light_flag=~light_flag;
if(start_end_flag!=1)
{
if(light_flag)
PORTC&=~BIT(2);
else PORTC|=BIT(2);//利用定时器实现运行灯闪烁。
}//if
}//if count3
if(count1>=60)
{
count1=0;
count_01min++;
} //if count1
switch(time_start_end)
{
case 0x01://初始化定时器,准备发送
step1:
time=0;
if(lu_shu<=8)
PORTA&=~BIT(lu_shu-1);//第一路输出高电平
else
PORTD&=~BIT(lu_shu-9);//第一路输出高电平
time_start_end=02;//状态机
f02_flag=0;
break;
case 0x02:
if (time>=start)//查询脉冲高电平时间,并计时显示
{
PORTA="0Xff";//与设定时间比较,高电平时间到,初始化低电平计数
PORTD="0Xff";
time_start_end=0x03;
count_01min=0;count1=0;
if(f02_flag==0)
f02_flag=1;
} //end if
f03_flag=0;
break;
case 0x03: //低电平时间计数,计数时间到清零分技术标志
if(count_01min>=end)
{
if(f03_flag==0)
f03_flag=1;//第一次低电平时间结束,显示要显示结束数值,
if(lu_shu<lushu)//没有结束循环,则立马发送
{
lu_shu++;
goto step1;
}//if
else //间隔时间技术开始,清零所有的计数标志,开始计数
{
time_start_end=0X04;
count_01min=0;
count1=0;
lu_shu=0;
f04_flag=0;
}//else
}//if
break;
case 0x04:
if(count_01min>=jiange)//如果间隔计数数值到,则立马再次重新发送
{
if(f04_flag==0)
f04_flag=1;
lu_shu=1;
goto step1;
}
break;
default:break;
}//switch*/
} //end time interupt
////////////////////////////
//SPI initialize
// clock rate: 31250hz
void spi_init(void)
{
SPCR = 0x50; //setup SPI
SPSR = 0x01; //setup SPI
}
void spi_send(uchar dd)
{
SPDR="dd";
while(0==(SPSR&0X80));
SPSR&=0X7f;
WDR ();
}
//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
spi_init();
timer1_init();
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x04; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
//eeprom写
void eeprom_write(uchar address,ulon i )//eeprom write
{
EEPROM_WRITE(address,i);
WDR();
SEI();
}
//eeprom读
unsigned long eeprom_read(uchar address1)
{
unsigned long i;
EEPROM_READ(address1,i); //eepromread
WDR();
return i;
}
//根据key fuction数值读取相应的eeprom数据
uint eeprom_fuc_read(void)
{ uint value;
if(k_fuction==1)
value="eeprom"_read(0x10);
else if(k_fuction==2)
value="eeprom"_read(0x20);
else if(k_fuction==3)
value="eeprom"_read(0x30);
else if(k_fuction==4)
value="eeprom"_read(0x40);
else if(k_fuction==5)
value="eeprom"_read(0x50);
return value;
}
//根据key fuction数值读取相应的eeprom数据
void eeprom_fuc_write(ulon key1)
{
if(k_fuction==1)
eeprom_write(0x10,key1);
else if(k_fuction==2)
eeprom_write(0x20,key1);
else if(k_fuction==3)
eeprom_write(0x30,key1);
else if(k_fuction==4)
eeprom_write(0x40,key1);
else if(k_fuction==5)
eeprom_write(0x50,key1);
}
//数码管显示不带点函数
void show_led(uchar data,uchar wei)
{
switch (wei)
{
case 1: PORTB&=0Xf7;break;
case 2:PORTB&=0Xfb;break;
case 3:PORTB&=0Xfd;break;
case 4:PORTB&=0Xfe;break;
default:break;
}
PORTB&=~BIT(4);
PORTB|=BIT(4);
spi_send(num[data]);
delay(2);
PORTB|=0X0f;
PORTB&=~BIT(4);
PORTB|=BIT(4);
}
//数码管显示带点函数
void show_led_point(uchar data,uchar wei)
{
switch (wei)
{
case 1: PORTB&=0Xf7;break;
case 2:PORTB&=0Xfb;break;
case 3:PORTB&=0Xfd;break;
case 4:PORTB&=0Xfe;break;
default:break;
}
PORTB&=~BIT(4);
PORTB|=BIT(4);
spi_send(num_p[data]);
delay(2);
PORTB|=0X0f;
PORTB&=~BIT(4);
PORTB|=BIT(4);
}
//主功能中第一位闪烁
void light_1(uchar lu_date)
{
if(light_flag)
show_led(lu_date,4);
else
show_led(16,4);
}
void show_avr(void)
{
show_led(k_fuction,4);
show_led(16,3);
show_led(16,2);
show_led(16,1);
}
////////////////根据数据的位数,显示数码管的闪烁状态
void show_led_flash(void)
{
uchar i,j;
uint data;
if(light_flag==0)//定时器闪烁数据显示
{
if(k_fuction!=0)
show_avr();
}//if
else
{
data="key";
if(k_fuction!=0)//显示功能键数值,不显示0
{
show_led(k_fuction,4);
if(data>=100)//是否显示第三位
show_led(data/100,3);
if((k_fuction==4)|(k_fuction==5))//如果功能键第5次按下,不显示点
show_led((data%100/10),2);
else show_led_point((data%100/10),2);//其余功能键值第二位显示点
show_led(data%10,1);
}//if
}//else
}//end show
///////加减键检测
void key_add_dec(void)
{
uchar m,n;
if((PINC&0X80)!=0X80)
{
for(m=0;m<12;m++)
show_avr();//延时去抖动,并且显示路数
if((PINC&0X80)!=0X80)
key++;
if((k_fuction==4)|(k_fuction==5))//4,5功能键不能超过16
{
if(key>16)
key="0";
}
if(key>999) //功能键最大为999
key="0";//循环显示作为一个延时,防止按键加的过快
for(m=0;m<30;m++)
{
show_led(k_fuction,4);
if((key/100)!=0)//判断是否显示第三位
show_led(key/100,3);
if((k_fuction!=4)&(k_fuction!=5))//4,5功能不显示带点的,
show_led_point(key/10%10,2);
else
show_led(key/10%10,2);//其余第二位显示带点
show_led(key%10,1);
}//for
}// end if add
/////////////////////
if((PINC&0X01)!=0X01)//判断减按下
{
for(n=0;n<12;n++)//延时去抖动,并且显示路数
show_avr();
if((PINC&0X01)!=0X01)
{
if((k_fuction==4)|(k_fuction==5))
{
key--;
if(key==65535)
key="16";
}//if
else
{
key--;
if(key==65535)
key="999";
}//else
}//end if
/////////////////////
for(m=0;m<30;m++)//延时防止减的过快
{
show_led(k_fuction,4);
if((key/100)!=0)
show_led(key/100,3);
if((k_fuction!=4)&(k_fuction!=5))
show_led_point(key/10%10,2);//4,5功能键不显示带点
else
show_led(key/10%10,2);//其余功能键显示带点
show_led(key%10,1);
}//end for
}//end if dec
}//end key_add_dec
////////////功能键检测
void key_scan(void)
{
if((PINC&0X02)!=0X02)
{
delay(5);
if((PINC&0X02)!=0X02)
k_fuction++;
if(k_fuction>5)
k_fuction=0;
while((PINC&0X02)!=0X02);//等待按键抬起
}
}
////////////////////////启动停止键检测功能函数
void start_end(void)
{
if((k_fuction==0)|(k_fuction==5))//只有在0,5功能下才可以进入启动健
{
if((PINC&0X40)!=0X40)
{
delay(2);//延时去抖动
if((PINC&0X40)!=0X40)
{
while((PINC&0X40)!=0X40);//等待键抬起
start_end_flag++;//数据处理
time_start_end=0;//初始化数据,构成循环
TCCR1B = 0x03; //stop
} //if
}//if
}//if
}//end
/////////手动模式处理
void shou_dong(void)
{
while(k_fuction==5)//手动循环
{
TCCR1B = 0x00; //stop,不闪烁
if(start_end_flag!=1)
key_scan();//查询功能键是否按下,按下则k_fuction=0;跳出循环
if(k_fuction==0)//如果跳出循环则回复为待机状态
{start_end_flag=0;TCCR1B=0x03;}
else
{
if(start_end_flag==1)//启动输出高电平
{
PORTC&=~BIT(2);//置1工作,因加光耦,实际置0
if((key<=8)&&(key>=1))
PORTA&=~BIT(key-1);//第一路输出高电平
else if ((key>=8)&&(key<=16))
PORTD&=~BIT(key-9);//第一路输出高电平
}
start_end();//检测启动
/////////////////////////////////////////
if(start_end_flag==2)//停止,输出经光耦低电平
{
TCCR1B = 0x03; //启动定时器,闪烁状态,并可调按键
key_add_dec();//仅停止时候可以检测增加键
PORTA="0Xff";//与设定时间比较,停止
PORTD="0Xff";
}//if
///////////////////////////////////////
if(start_end_flag==3)//停止后又马上启动
start_end_flag=1;
/////////////////////////////////////
if(start_end_flag!=2)
{
show_led(key%10,1);
show_led(key/10,2);
show_led(16,3);
show_led(5,4);
}//end if
else
{
if(light_flag==0)//定时器闪烁数据显示
{
show_led(key%10,1);
show_led(key/10,2);
show_led(16,3);
show_led(5,4);
}//if
else
{
show_led(16,1);
show_led(16,2);
show_led(16,3);
show_led(5,4);
}//else
}//end if
}//else
}//while
}//shou_dong
///////////////////////////////
//待机状态下功能键盘处理函数
void key_function(void)
{
ulon i,j,k;
key_scan();
if(k_fuction!=0)//在待机状态,加减不起作用,其余功能键下,健起作用
key_add_dec();
switch (k_fuction)
{
case 0:k=k_fuction;
show_led(15,4);show_led(12,3);
show_led(17,2);show_led(1,1);break;
case 1:
if(k!=k_fuction)
{
key=start;k=k_fuction;
}
show_led_flash();break;
case 2:
if(k!=k_fuction)
{
eeprom_write(0x10,key);
start=key;
k=k_fuction;
key=end;
}
show_led_flash();break;
case 3:
if(k!=k_fuction)
{
eeprom_write(0x20,key);
end=key;
k=k_fuction;
key=jiange;
}
show_led_flash(); break;
case 4:
if(k!=k_fuction)
{
eeprom_write(0x30,key);
jiange=key;
k=k_fuction;
key=lushu;
}
show_led_flash(); break;
case 5:
if(k!=k_fuction)
{
eeprom_write(0x40,key);
lushu=key;
k=k_fuction;
key=0;
}
show_led_flash();
break;
default:break;
}
}//只有按键回复到待机状态和5状态可以存储,否则不能存储
void show_pulse(void) //自动运行时,显示状态
{ uchar q;
PORTC&=~BIT(2);//点亮灯指示运行
/////////////////////////////////////////
if(lu_shu==16)
lu_shu=17;
if(time_start_end==0x00)//第一次按键启动
{
time_start_end=0x01;time=0;
}//end if
//////////////////////////////////////////////////////
if(f03_flag==1)
{
for(q=80;q>0;q--)
{
show_led_point(end/10%10,2);
show_led(end%10,1);
if(end/100)//是否显示第3wei
show_led(end/100,3);
}//for
f03_flag=2;
}//if
////////////////////////
if(f04_flag==1)//如果间隔时间到,要显示完整间隔时间
{ for(q=80;q>0;q--)
{
show_led_point(jiange/10%10,2);
show_led(jiange%10,1);
if(jiange/100)//是否显示第3wei
show_led(jiange/100,3);
}
f04_flag=2;
}
///////////////////////////////////////////
if(time_start_end==0x02)//显示time高电平时间计数
{
light_1(lu_shu);//第一位数码管闪烁
show_led_point(time/10%10,2);
show_led(time%10,1);
if(time/100)//是否显示第3wei
show_led(time/100,3);
}//end if;
if(f02_flag==1)//如果正好在沿上,则要显示完整之后显示0
{
for(q=80;q>0;q--)
{
show_led_point(start/10%10,2);
show_led(start%10,1);
if(time/100)//是否显示第3wei
show_led(start/100,3);
}
f02_flag=2;
}
//////////////////////////////////////////
if(time_start_end==0x03)//显示低电平count_01min时间计数
{
light_1(lu_shu);//第一位数码管闪烁
if(count_01min/100)//是否显示第3wei
show_led(count_01min/100,3);
show_led_point(count_01min/10%10,2);
show_led(count_01min%10,1);
}
if(time_start_end==0x04)//显示间隔循环时间
{
light_1(lu_shu);//第一位数码管闪烁
if(count_01min/100)//是否显示第3wei
show_led(count_01min/100,3);
show_led_point(count_01min/10%10,2);
show_led(count_01min%10,1);
}//end if
}//end show_pulse
void main(void)
{ uchar i;
uint end1,jiange1,lushu1;
init_devices();
/*/////////////////////////////////////验证使用,已经生成EEPROM文件
eeprom_write(0x10,10);//写功能键1下初始化数值
eeprom_write(0x20,1);//写功能键2下初始化数值
eeprom_write(0x30,1);//写功能键3下初始化数值
eeprom_write(0x40,2);//写功能键4下初始化数值
eeprom_write(0x50,0);//写功能键4下初始化数值
///////////////////////////////////*/
start="eeprom"_read(0x10);
end="eeprom"_read(0x20);
jiange="eeprom"_read(0x30);
lushu="eeprom"_read(0x40);
while(1)
{
start_end(); //检测启动按键
if(start_end_flag==1) //启动 (下面进行手动自动选择)
{
if(k_fuction==0)
show_pulse(); //自动循环启动脉冲
else if(k_fuction==5) //手动启动1路脉冲函数
{shou_dong();
}
}
else if(start_end_flag==2)//停止脉冲过程,显示待机状态
{start_end_flag=0;lu_shu=1;}
else
key_function(); //start_end_flag=0;待机状态下调整参数函数*/
}//while(1)
}//main