简介
首先开关机部分是硬件电路配合的,然后控制led闪烁放在定时器中断里了(个人因为要求不高,就放中断里了),其他没什么,发出来方便没用过的人快速使用。
程序
注释:
1.开发环境为WinAVR
2.器件出厂时 CKSEL = “10”, SUT = “10”,且 CKDIV8 编程。这个缺省设置的时钟源是9.6MHz 的内部 RC 振荡器,初始系统时钟预分频为 8,启动时间为最长。这种设置保证用户可以通过 ISP 或并行编程器得到所需的时钟源。
3.Makefile里注意改:F_CPU = 1200000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#define BIT0 (0x1<<0)
#define BIT1 (0x1<<1)
#define BIT2 (0x1<<2)
#define BIT3 (0x1<<3)
#define BIT4 (0x1<<4)
#define BIT5 (0x1<<5)
void key_scan(void);
void sys_init(void);
volatile unsigned char TIM_WORK = 0;
volatile unsigned char tim = 0;
volatile unsigned char TIM_FLAG = 0;
volatile unsigned char key_flicker = 1;
unsigned char key_up = 1;
int main(void)
{
sys_init();
_delay_ms(250);//避免按键开机时开始按键扫描
while(1)
{
key_scan();
}
return 0;
}
void sys_init(void)
{
OSCCAL = 0x58; //校准片内RC振荡器频频率9.6MHz
DDRB = 0x00; //将所有I/O口均初始化为输入状态
PORTB = 0x00; //BIT(ADC_PORT);
/*IO初始化*/
DDRB |= 0x0A; //PB1,PB3设为输出
DDRB &= ~(BIT0 | BIT4); //设为上拉输入
PORTB |= (BIT0 | BIT4);
PORTB |= BIT1; //保持电源
PORTB |= BIT3; //打开led
/*定时器中断初始化*/
TCCR0B = 5; //1024分频
TIMSK0|= BIT1; //溢出中断
/*时钟频率1.2M ,3次中断,500ms,使用示波器测量,闪烁周期为990ms
*1200000/1024=1172; 1172*0.5=586; //期望周期为1s
*由于定时器计数255中断一次,所以中断两次后,在TCNT0中写入255-(586%255)=179
*即可实现500毫秒中断一次 ; 我下面的值并不是这个数
*/
TCNT0 = 0x95;
sei(); //开总中断
}
void key_scan(void)
{
char i;
if(((PINB&0x01) != 0)&&((PINB&0x10) != 0))
{
key_up = 1;
}
if(key_up == 1)//避免按键按下后继续扫描
{
if((PINB&0x01)== 0)//关机按键
{
for(i=0;i<5;i++)
{
_delay_ms(100);
}
if((PINB&0x01)== 0)
{
PORTB &= ~(BIT1|BIT3);//关机
}
}
else if((PINB&0x10)== 0)//分频按键
{
_delay_ms(10);
if((PINB&0x10)== 0)
{
if(key_flicker == 0)
{
key_flicker = 1;
TIM_WORK = 0;
PORTB |= BIT3;
key_up = 0;
}
else
{
key_flicker = 0;
TIM_WORK = 1;
key_up = 0;
}
}
}
}
}
ISR(TIM0_OVF_vect)
{
if(TIM_WORK == 1)
{
tim++;
if(tim == 2)
{
TCNT0 = 0x95;
}
if(tim == 3)
{
tim = 0;
if(TIM_FLAG == 0)
{
PORTB |= BIT3;
TIM_FLAG = 1;
}
else
{
PORTB &= ~BIT3;
TIM_FLAG = 0;
}
}
}
}
附件
ATTINY13芯片手册中文版
百度网盘:提取码:qe6d