资讯详情

基于AVR单片机的上下课自动打铃系统的实现(放出原理图+程序原码)

昨晚花一晚上把这些资料整理了一下,全部发出来了。 由于补课没有铃。 3 月份做了这个东西,已实际使用,稳定运行一个学期。 上运行图:

硬件如下: AVR ATmega16 单片机,开发板(用到上面的:继电器 LED 走马灯、两个按钮)、门铃、 LED 若干、 16Mhz 无源晶振 硬件照片: : 单片机: 晶振:

——————————好了 照片晒完了,下面开始正文—————————— 原理图如下: 好吧我的能耐真大,这电路图不是用什么 CAD 专业软件画的,而是用 Windows 画 图板用鼠标一笔一划画的。。。所以效果不是很好,凑合着看吧,知道个大概就行了。(开发板上肯定还有其他资源,电路图中的资源也不止开发板上的。这个电路 图是本系统的原理图而不是开发板的全部电路图,画的只是和本系统有关的东西,开发板上其他无关的就不画了,也不需要画) 简单说明下: L1~L8 对应开发板上的 8 LED D2~D6 对应上面运行图上的那 5 个红色“上课指示灯”; D1 为一盏绿色的 LED (运行图上注意点看,用透明胶包住的那个绿色 LED ),用于监视程序是否在运行(晶振是否起振,是否死机); K1 K2 用于选择上午下午(上午有早读,下午没有)。继电器不用说了,控制门铃开关用。 下面放出源程序。(刚刚我已在程序中加入了很多注释了,后面还是要做下解析): ————源程序(本程序版权归李彦锋所有)———— #defineuchar unsigned char #defineuintunsigned int #defineulong unsigned long int volatile uint nowtime; //计时变量。然后下面的几个变量是一些逻辑控制的 volatile uint ledmode; volatile uint shangkeledmode; volatile uint shangkeledtime; volatile uint class; //上下课逻辑,上课为1,下课为0,见主函数 #include <iom16v.h> #include <macros.h> void port_init(void) { B=0xFF; PORTB=0x00; DDRC=0xFF; DDRA=0XFF; DDRD|=0XF0; //初始化IO口 } void timer0_init(void) { TCCR0 = 0x00; TC 0 = 0x06; OCR0= 0xFA; TCCR0 = 0x03; //初始化timer0 } //timer0本系统中用于控制上下课指示灯闪烁 #pragma interrupt_handler timer0_ovf_isr:iv_ M0_OVF void timer0_ovf_isr(void) { tm0rsf(); //别看漏 TCNT0 = 0x06; } //TIMER1 initialize - prescale:256 // WGM: 0) Normal, TOP=0xFFFF // desired value: 1Sec // actual value:1.000Sec (0.0%) void timer1_init(void) { TCCR1B = 0x00; //stop TCNT1H = 0x0B; //setup TCNT1L = 0x ; OCR1AH = 0xF4; OCR1AL = 0x24; OCR1BH = 0xF4; OCR1BL = 0x24; ICR1H= 0xF4; ICR1L= 0x24; TCCR1A = 0x00; TCCR1B = 0x04; //start Timer //初始化timer1 } //timer1本系统中用于上课时间和下课时间计时 #pragma interrupt_handler timer1_ovf_isr:iv_TIM1_OVF void timer1_ovf_isr(void) { tm1rsf(); //哈哈可能有人漏看了这里,回调函数执行另一个函数,这样程序看起来更整洁,这是我的编程习惯^v^ TCNT1H = 0x0B; TCNT1L = 0xDC; //重载高低值 //timer1回调函数 } void init_devices(void) { CLI(); port_init(); timer0_init(); timer1_init(); CR = 0x00; GICR= 0x00; TIMSK = 0x05; (); } void delay(uint ms) //这个就不用说了 死循环延迟 { uint i,j; for(i=0;i<ms;i++) { for (j=0;j<2300;j++); } } void tm0rsf() //控制上课指示灯闪烁的函数,不喜欢写在回调函数里,这样程序看起来更工整。。。 { if(class==1) //是否上下课,上课就闪,下课就不闪。 { shangkeledtime++; if (shangkeledtime==150) //150ms闪一下。其他自己看吧。。。。 { shangkeledtime=0; if(shangkeledmode==1) //开灯,相应IO输出高电平 { PORTA|=0X54; PORTC|=0x02; PORTD|=0x20; shangkeledmode=0; } else //关灯,相应IO输出低电平(接地) { PORTA&=0X03; PORTC&=0xFC; PORTD&=0 F; shangkeledmode=1; //逻辑自己看吧。。。。 } } } else { PORTA&=0X03; PORTC&=0xFC; PORTD&=0XDF; } } void tm1rsf() //timer1回调函数执行的函数 { nowtime++; //计时变量自增 if(ledmode==1) //嗯这个就是控制D0 LED闪烁的了,主要就是看timer1是不是在走。 { ledmode=0; PORTA|=0x01; } else { ledmode=1; PORTA&=0XFE; } } void ring() //响铃函数,控制继电器的。。(PC7输出高电平) { PORTC=0xFF; //因为PC口只有用到一个PC7所以不管这么多懒得算了直接全部输出高电位 delay(300); PORTC=0x00; delay(8300); PORTC=0xFF; delay(300); PORTC=0x00; delay(8300); } uchar key_press() //检测K1K2是否按下。。 { uchar j; DDRD|=0X0F; PORTD|=0X0F; DDRD&=0XF0; j=PIND; j=j&0X0F; if(j==0X0F) { return 0; } else { return 1; } } uchar key_scan() //检测是K1还是K2按下。。 { uchar key; delay(10); if(key_press()) { key=PIND; key&=0X0F; switch(key) { case 0X0E: key=1; break; case 0X0D: key=2; break; default: key=0; } while(key_press()); } else { key=16; } return key; } void main() //好了主函数开始了。。。 { uchar i,j; uint k,mode; uint ledmode; init_devices(); //初始化IO。。上面有。 k=0; ledmode=1; //逻辑自己看,不用解释。。。 while(k==0) //注意了 这一段是上电后等待按下K1K2的。 { if(ledmode==1) //上电后LED走马灯在那狂闪(按下之前) { PORTB=0XF0;delay(80); ledmode=0; } else{PORTB=0X0F;delay(80);ledmode=1;} i=key_press(); if(i) { //判断按的哪个 j=key_scan(); if (j==1) {mode=1;k=1;} if (j==2) {mode=2;k=1;} } } if (mode==1) //如果按的K1,也就是早上用,有早读的 { uint o
锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台