最新日志

发表于:2008-8-28 20:27:16
标签:示波器  

1

我的毕业设计--存储示波器

整个系统采用FPGA Cyclone 2C5芯片,在内嵌NIOS II,进行算法的处理,和显示采用320*240液晶进行显示。整个电路还包括前端信号处理部分,AD器件采用TLC5510,整个系统在程序上采用实时显示,和插值显示。

插值部分采用正统插值,由于整个系统在触发信号,做得不是很好,有点延时,所以在正统插值上,显示出来的波形不是很好看(只有在正弦信号时,显示的波形会好点,方波信号插值显示出来就很丑了)。插值算法采用查表的方法,曾经试过用计算的方法,这样计算量太大,整个系统显示一次波形要花很多时间。

   由于个人能力有限,整个系统做得很粗糙,只能用来学习用用。跟现在的数字示波器相比,功能太过简单了。

    这个系统的设计,从开始到完成,想想也花了两个多月时间了,虽然中间有停过一段时间。但是设计这样一个系统也是对自己一个考验吧。

    经过实践证明,发现国内的一些论文,像插值算法,没有经过真正系统实践过,太过理想化。那些算法是可以的,我也试过用一个正弦波数组进行插值,仿真出来的波形是很漂亮,只要用5个点就可以了。但是真正用到一个系统时,就会出现很多问题。

     在写液晶驱动上也花了好多时间,由于FPGA是3。3V供电,整个液晶工作得不是很理想,在写寄存器有点小BUG,一下子找不出原因。

    在电平匹配上要注意下,这个可以认真看下手册。工作后,花了一天的时间用心看了下手册,发现里面对IO的说明讲得很详细,如何让IO口匹配5v电平。代码暂不公开,整个程序写得比较乱。后面调试时改动很多。

点击看大图 

点击此处查看原文 >>

系统分类: ARM   |    用户分类:    |    来源: 原创

评论(0) | 阅读(78)
发表于:2008-3-15 12:12:51
标签:密码锁  

0

基于FPGA的密码锁

采用4X4键盘电路,和一个四位动显示电路.来完成基本的控制功能 .
1.4X4 键盘扫描电路的设计
电路中分为键盘去抖电路和键盘译码电路。弹跳消除电路所使用的频率必须比其它电路的
工作频率高,扫描电路的工作频率为24HZ左,则去抖电路的工作频率是前者的4倍,或者更高,
为128HZ左右。在此次电路设计中去抖动电路频率为250HZ,键盘扫描频率为25HZ。
2.四位动态数码管显示电路
电路中扫描频率为250HZ,其中每段数码管的频率不得低于42HZ,否则会出现频闪现象。
3.FPGA 控制电路。
电路中设计中,分为数字键,和功能键,当按下四位数字键时,按下激活电锁键,则这四位
数字键将作为该密码的当前密码。只有在按下正确密码时,并按下功能键清除/解除电锁键,
时,密码被激活。解锁。

pdf

点击此处查看原文 >>

系统分类: 汽车电子   |    用户分类:    |    来源: 原创

评论(0) | 阅读(427)
发表于:2008-3-13 18:43:49
标签:简易电压源  

0

简易电压源

/*****************************************************
This program was produced by the
CodeWizardAVR V1.24.8c Professional
Automatic Program Generator
?Copyright 1998-2006 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project : 简易直流电压源
Version :
Date    : 2007-5-18
Author  : F4CG                           
Company : F4CG                           
Comments:


Chip type           : ATmega16L
Program type        : Application
Clock frequency     : 8.000000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 256
*****************************************************/

#include <mega16.h>
#include <delay.h>
#include "1602a.h"
#define ADC_VREF_TYPE 0xc7//内部基准电源,单通道输入PA7
unsigned int adc_v; 

int key_stime_ok,key_stime_counter;
void adc_to_disbuffer(unsigned int adc)
{
 // #asm("cli")
  
 //  LcdPos(6,0); //确定光标位置
  // LcdWd(adc%10+0x30);
   adc="adc/10";
   LcdPos(5,0); //确定光标位置
   LcdWd(adc%10+0x30);
   adc/=10;
     LcdPos(4,0); //确定光标位置
   LcdWd(adc%10+0x30);
   adc/=10; 
    LcdPos(3,0); //确定光标位置
   LcdWd('.');
     LcdPos(2,0); //确定光标位置
   LcdWd(adc%10+0x30);
   adc/=10;
//#asm("sei")
}   
interrupt [TIM0_COMP] void timer0_comp_isr(void)
{
// Place your code here   

if (++key_stime_counter >=1)
  { 
  key_stime_ok = 1; 
                  }
}
// ADC interrupt service routine
interrupt [ADC_INT] void adc_isr(void)
{
  unsigned int adc_data;
// Read the AD conversion result
adc_data=ADCW;

// Place your code here
adc_v=(unsigned long)adc_data*2560/1024;    //换算成电压值
  adc_to_disbuffer(adc_v);  
   
}

// Declare your global variables here

void main(void)
{
// Declare your local variables here
//char j="88";
// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0xff;//液晶接口
DDRB=0xff;

// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0xff;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0xff;     
DDRD=0xff;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top="FFh"
// OC0 output: Disconnected
TCCR0=0x0C;//采用比较模式,256分频   8M/256=31.25K
//TCCR0=0X0D;//1024   7.81k
TCNT0=0x00;
OCR0=0x40;// (61+1)/31.25   =2ms
 // OCR0=0XFF;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top="FFFFh"
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top="FFh"
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x02;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// ADC initialization
// ADC Clock frequency: 125.000 kHz
// ADC Voltage Reference: Int., cap. on AREF
// ADC Auto Trigger Source: Timer0 Compare Match
ADMUX=ADC_VREF_TYPE;
ADCSRA=0xAE;
SFIOR&=0x1F;
SFIOR|=0x60;

// Global enable interrupts

RstLcd();//液晶初始化
RstLcd();//液晶初始化
RstLcd();//液晶初始化
/*
LcdPos(0,0);//x,y
LcdWd(j%10+0x30);  
LcdPos(1,0);//x,y
j=j/10;
LcdWd(j%10+0x30);
//j=j/10 ;
LcdPos(2,0);//x,y
LcdWd('=');
LcdPos(3,0);
//Write_String(str);
lcd_putsf("JIANGLONGJIAN");
//LcdWd('b');*/
  LcdPos(0,0); //确定光标位置
  LcdWd('v');
  LcdPos(1,0); //确定光标位置
  LcdWd('=');
  #asm("sei")
while (1)
      {
      // Place your code here
   //   if (key_stime_ok==1)
    // { key_stime_ok=0;
     //  adc_to_disbuffer(adc_v);
      // } 
 
      };
}
c

点击此处查看原文 >>

系统分类: 汽车电子   |    用户分类:    |    来源: 原创

评论(0) | 阅读(446)
发表于:2008-3-13 18:41:33
标签:1302  

0

基于1302的万年历

这个是1302程序,液晶用12864来显示

rar

点击此处查看原文 >>

系统分类: 汽车电子   |    用户分类:    |    来源: 原创

评论(0) | 阅读(514)
发表于:2008-3-13 18:38:38
标签:模拟SPI接口  

0

模拟SPI接口程序

//***********************************************************
//功能      : 由AVR作为主机,向FPGA发送数据,采用模拟SPI接口来实现
//            互相通信 
//作者      : 小白龙
//创建日期  : 2007.8.1 
//版本      :  V1.1
//修改日期  :2007.8.12
//************************************************************
#define clk_r       PORTD.0  //所有IO口初始时设为输出口
#define data_r      PORTD.1
#define ss_r        PORTD.2

#define clk_s       PORTD.3
#define ss_s        PORTD.4
#define data_s      PORTD.5
#define data_sPIN   PIND.5
#define data_sDDR   DDRD.5 
#define IO_PIN      PIND
#define IO_DDR      DDRD.1  //数据读入口
 uchar spiread(void);
void spisend(uchar data);


/**********************************************************
*
*功能:模拟SPI接口程序,低位先发送,最后发送高位,
      FPGA接收数据往左移动,即先接收高位 ,二者顺序发送和接收数据相反
*说明:在CLK的上升沿开始写入数据,开始时SS位片选信号,
      当SS由高变低时,产生时钟信号,开始传送
*********************************************************/
void spisend(uchar data)//写入
{  
    uchar i;
    data_sDDR=1;
    clk_s=0;
    for(i=8;i>0;i--)
 {
  if ((data&0x01)==1)
   {
   data_s=1;
   }
  else
   data_s=0;
   delay_1us();
  clk_s=1;
 // delay_1us();
  clk_s=0;  
  data>>=1;//右移一位
 }
}
/**********************************************************
*
*名称:spiread()
*功能:AVR作为主机,由AVR提供时仲,从FPGA取数据
*说明:在CLK的下降沿开始读数据,FPGA的数据从高位开始发送,
      AVR中接收的数据先送到低位中
*********************************************************/
uchar spiread(void)
{
 uchar i;
 uchar data="0x00";
 uchar temp; 
 IO_DDR=0;  //IO口作为输入,DDR要写0 
 ss_r=0;
 clk_r=0;  
 for(i=0;i<8;i++)
 {   
  clk_r=1;
  clk_r=0;     
  temp="IO"_PIN;
        if (temp&0x02)       //下降沿采集数据,调换则会出错
 data|=(0x01<<i);
 
 }
 IO_DDR=1;
 ss_r=1;  //读完数据后,SS拉高,同时时钟拉高一次,上升沿重新置数
 clk_r=1;
return(data);
}

// 
//
// PORTA="0x00";   //灯指示
// DDRA="0XFF";
//
// PORTB="0x00";//0101 0000
// DDRB="0x07";//0000 0111接口作为模拟SPI口输出接口要写1
//
// PORTC="0x00";
// DDRC="0x80";
//
// DDRD="0xff";//0000 0001
// PORTD="0x00";//0100 1000
//         // SPUL="1",CL=1;
//
// // Timer/Counter 0 initialization
// TCCR0=0x0b;//采用比较模式,256分频   8M/256=31.25K
// TCNT0=0x00;
// OCR0=0x3D;// (61+1)/31.25   =2ms
//
// // Timer/Counter 1 initialization
// TCCR1A=0x00;
// TCCR1B=0x00;
// TCNT1H=0x00;
// TCNT1L=0x00;
// ICR1H=0x00;
// ICR1L=0x00;
// OCR1AH=0x00;
// OCR1AL=0x00;
// OCR1BH=0x00;
// OCR1BL=0x00;
//
// // Timer/Counter 2 initialization
// ASSR="0x00";
// TCCR2=0x00;
// TCNT2=0x00;
// OCR2=0x00;
//
// // External Interrupt(s) initialization
// GICR|=0x40;
// MCUCR="0x03";
// MCUCSR="0x00";
// GIFR="0x40";     //通过写1来清0
// // Timer(s)/Counter(s) Interrupt(s) initialization
// TIMSK="0x02";
//
// // Analog Comparator initialization
// ACSR="0x80";
// SFIOR="0x00";
// ss_r=1;
// //PORTB.1=1;
// key_init(); //键盘初始化
// #asm("sei")   // 开放全局中断
//  
// while (1)
//       {
      // Place your code here
//***********************键盘处理*******************************//
//       
// if (key_stime_ok)    10ms到,键处理
//           {
//      key_stime_ok = 0;
//               switch (read_key())  调用按键接口程序  
//        {
//        case 1:
//    {
//     ss_r=0;  在接收数据时要先拉低
//     PORTA="spiread"();
//     ss_r=1;
//    clk_r=1; 
//            }  break; 
//         case 2:
//            {
//            ss_s=0;
//     spisend(0x80);
//     ss_s=1;
//            }break;
//         case 3:
//         {
//           ss_s=0;
//     spisend(0x00);
//     ss_s=1;
//            }
//            break;
//        case 4:
//        { 
//          }
//          break;
//          }
// }end keyproc
// 
// }end while
// }

点击此处查看原文 >>

系统分类: 汽车电子   |    用户分类:    |    来源: 原创

评论(0) | 阅读(752)
发表于:2008-3-13 18:36:09
标签:电机调速  

0

电机调速控制系统_主程序

这个是电机调速控制系统的程序,单片机是AVR的mega16,采用液晶显示,电路图在前面已经发过了。

#include <mega16.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include "first.c"
#include "pid.c"
#include "delay.c"
#include "key_4.c" 
#include "1602a.c"
// Declare your global variables here
bit s1; //停止/开始
bit s2; //正转反转

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Place your code here
TCNT0=0x83;
  
 if(++tc>250)
   {  
     tc="0";
    #asm("cli"); 
    read="1";
    }
   if (++key_stime_counter >=3)//定时10MS
  {      
   key_stime_counter = 0;
   key_stime_ok = 1; 
                 }
}  
// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
//read=1;
counter++;
}//end interrupt
 
/**************************读取计数值显示************************/
void read_counter()
{
   unsigned int sett;
   unsigned int count;//计数值    
    count="counter";
   count=(count*60);
  count="count">>3; 
  LcdPos(0,1); //确定光标位置
  LcdWd('p');  //个位 
  LcdWd('r');  //
  LcdWd('e');
  LcdWd('='); 
  LcdPos(11,1); //确定光标位置
  LcdWd('s');  //
  LcdPos(10,1); //确定光标位置
  LcdWd('/');  //
  LcdPos(9,1); //确定光标位置
  LcdWd('n');  //
  LcdPos(8,1); //确定光标位置
  LcdWd(count%10+0x30);  //个位
 
  count/=10;  //十位
  LcdPos(7,1); //确定光标位置
  LcdWd(count%10+0x30);    
 
  count/=10;  //百位
  LcdPos(6,1); //确定光标位置
  LcdWd(count%10+0x30);
  count/=10;  //千位
  LcdPos(5,1); //确定光标位置
  LcdWd(count%10+0x30);
  count/=10;  //万位
  LcdPos(4,1); //确定光标位置
  LcdWd(count%10+0x30);

     sett="set";
     LcdPos(0,0);
     LcdWd('s');
     LcdWd('e');
     LcdWd('t');
     LcdWd('=');     
  LcdPos(11,0); //确定光标位置
  LcdWd('s');
  
  LcdPos(10,0); //确定光标位置
  LcdWd('/');
   
  LcdPos(9,0); //确定光标位置
  LcdWd('n');
  LcdPos(8,0); //确定光标位置
 
  LcdWd(sett%10+0x30);
  sett/=10;
 
  LcdPos(7,0); //确定光标位置
  LcdWd(sett %10+0x30);    
  sett/=10;
 
  LcdPos(6,0); //确定光标位置
  LcdWd(sett%10+0x30);
 
  sett/=10;
  LcdPos(5,0); //确定光标位置
  LcdWd(sett%10+0x30);
  sett/=10;
 
  LcdPos(4,0); //确定光标位置
  LcdWd(sett%10+0x30);   
  counter="0";
    #asm("sei");
}//end read_counter
/***************************主函数***********************************/
void main(void)
{
   
    double      rOut;                   //  PID Response (Output)
    double      rIn;                    //  PID Feedback (Input)
   PIDInit ( &sPID );                  //  Initialize Structure
   ocr="700";
  set="1500";
    sPID.Proportion =1.5;              //  Set PID Coefficients
   // sPID.Integral   = 0.683;
   // sPID.Derivative = 0.683;
  sPID.SetPoint =set;            //  Set PID Setpoint
  sPID.SetPoint=sPID.SetPoint/60.0;
  #asm("cli");

PORTA=0x00;   //液晶
DDRA=0XFF;
PORTB=0x00;
DDRB=0x0F;//0000 1111  
PORTC=0x00;
DDRC=0x00;
PORTD=0x30;//0000 0000  PD2外部中断入口
DDRD=0x30;//0011 0000

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 125.000 kHz
// Mode: CTC top="OCR0"
// OC0 output: Disconnected
TCCR0=0x04; //定时4MS*500
TCNT0=0x83;
OCR0=0x82;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 1000.000 kHz
// Mode: Ph. correct PWM top="00FFh"
// OC1A output: Non-Inv.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0xc3;//选通OC1A
TCCR1B=0x01;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x03;
OCR1AL=0xff;
OCR1BH=0x03;
OCR1BL=0xff;//对应着PD4口的PWM波,
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top="FFh"
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Rising Edge
// INT1: Off
// INT2: Off
GICR|=0x40;
MCUCR=0x03;
MCUCSR=0x00;
GIFR=0x40;  //通过写1来清0
 

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x01;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
RstLcd();
key_init(); //键盘初始化
#asm("sei")   // 开放全局中断
 
while (1)
      {
      // Place your code here
//***********************键盘处理*******************************//
      
      if (key_stime_ok)    // 10ms到,键处理
          {
             key_stime_ok = 0;
              switch (read_key())   // 调用按键接口程序  
               {
             /****************复位******************/ 
               case 1:
    { 
    /************键值处理**************/
      s1=!s1;
      if (s1)
      {
        RR
         LcdPos(14,1); //确定光标位置
                       LcdWd('R');  //
                       LcdPos(12,0); //确定光标位置
                       LcdWd('R');
                       LcdWd('U');
                       LcdWd('N');
                       LcdWd(' ');
        }
       else
       {
         ocr="0";
         ST
                      LcdPos(12,0); //确定光标位置
                      LcdWd('S');
                      LcdWd('t');
                      LcdWd('o');
                      LcdWd('p'); 
                      }              
                                 
                   }  break; 
                      case 2:
                   { 
                      s2=!s2;
                      if (s2)
                      {
                        ocr="0";
                        RR//电机正转
                        ocr="700";
                        LcdPos(14,1); //确定光标位置
                         LcdWd('R');  //
                        LcdPos(12,0); //确定光标位置
                          LcdWd('R');
                      LcdWd('U');
                      LcdWd('N');
                      LcdWd(' ');
                      }
                      else
                      {
                      ocr="0";
                      LL
                      ocr="700";
                      LcdPos(14,1); //确定光标位置
                      LcdWd('L');  //
                      LcdPos(12,0); //确定光标位置
                      LcdWd('R');
                      LcdWd('u');
                      LcdWd('n');
                      LcdWd(' ');
                      }
                    
                   }break;
                case 3:
                 
                {  
                  set-=100; //按一次加100
                 if (set<1500)
                  set="4000";
                   }
                  
                   break;
               case 4:
               { 
        //   read_counter();
         //  rIn = sensor ();                //  Read Input
         //  rOut = PIDCalc ( &sPID,rIn );   //  Perform PID Interaction
        //   actuator ( rOut );              //  Effect Needed Changes
              set+=100; //按一次加100
              if (set>4000)
              set="1500";
              }
                 break;
                 }
           }//end keyproc
   //  read_counter();   
     if (read==1)
     {
       read="0";
     if (counter<2) ST  //当有外力时,停止
       sPID.SetPoint=((unsigned int )sPID.SetPoint<<3)/60.0; 
      sPID.SetPoint =set;
      sPID.SetPoint=sPID.SetPoint/60.0;
       rIn = sensor ();                //  Read Input
       rOut = PIDCalc ( &sPID,rIn );   //  Perform PID Interaction
       actuator ( rOut );              //  Effect Needed Changes
       read_counter(); 
     }//end  read
       }//end while
}//end main

/*====================================================================================================
   PID计算部分
=====================================================================================================*/

double PIDCalc( PID *pp, double NextPoint )//NextPOint为下次测量的值
{
    double  Error;
    //dError,
           

       Error = pp->SetPoint - NextPoint;          // 偏差  
         //  Error = NextPoint-pp->SetPoint ;
        //if (Error>3000) ST;
       // pp->SumError += Error;                      // 积分
       // dError = pp->LastError - pp->PrevError;     // 当前微分
        pp->PrevError = pp->LastError;
        pp->LastError = Error;
        return (pp->Proportion *(Error*2.45 -3.0*pp->LastError+1.55 *pp->PrevError)              // 比例项
                     // 积分项
                    // 微分项
        );
}
 
/*====================================================================================================
   Initialize PID Structure
=====================================================================================================*/

void PIDInit (PID *pp)  //定义一下结构类型变量PP
{
    memset ( pp,0,sizeof(PID)); //清空一个结构类型的变量或数组
}

/*====================================================================================================
    Main Program
=====================================================================================================*/

double sensor (void)                    // 接收采集的数据
{  
  // if (counter<30) ST  //当有外力时,停止
    return (counter>>3);
}

void actuator(double rDelta)            // 对接收回来的数进行处理送显示

   ocr="ocr"+rDelta;
  if (TCCR1A==0xc3)  
 
 { 
   OCR1A=ocr;}//  对应着PD5口输出的PWM波,当为0时最大
   if (TCCR1A==0x33)
   {OCR1B=ocr;} 
  if (ocr>1024) ocr="700";
  // if (ocr<300) { ST};//停止
  
 }

/***************定时器0中断进行键盘扫描时间****************/
/***********************************************
interrupt [TIM0_COMP] void timer0_comp_isr(void)
{
// Place your code here
if (++key_stime_counter >=5)//定时10MS
  {
   key_stime_counter = 0;
   key_stime_ok = 1; 
                  }
} */
/********************定时器0寄存初始化*********************/
/**********************************************/
void key_init(void)
{
  //TCCR0|=0x0b;//采用比较模式,256分频   8M/256=31.25K
  //TCNT0|=0x00;
  //OCR0=0x3D;// (61+1)/31.25   =2ms
// Timer(s)/Counter(s) Interrupt(s) initialization
 // TIMSK|=0x01;
 // #asm("sei")   // 开放全局中断
}
/***********************************/
/********函数功能说明***************/
/********键盘功能处理***************/
void key_pro(void)
{
      if (key_stime_ok)    // 10ms到,键处理
          {
             key_stime_ok = 0;
              switch (read_key())   // 调用按键接口程序  
               { case 1:
    { /************键值处理**************/
       PORTA="0X11";   
                   }  break;
                case 2:
                     PORTA="0XFE";
                     break;
                case 3:
                   PORTA="0XF1";
                   break;
               case 4:
                 PORTA="0x55";
                 break;
                 }
                
           }
}

/*************键盘扫描*****************/
/****************************************/

char read_key(void)
{
  char key_press, key_return = 0;
  key_press = key_input;  // 读按键I/O电平,当有键按下时为0,没按下时为1
  switch (key_state)
 {
  case key_state_0:    // 按键初始态
      if (key_press!=0x3c) key_state = key_state_1;// 键被按下,状态转换到键确认态
   break;
  case key_state_1:    // 按键确认态
      if (key_press!=0X3C)    //有键按下
    {
 //key_return = 1;   // 按键仍按下,按键确认输出为"1"
 switch (key_press=key_input)
 {
 case 0x1c:
 key_return=1;    break;
 case 0x2c:
 key_return=2;break;
 case 0x34:
 key_return=3;break;
 case 0x38:
 key_return=4;break;
 }   
 key_state = key_state_2; // 状态转换到键释放态
 }
 else
 key_state = key_state_0; // 按键已抬起,转换到按键初始态
 break;
 case key_state_2:       //键已经释放,确认了有键按下
 if (key_press==0x3c)
 key_state = key_state_0; //按键已释放,转换到按键初始态
 break;
  } 
     return key_return;         //当返回为0时,表示没有键按下,
}

点击此处查看原文 >>

系统分类: 汽车电子   |    用户分类:    |    来源: 原创

评论(0) | 阅读(431)
发表于:2008-2-6 13:31:00
标签:555  

0

迟旧迎新

留下一片地。。。

点击此处查看原文 >>

系统分类: 自由话题   |    用户分类:    |    来源: 原创

评论(0) | 阅读(433)
发表于:2007-12-9 19:18:25
标签:键盘扫描  

0

4*4键盘扫描

                      4*4键盘扫描文档

  今天把4*4键盘的程序从单片机上移植到了NIOS上。

   4*4键盘扫描电路

 

 

程序采用间隔时间进行扫描法,由于键盘的抖动时间为10ms-20ms之间,所以在定时器中加入一个标志位,当定时10ms后,就进入判断,采用类似FPGA的状态机法,进行扫描。有效的避开了抖动。

状态一,判断是否有键按下,有键按下,则转到状态二。

状态二:再进行判断有没键按下,有按下,则进行扫描,进入状态三。没有,则返回状态一。

   状态三: 根据行码,和列码进行判断键值,根据相应的键值执行相应的程序。进入状态四

   状态四: 判断键是否释放,松开,则返回状态一,没有,则在状态四。

首先分为行信号(key4—key7),作为输入端口,用于读取IO口上的电平值,初始时写0

列信号(key0---key3),作为输出端口,为送入扫描信号。

在初始时,将所有的列信号(输出口)(key3—key3)置为低电平,在没有任何键按下时,读取(输入口)key4—key7上的电平值将为1,当任何一个按键按下时,则key4-key7中将会有一行被拉低,则表示有键按下。

这时就开始从key0-key3送入扫描字,进行扫描。扫描字为0111,101111011110

如果在它的输入端口发现一个0值,则就知道了在哪一列上有键按下。没有的话,则扫描字左移,继续扫描。根据行值,列值,来读出键值。

 

根据上面的接口电路。Key7—key0对应着键盘的接口高位到低位。

假如:开始key7-key4作为输入口,由于上拉电阻,则读出的数据为1key0-key3作为输出口,写低电平。当键S4按下时,则Key4电平被拉低,判断出在第一行上有键按下。这时,进行扫描。在key0-key3送入扫描字1110,读取key4-key7口上电平,发现key4上的电平为0,则判断出第四列有键按下。则得出s4键按下。键值为key7:key0=1110 (行码)&1110(列扫描字)==1110 1110以此累推。

 

总结:经过移植几种程比较,这种效率最高。而且占用的时间比较少。不过在NIOS上移植,可以结合FPGA,直接做个4*4键盘扫描控制器,当有键按下时,可以进入中断。这样的话,节省了CPU的时间。当有键按下时,送出键按下标志位。进入中断。读取键值,执行键盘程序。可见NIOS的强大功能,和可配置性,还有很多东西待去学习。

/**********************************************************

*功能: 键盘扫描函数

*说明:

*********************************************************/

unsigned char read_key(void)

{

   unsigned char i;

   unsigned char key_return = 0;

  

   IOWR_ALTERA_AVALON_PIO_DIRECTION(KEY_PIO_BASE,0X0f);

   //高四位作为输入,读取数据,低四位为输出

   Key_data=0x00;//低四位输出口写0

    switch (key_state)

  {

      case 0:

           // 读按键高四位I/O电平,当有键按下时为0,没按下时为1 

    if((IORD_ALTERA_AVALON_PIO_DATA(KEY_PIO_BASE)&0xf0)==0xf0)

      {

              break;//无键按下返回

      }

     else

      {

             key_state=1; //有键按下      

      }break;

     

      case 1://进行扫描键值

             {

       if((IORD_ALTERA_AVALON_PIO_DATA(KEY_PIO_BASE)&0xf0)==0xf0)

                                                      //读取高四位电平

         {

              break;//无键按下返回,是误动作

         }

      else