原创 轻触式开关电路在AVR单片机中的应用

2008-12-2 01:39 2492 4 4 分类: 软件与OS
引 言:
单键开关电路已经广泛应用于PDA、手机和电子词典等数码产品中,其实现方式多种多样。一般可采用RS触发器、计数器以及采用555集成电路等等。在单片机的一些实际应用中,以上的实现方式会增加整个电路的复杂度,不能达到简洁、实用的效果。本文将介绍一种可以在单片机应用中实现的,简易、稳定的轻触式单键开关电路。
1 电路原理

  如图1所示,DC-DC为一个带有关断控制端的直流稳压电源芯片,MCU是一个单片机。当按下S1时,Q1和D1导通,稳压芯片工作,为单片机供电。单片机马上将相应的I/O引脚置为输出高,这时Q1和Q2导通,整个电路进入工作状态。而后单片机再将这个I/O引脚设置为输入,由于上拉电阻R4的存在,Q1和Q2一直导通。单片机一直扫描相应I/O输入状态,如果S1没有按下去,则这个I/O将始终为高。当S1再次按下去时,D2导通,单片机检测到这个I/O引脚输入为低,这时单片机就将这个I/O设置成输出为低的状态。Q2截止,如果按键抬起,Q1也会截止,稳压芯片将不会为单片机提供电压,整个电路处于关断状态。

388171_1.jpg


2 关于R3和上拉电阻R4的取值

  在一些单片机中,例如AVR系列单片机ATmega8L,带有内部上拉电阻Rpu,如图2所示。

388171_2.jpg

可以通过单片机程序控制电阻上拉与否,从而不需要外接上拉。
一般情况下,R3取值要远大于R4,否则单片机I/O的输入电压Vpin会有低于标准输入电压VIH最低值的可能。从ATmega8L数据手册中查到 Rpu取值在20kΩ~100kΩ之间,又因为VIH的最小值约为0.6VCC。因此R3/(R3+R4)>0.6,取R4=50kΩ,并取R3/ (R3+R4)=0.8 ,所以R3取值应该在200kΩ左右的范围,可以根据实际工作情况来选择具体的R4取值。

3 对Vin连接方式的处理

  从图1上不难看出,采用这种控制方式后,Q1上将会消耗一定的功率。一种降低功率消耗的方式就是将Vin直接接到电池上去,可以根据电路灵活掌握。

4 电容C1的作用

  对于一般的AVR单片机来说,内部都有BOD(Brown-down Detection)电路。这个电路具有低电压检测功能:当输入电压由高变低时,单片机就会自动复位。

  如图1所示,想关机的时候,按下S1,单片机输出低。按键抬起后,Q1、Q2截止,单片机掉电。然而单片机的BOD电路检测到单片机的电压突然降低后,就会使单片机复位,并将I/O设置为上拉状态,Q1、Q2导通,导制电路再次开启。

  加入C1后,使单片机掉电后要对C1进行充电,而在C1充电没有达到单片机工作最低电压期间,Q1、Q2已经截止了,从而打乱了单片机复位操作。 5 开关机延时处理

  在一些具体的应用场合,例如手机等数码产品,开关机都需要延时操作。一种简单的实现方式就是,单片机在按键按下时开始计数,直到按键抬起。只有这个计数值足够大,才允许开机,否则不认为是开机操作。同理,关机也可以做类似的处理。

  单片机程序流程如图3所示。

388171_3.jpg

单键开关电路已经广泛应用于PDA、手机和电子词典等数码产品中,其实现方式多种多样。一般可采用RS触发器、计数器以及采用555集成电路等等。在单片机的一些实际应用中,以上的实现方式会增加整个电路的复杂度,不能达到简洁、实用的效果。本文将介绍一种可以在单片机应用中实现的,简易、稳定的轻触式单键开关电路。


相关电路如下图示:点击看大图


MCU用的是AVR 的ATMEGA16L,电源芯片用的是LM2576-3.3,是低电平开启的,有些电源芯片用的是高电平开启。图中有标注。


20060824102218.JPG


这个是不能复位的版本。一复位就会关机。就是只有上电复位。


说明一下第一个电路工作原理:

S2按下后,D3,Q1,Q3导通,输出低电平给LM2576的判断控制端。稳压芯片工作,为单片机供电。单片机马上将相应的I/O引脚置为输出高,这时Q1和Q2及Q3都导通,整个电路进入工作状态。而后单片机再将这个I/O引脚设置为输入,由于开启AVR单片机IO的内置上拉电阻,Q1和Q2和Q3一直导通。单片机一直扫描相应I/O输入状态,如果S2没有按下去,则这个I/O将始终为高。当S2再次按下去时,D4导通,单片机检测到这个I/O引脚输入为低,此时作些延时,看延时合不合预先设定的值,达到则将单片机的这个I/O设置成输出为低的状态。Q2截止,如果按键抬起,Q1也会截止,稳压芯片将不会为单片机提供电压,整个电路处于关断状态。


注意,C10是必不可少的,不然由于单单片机的复位操作会使系统断电。

进入正常工作后,就将正常工作的代码写入EEPROM。关机时将正常关机的代码也写入EEPROM。这样,还可以检测是不是正常关机。


最后,奉上这些boot代码:

//*****************************GCC for the new lab board ******************************

//****************************** code 02 ***********************************************

#include

#include

#include

#include


#define POWER PB0

#define LED  PD7

#define ON  0x0f

#define OFF  0xf0

//******************************向UART 写一字节**************************************

int usart_putchar(char c)

{

 if(c==
)

 usart_putchar( );

 loop_until_bit_is_set(UCSRA,UDRE);

 UDR=c;

 return 0;

}

//*******************************从UART 读一字节*************************************

int usart_getchar(void)

{

 loop_until_bit_is_set(UCSRA,RXC);

 return UDR;

}

//************************************初始化i/o**************************************

void Initialuart(void)

{

 //UART 初始化

 UCSRB=_BV(RXEN)|_BV(TXEN);/*(1< UBRRL=25; //9600 baud 6MHz:38 4MHz:25

 //i/o 流UART 连接

 fdevopen(usart_putchar,usart_getchar,0);

}

//*********************************to start the power,hehe***************************

void Powerpost(void)

{

 unsigned long i="0";

 unsigned char val;

 DDRB&=~_BV(POWER);

 PORTB|=_BV(POWER);


 eeprom_busy_wait();

 val=eeprom_read_byte(0); //从EEPROM 0 地址处读取一字节赋给RAM 变量val

 if(val==OFF)

 {


  //if(PIND&_BV(K4)) _delay_ms(500);if(PIND&_BV(K4))

  while(!(PINB&_BV(POWER))) {i++;if(i>300000) break;}

  if(i>=300000)

  {

   DDRB|=_BV(POWER);

   PORTB|=_BV(POWER);

   eeprom_busy_wait(); //等待EEPROM 读写就绪

   eeprom_write_byte(0,ON); //将0xbb 写入到EEPORM 0 地址处 

   DDRD|=_BV(LED);

   PORTD|=_BV(LED); 

  }

  else

  {

   eeprom_busy_wait(); //等待EEPROM 读写就绪

   eeprom_write_byte(0,OFF); //将0xbb 写入到EEPORM 0 地址处

   DDRB|=_BV(POWER);

   PORTB&=~_BV(POWER); 

   DDRD|=_BV(LED);

   PORTD&=~_BV(LED);    

  }

    

 }

 else

 {

  DDRD|=_BV(LED);

  PORTD|=_BV(LED);

  DDRB|=_BV(POWER);

  PORTB|=_BV(POWER);

  eeprom_busy_wait(); //等待EEPROM 读写就绪

  eeprom_write_byte(0,ON); //将0xbb 写入到EEPORM 0 地址处 

 }

}

//************************************Shut Down *************************************

void ShutDown(void)

{

 unsigned long i="0";

 while(!(PINB&_BV(POWER))) {i++;if(i>200000) break;}

 if(i>=200000)

 {

  eeprom_busy_wait(); //等待EEPROM 读写就绪

  eeprom_write_byte(0,OFF); //将OFF 写入到EEPORM 0 地址处

  PORTD&=~_BV(LED);

  DDRB|=_BV(POWER);

  PORTB&=~_BV(POWER);     

 }

}

//************************************the entrey*************************************

int main()


 Powerpost();

 Initialuart();

 printf("hello,你好吗?嘿嘿!!
"); 

// PORTB=0x00;

 while(1)

 {

  ShutDown();

 }

}


祝大家成功!!!

文章评论0条评论)

登录后参与讨论
我要评论
0
4
关闭 站长推荐上一条 /2 下一条