原创 FC-1脉冲发生器 程序 技术指标

2009-3-9 15:50 2953 2 3 分类: 测试测量

点击开大图点击开大图


点击开大图


点击开大图


 


 


//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

文章评论1条评论)

登录后参与讨论

用户1469954 2010-9-30 22:05

能给个原理图吗
相关推荐阅读
用户198065 2010-07-18 10:52
51 avr 下载板 最小系统 转接板
51 /AVR 双用最小系统 空板 DIY 提供转接板功能:(1)AT89S5X,stc89CXX系列最小系统板,烧写板      (2)ATMEGA8515/ATmega16/ATmega32最小系...
用户198065 2010-07-18 10:50
USB下载器
usb 下载器 空板提供制作方法,原理图,PCB,保证新手也能会制作自己的烧写器。  提供监控程序和制作方法,只要焊接没问题,100%可制作 选择我们精英电子团队的作品,就等于选择了专业,因为我们有自...
用户198065 2009-11-16 08:26
AVR mega48 电动车电子里程仪
      AVR mega48电动车电子里程仪规格功能说明:该电子里程仪有两种计量方式,所以,设计时需要预留两种测量接口,客户可以根据自己的需要使用任何一种测量方式。两种测量方式都需要完成如下功能:...
用户198065 2009-02-27 22:11
基于51单片机超声波测距器设计 倒车雷达
超声波倒车控制器的技术要求(暂定)1:在现有样品只能显示测试距离功能的基础上增加继电器用来控制电机断电(串励系统)或者启动它励(它励系统)同时有声光报警。数位显示可以保留作为选装件。2:控制器应在离障...
用户198065 2009-02-27 21:44
51 单片机 开发板 图片
    ...
我要评论
1
2
关闭 站长推荐上一条 /2 下一条