/****************************************************************
名称:3.23 报警器与旋转灯 (The alarm and the rotary lamp)
平台:GCC atmega16
说明:本例启用了2个定时中断器中断和1个外部中断
其中T0定时器溢出中断控制 LED 旋转,T1 定时器溢出中断控制报警
声音输出,INT0 中断控制系统的启动与停止。
*****************************************************************/
#define F_CPU 1000000UL // 1M 晶振
#define INT8U unsigned char
#define INT16U unsigned int
#include <avr/io.h>
#include<avr/interrupt.h>
#include<util/delay.h>
#define SPK()(PORTD^=_BV(PD7)) // 蜂鸣器输出定义
volatile INT8U FRQ = 0x00; // (volatile :不优化程序的意思 )定时初值循环递增控制频率循环递减
INT8U ON_OFF=0; // 开关变量
INT8U Pattern=0xE0; //Pattern:模式 旋转灯端口花样初值 11100000
/****************************************************************
主程序
*****************************************************************/
int main()
{
DDRC=0xFF; // 配置LED输出端口
DDRD=~_BV(PD2); PORTD=_BV(PD2); // 配置按键输入与蜂鸣器输出端口
TCCR0=0x05; //T0 预设分频:1024
TCNT0=256-F_CPU/1024.0*0.1; // 1 MHz时钟,0.1s 定时初值
TCCR1B=0x01; // T1 预设分频:1
MCUCR=0x02; // INT0为下降沿触犯
GICR=0x40; // INT0中断使能
TIMSK|=0x05; // 开启2个定时器中断,分别控制报警器和LED
sei(); // 开总中断
while(1)
{
FRQ++; /*定时初值循环递增 控制频率循环递增*/ /*FRQ在超过255溢出后 从0开始在继续递增*/
_delay_ms(1); /*改变延时时参数 可调整报警声音输出的急促程度 (如:1、2、3、4)*/
}
}
/****************************************************************
外部中断0,启停报警器声音和 LED 旋转
*****************************************************************/
ISR(INT0_vect)
{
ON_OFF=!ON_OFF; // 启停切换
if(ON_OFF)
{
Pattern=0xE0; // 11100000,开3个灯旋转
}
else
{
TIMSK=0x00; // 关闭所有定时器中断
PORTC=0x00; // 关闭所有LED
PORTD&=~_BV(PD7); // 在蜂鸣器链接的 PD7 脚输出低电平
}
}
/****************************************************************
T0 定时器中断程序控制 LED 旋转
*****************************************************************/
ISR(TIMER0_OVF_vect)
{
TCNT0=256-F_CPU/1024.0*0.1; // 重装0.1s 定时初值
/* 以下两行 实现111 的循环左移(高位为1时 左移后 右端补1,否则直接左移)*/
if( Pattern&0x80) Pattern= (Pattern<<1)|0x01;
else Pattern<<=1;
PORTC=Pattern; // 显示LED
}
/****************************************************************
T1 定时器中断程序控制报警声音输出
*****************************************************************/
ISR (TIMER1_OVF_vect)
{
TCNT1=0xFE00+FRQ; //主程序中 FRQ 的递增导致输出频率递减
SPK();
}
|