<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 基于AVR單片機的上下課自動打鈴系統(tǒng)的實現(xiàn)

          基于AVR單片機的上下課自動打鈴系統(tǒng)的實現(xiàn)

          作者: 時間:2016-11-30 來源:網(wǎng)絡(luò) 收藏
          簡單說明下:
          L1~L8對應(yīng)開發(fā)板上的8個LED;D2~D6對應(yīng)上面運行圖上的那5個紅色“上課指示燈”;D1為一盞綠色的LED(運行圖上注意點看,用透明膠包住的那個綠色LED),用于監(jiān)視程序是否在運行(晶振是否起振,是否死機);K1 K2用于選擇上午下午(上午有早讀,下午沒有)。繼電器不用說了,控制門鈴開關(guān)用。
          下面放出源程序。(剛剛我已在程序中加入了很多注釋了,后面還是要做下解析):
          ————源程序(本程序版權(quán)歸李彥鋒所有)————
          #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,見主函數(shù)

          #include
          #include

          void port_init(void)
          {
          DDRB=0xFF;
          PORTB=0x00;
          DDRC=0xFF;
          DDRA=0XFF;
          DDRD|=0XF0;
          //初始化IO口
          }


          void timer0_init(void)
          {

          TCCR0 = 0x00;
          TCNT0 = 0x06;
          OCR0= 0xFA;
          TCCR0 = 0x03;
          //初始化timer0
          }
          //timer0本系統(tǒng)中用于控制上下課指示燈閃爍
          #pragma interrupt_handler timer0_ovf_isr:iv_TIM0_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 = 0xDC;
          OCR1AH = 0xF4;
          OCR1AL = 0x24;
          OCR1BH = 0xF4;
          OCR1BL = 0x24;
          ICR1H= 0xF4;
          ICR1L= 0x24;
          TCCR1A = 0x00;
          TCCR1B = 0x04;//start Timer
          //初始化timer1
          }

          //timer1本系統(tǒng)中用于上課時間和下課時間計時

          #pragma interrupt_handler timer1_ovf_isr:iv_TIM1_OVF
          void timer1_ovf_isr(void)
          {
          tm1rsf();//哈哈可能有人漏看了這里,回調(diào)函數(shù)執(zhí)行另一個函數(shù),這樣程序看起來更整潔,這是我的編程習慣^v^

          TCNT1H = 0x0B;
          TCNT1L = 0xDC;//重載高低值

          //timer1回調(diào)函數(shù)
          }


          void init_devices(void)
          {
          CLI();
          port_init();
          timer0_init();
          timer1_init();
          MCUCR = 0x00;
          GICR= 0x00;
          TIMSK = 0x05;
          SEI();
          }


          void delay(uint ms)//這個就不用說了 死循環(huán)延遲
          {
          uint i,j;
          for(i=0;i {
          for (j=0;j<2300;j++);
          }
          }

          void tm0rsf()//控制上課指示燈閃爍的函數(shù),不喜歡寫在回調(diào)函數(shù)里,這樣程序看起來更工整。。。
          {

          if(class==1)//是否上下課,上課就閃,下課就不閃。
          {
          shangkeledtime++;
          if (shangkeledtime==150)//150ms閃一下。其他自己看吧。。。。
          {
          shangkeledtime=0;
          if(shangkeledmode==1)//開燈,相應(yīng)IO輸出高電平
          {
          PORTA|=0X54;
          PORTC|=0x02;
          PORTD|=0x20;
          shangkeledmode=0;
          }
          else//關(guān)燈,相應(yīng)IO輸出低電平(接地)
          {
          PORTA&=0X03;
          PORTC&=0xFC;
          PORTD&=0XDF;
          shangkeledmode=1;//邏輯自己看吧。。。。
          }
          }
          }
          else
          {
          PORTA&=0X03;
          PORTC&=0xFC;
          PORTD&=0XDF;
          }
          }

          void tm1rsf()//timer1回調(diào)函數(shù)執(zhí)行的函數(shù)
          {
          nowtime++;//計時變量自增
          if(ledmode==1)//嗯這個就是控制D0 LED閃爍的了,主要就是看timer1是不是在走。
          {
          ledmode=0;
          PORTA|=0x01;
          }
          else
          {
          ledmode=1;
          PORTA&=0XFE;
          }

          }

          void ring()//響鈴函數(shù),控制繼電器的。。(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()//好了主函數(shù)開始了。。。
          {
          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 overzaodu;
          uint canoverzaodu;
          overzaodu=0;
          canoverzaodu=0;
          PORTB=0XF3;//早讀上課時跑馬LED亮上面2盞(亮上面。。代表上午^v^)
          nowtime=0;
          class=1;
          while(canoverzaodu==0)
          {
          if (class==1)
          {
          if (nowtime==1200)//先上20分鐘的早讀
          {
          class=0;
          nowtime=0;
          overzaodu++;
          ring();//早讀下課打鈴
          }
          }
          else
          {

          if (nowtime==300)//早讀休息5分鐘,接下來自己看吧
          {


          class=1;
          nowtime=0;
          overzaodu++;
          ring();
          ring();
          PORTC=0xFF;
          delay(300);
          PORTC=0x00;
          }
          }
          if (overzaodu==1)

          {
          PORTB=0XF1;//早讀下課,LED多亮一盞
          }
          if (overzaodu==2)
          {
          canoverzaodu=1;
          PORTB=0XF0;//早讀結(jié)束,LED亮完上面4盞。。
          }//然后跳出早讀while,進入到下面正常上課while--上課40分鐘,下課10分鐘,上課,下課…………無限循環(huán)。。。
          }
          }

          if (mode==2)//按下K2,也就是下午用的
          {
          PORTB=0X0F;
          class=1;//邏輯,上課為1下課為0
          ring();
          ring();
          PORTC=0xFF;
          delay(300);
          PORTC=0x00;//這都是打鈴用的。。上課比較吵,要打5遍。(一個ring打兩遍,兩個ring后直接在這里控制IO再打一遍)
          }

          nowtime=0;

          while(1)//正常上課while,這里就不解釋太多了,邏輯和上面早讀的差不多的

          {


          if (class==1)
          {
          if (nowtime==2400)//是否夠40分鐘
          {
          class=0;
          nowtime=0;//計時變量清零
          ring();//打鈴,下課打2遍就好了(一個ring兩遍,具體看上面ring函數(shù))
          }
          }
          else
          {
          if (nowtime==600)
          {


          class=1;
          nowtime=0;
          ring();
          ring();
          PORTC=0xFF;
          delay(300);
          PORTC=0x00;//上課打5遍鈴,其他就不解釋這么多了,邏輯一樣的自己看就行。
          }
          }
          }
          }
          ————源程序(本程序版權(quán)歸李彥鋒所有)————
          再簡單說下吧,程序中的邏輯就不說了。
          1.點亮L1~L8為PB0~PB7輸出低電平(接地),因為那頭接的是VCC +5V的正電壓。
          2.PC7輸出高電位,繼電器B和C導(dǎo)通,接通門鈴,就響了。
          3.D1~D6我是直接把LED的正負接在IO口上的,所以輸出電位的時候一高一低。其實可以IO口上全接正然后統(tǒng)一接地,但是這樣麻煩,反正有足夠的IO口,就這么干了。
          附:最早是用內(nèi)部時鐘,然后后來跑不準,折騰了我一個星期,后來才發(fā)現(xiàn)是內(nèi)部時鐘的問題,上了個晶振,解決問題。。。
          好了就說到這里,結(jié)束。
          上一頁 1 2 下一頁

          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();