欧美色欧美亚洲高清在线观看,国产特黄特色a级在线视频,国产一区视频一区欧美,亚洲成a 人在线观看中文

  1. <ul id="fwlom"></ul>

    <object id="fwlom"></object>

    <span id="fwlom"></span><dfn id="fwlom"></dfn>

      <object id="fwlom"></object>

      北郵小學(xué)期AVR單片機(jī)電子琴實(shí)驗(yàn)報(bào)告

      時(shí)間:2019-05-13 01:16:21下載本文作者:會(huì)員上傳
      簡(jiǎn)介:寫(xiě)寫(xiě)幫文庫(kù)小編為你整理了多篇相關(guān)的《北郵小學(xué)期AVR單片機(jī)電子琴實(shí)驗(yàn)報(bào)告》,但愿對(duì)你工作學(xué)習(xí)有幫助,當(dāng)然你在寫(xiě)寫(xiě)幫文庫(kù)還可以找到更多《北郵小學(xué)期AVR單片機(jī)電子琴實(shí)驗(yàn)報(bào)告》。

      第一篇:北郵小學(xué)期AVR單片機(jī)電子琴實(shí)驗(yàn)報(bào)告

      北京郵電大學(xué)信息與通信工程學(xué)院

      小學(xué)期AVR單片機(jī)實(shí)驗(yàn)報(bào)告

      實(shí)驗(yàn)題目: 基于ATmega16L單片機(jī)的電子琴設(shè)計(jì)

      學(xué)生姓名:學(xué)渣

      班 級(jí):2012XXXXXX 班內(nèi)序號(hào):XX 學(xué) 號(hào):2012XXXXXX 日 期:2014年9月30日

      同組同學(xué):學(xué)渣

      第1頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      目錄:

      一、實(shí)驗(yàn)介紹......................................3 1.1實(shí)驗(yàn)課題名稱.................................3 1.2實(shí)驗(yàn)平臺(tái).....................................3 1.3實(shí)驗(yàn)課題關(guān)鍵字 ..............................3 1.4實(shí)驗(yàn)摘要.....................................3

      二、小組分工......................................3

      三、基本題目訓(xùn)練——流水燈與數(shù)碼管秒表計(jì)時(shí)器.......3 3.1實(shí)現(xiàn)功能......................................3 3.2程序代碼分析..................................4 3.3實(shí)驗(yàn)結(jié)果圖片...................................7

      四、有關(guān)發(fā)聲的基礎(chǔ)知識(shí)............................7

      五、電子琴的設(shè)計(jì)與測(cè)試..............................9 5.1設(shè)計(jì)過(guò)程......................................9 5.2實(shí)驗(yàn)所需元器件.................................9 5.3實(shí)驗(yàn)程序主要流程圖.............................10 5.4實(shí)驗(yàn)原理及原理圖...............................10 5.4.1實(shí)驗(yàn)原理....................................10 5.4.2原理圖.....................................11 5.5各個(gè)模塊的設(shè)計(jì)與講解............................11 5.6程序源代碼及程序分析..........................14 5.7實(shí)驗(yàn)結(jié)果.......................................24

      六、排錯(cuò)過(guò)程.........................................26

      七、心得體會(huì)..........................................29

      八、參考文獻(xiàn)..........................................32

      九、意見(jiàn)與建議........................................33

      第2頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      一、實(shí)驗(yàn)介紹:

      1.1實(shí)驗(yàn)課題名稱:基于ATmega16L單片機(jī)的電子琴設(shè)計(jì) 1.2實(shí)驗(yàn)平臺(tái):本實(shí)驗(yàn)所用平臺(tái)為AVR Studio 4 1.3實(shí)驗(yàn)課題關(guān)鍵字:

      ATmega16L型單片機(jī) 電子琴 鍵盤(pán)按鍵 LCD液晶顯示屏

      1.4實(shí)驗(yàn)摘要:

      本實(shí)驗(yàn)設(shè)計(jì)的電子琴擁有可視化操作界面,能實(shí)現(xiàn)即時(shí)彈奏音樂(lè)、音樂(lè)播放、音樂(lè)變速、音樂(lè)變調(diào),并可以進(jìn)行任意長(zhǎng)度錄音(通過(guò)按鍵記錄音階)等功能

      二、小組分工:

      ? XXX負(fù)責(zé)電路硬件的連接和報(bào)告的撰寫(xiě) ? XXX負(fù)責(zé)程序代碼的編寫(xiě) ? XXX負(fù)責(zé)資料的收集整理和查閱

      三、基本題目訓(xùn)練——流水燈與數(shù)碼管秒表計(jì)時(shí)器

      3.1功能:八盞LED二極管按順序依次循環(huán)點(diǎn)亮,實(shí)現(xiàn)流水燈的效果,同時(shí)兩只數(shù)碼管分別代表秒和十分之一秒,進(jìn)行秒表計(jì)時(shí),配有

      第3頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      兩個(gè)按鍵,實(shí)現(xiàn)計(jì)時(shí)過(guò)程中的暫停和繼續(xù),同時(shí)在按下暫停鍵的時(shí)候蜂鳴器會(huì)響一聲。利用ATmega16的寄存器中斷功能,實(shí)現(xiàn)流水燈和數(shù)碼管秒表計(jì)時(shí)器在實(shí)驗(yàn)板上同時(shí)工作,并且互相獨(dú)立不影響。

      3.2程序代碼分析:

      #include #include

      char b[10] = {

      0b11111010,//0

      0b00110000,//1

      0b11011001,//2

      0b01111001,//3

      0b00110011,//4

      0b01101011,//5

      0b11101011,//6

      0b00111000,//7

      0b11111011,//8

      0b01111011,//9

      };char a[10] = {

      0b11111010,//0

      0b00110000,//1

      0b11011001,//2

      0b01111001,//3

      0b00110011,//4

      0b01101011,//5

      0b11101011,//6

      0b00111000,//7

      0b11111011,//8

      0b01111011,//9

      };

      volatile char temp;

      int main(void){ DDRA = 0xff;PORTA = 0b10000000;DDRC = 0xff;

      第4頁(yè)

      北京郵電大學(xué)信息與通信工程學(xué)院

      DDRD = 0b11111011;DDRB = 0b11111011;

      TCNT0 = 55;PORTB = b[0];PORTD = a[0];PORTC |=(1 << 0);TCCR0 |=(1 << CS01);int count1 = 0,count2 = 0,i;

      MCUCR |=(1 << ISC00)|(1 << ISC01);//INT0上升沿觸發(fā)

      GICR |=(1 << INT0);//使能INT0,INT1 sei();//使能全局中斷

      while(1){

      for(i = 0;i<9000;i++)

      {

      while(!(TIFR &(1<

      TCNT0=55;

      }

      count1++;

      if(count1!=10)

      PORTD = a[count1];

      else

      {

      count2++;

      count1 = 0;

      if(count2 == 10)

      count2 = 0;

      temp = PORTA;

      PORTA = PORTA >> 1;

      if(temp & 0b00000001)

      {

      PORTA = PORTA | 0b10000000;

      }

      PORTB = b[count2];

      PORTD = a[0];

      }

      } } SIGNAL(SIG_INTERRUPT0)//INT0中斷服務(wù)程序 {

      int count3 = 0,count4=0;

      第5頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      while(!(PINB &(1<<2)))

      {

      count3++;

      if(count3 == 10)

      {

      count4++;

      count3 = 0;

      temp = PORTA;

      PORTA = PORTA >> 1;

      if(temp & 0b00000001)

      {

      PORTA = PORTA | 0b10000000;

      }

      }

      for(int i=0;i<9000;i++)

      {

      while(!(TIFR &(1<

      TCNT0=55;

      } } }

      第6頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      3.3實(shí)驗(yàn)結(jié)果:

      四、有關(guān)發(fā)聲的基礎(chǔ)知識(shí): 聲波是振動(dòng)產(chǎn)生的。頻率即表示每秒鐘振動(dòng)的次數(shù),采用CTC方式時(shí)AVR單片機(jī)通過(guò)特定的端口(PD4及PD5)輸出一定頻率的方波,TCCR1A設(shè)為比較匹配時(shí)OC1A/OC1B電平取反,TCCR1B的計(jì)數(shù)上限為

      第7頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      OC1A,根據(jù)公式OCnA=f/2N(1+OCRnA)計(jì)算出7個(gè)頻率音階所需的OCR1A,則只需將喇叭接在PD4或PD5,通過(guò)程序控制端口輸出特定頻率的方波波形(發(fā)聲使用正弦波最好,方波效果稍次但影響不大),喇叭就會(huì)發(fā)出七種不同的聲音,依照人聽(tīng)覺(jué)分辨7個(gè)音階分為三組,分別為高中,低音階頻率,經(jīng)計(jì)算可得,當(dāng)OCR1A=(500000/musicmem[i]-1)時(shí),{131,147,165,175,196,220,247}存放低音階頻率,{262,294,330,349,392,440,494}存放中音階頻率,{524,588,660,698,784,880,988}則存放高音階頻率,所以需要定義三個(gè)數(shù)組存放各音階的頻率值。除了音符頻率以外還需要音長(zhǎng),所以定義1個(gè)2位數(shù)組表示一段音樂(lè),第一個(gè)表示頻率,第二個(gè)表示音長(zhǎng),播放時(shí)先訪問(wèn)頻率數(shù)組,使喇叭發(fā)聲,之后訪問(wèn)音長(zhǎng)數(shù)組,確定喇叭發(fā)聲時(shí)間。而有了音符頻率數(shù)組,只要再得到任意一首歌的簡(jiǎn)譜,就可以將其轉(zhuǎn)化為兩個(gè)數(shù)組的形式,由音符對(duì)應(yīng)的頻率得出頻率數(shù)組,然后再根據(jù)每個(gè)音符的音長(zhǎng),將其通過(guò)樂(lè)曲的節(jié)拍和音符的拍數(shù)計(jì)算出音符持續(xù)時(shí)間即可得出音長(zhǎng)數(shù)字。

      第8頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      五、電子琴的設(shè)計(jì)過(guò)程: 5.1設(shè)計(jì)過(guò)程:

      5.2 實(shí)驗(yàn)所需元器件:

      ATmega16L型單片機(jī),JTAG下載器,揚(yáng)聲器,4*4矩陣鍵盤(pán),液晶屏,LM386,實(shí)驗(yàn)盒(內(nèi)裝剪刀、鑷子、導(dǎo)線等用品)等

      第9頁(yè)

      1602LCD北京郵電大學(xué)信息與通信工程學(xué)院

      5.3實(shí)驗(yàn)程序主要流程圖:

      5.4實(shí)驗(yàn)原理及原理圖 :

      5.4.1實(shí)驗(yàn)原理 :

      以ATmega16單片機(jī)作為整個(gè)系統(tǒng)的控制中心,外加琴鍵控制模塊、播放模塊、顯示模塊,使制作的電子琴完成設(shè)想的功能。琴鍵控制模塊為4*4矩陣鍵盤(pán),可以通過(guò)按下不同的琴鍵彈奏出不同的音階,每個(gè)音階對(duì)應(yīng)著不同的頻率,一段音樂(lè)是由許多不同的音階組成,這樣我們就可以根據(jù)不同的頻率組合得到我們想要的音樂(lè),同時(shí)在錄制模式下,還可以通過(guò)按不同的按鍵記錄下不同的音階,由此記錄一段音樂(lè)。播放模塊接收對(duì)應(yīng)頻率的方波,由此播放琴鍵彈奏的音階以

      第10頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      及播放預(yù)先存放在單片機(jī)里的音樂(lè)。顯示模塊顯示出當(dāng)前所處的模式。

      5.4.2 原理圖:

      5.5各模塊的設(shè)計(jì)與詳解:

      ? 中央處理器——ATmega16:

      第11頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      實(shí)驗(yàn)中,PB0~PB7全部設(shè)置為輸出,分配給LCD液晶顯示屏D0~D7管腳;PA0~PA7連接4*4矩陣鍵盤(pán)的八個(gè)引腳;PD4、PD6和PD7設(shè)置為輸出狀態(tài),分別連接到LCD顯示屏的RS、R/W和E端口上;PD5置為輸出狀態(tài),接到揚(yáng)聲器的一個(gè)管腳,揚(yáng)聲器的另一管腳接地;VCC為電源,向LCD顯示屏供電;GND為公共接地。

      ? 琴鍵控制模塊——4*4矩陣鍵盤(pán):

      工作原理:按鍵設(shè)置在行、列線交點(diǎn)上,行、列線分別連接到按鍵開(kāi)關(guān)的兩端。行線通過(guò)上拉電阻接到+5V 電源上。無(wú)按鍵按下時(shí),行線處于高電平的狀態(tài),而當(dāng)有按鍵按下時(shí),行線電平由與此行線相連的列線的電平?jīng)Q定。

      ? 顯示模塊——LCD液晶顯示屏:

      第12頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      引腳詳解:

      第1腳:VSS為地電源。第2腳:VDD接5V正電源。

      第3腳:VL為液晶顯示器對(duì)比度調(diào)整端,接正電源時(shí)對(duì)比度最弱,接地時(shí)對(duì)比度最高,對(duì)比度過(guò)高時(shí)會(huì)產(chǎn)生“鬼影”,使用時(shí)可以通過(guò)一個(gè)10K的電位器調(diào)整對(duì)比度。

      第4腳:RS為寄存器選擇,高電平時(shí)選擇數(shù)據(jù)寄存器、低電平時(shí)選擇指令寄存器。

      第5腳:R/W為讀寫(xiě)信號(hào)線,高電平時(shí)進(jìn)行讀操作,低電平時(shí)進(jìn)行寫(xiě)操作。當(dāng)RS和R/W共同為低電平時(shí)可以寫(xiě)入指令或者顯示地址,當(dāng)RS為低電平R/W為高電平時(shí)可以讀忙信號(hào),當(dāng)RS為高電平R/W為低電平時(shí)可以寫(xiě)入數(shù)據(jù)。

      第6腳:E端為使能端,當(dāng)E端由高電平跳變成低電平時(shí),液晶模塊執(zhí)行命令。

      第7~14腳:D0~D7為8位雙向數(shù)據(jù)線。

      第13頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      第15腳:背光源正極。第16腳:背光源負(fù)極。

      ? 播放模塊——揚(yáng)聲器:

      原先以為單片機(jī)本身的電源電壓不足以驅(qū)動(dòng)揚(yáng)聲器工作,所以設(shè)計(jì)了有LM386的功放模塊,后來(lái)在實(shí)際操作的過(guò)程中測(cè)試發(fā)現(xiàn),單片機(jī)本身的電源足以驅(qū)動(dòng)揚(yáng)聲器播放音樂(lè)音調(diào),因此舍棄了LM386功放模塊的設(shè)置。

      5.6程序源代碼及程序分析:

      #include #include #pragma data:code

      #define uchar unsigned char #define uint unsigned int

      const uchar table[]=“HELLO WELCOME!”;

      volatile uint num=0,count=0;volatile uint Mode=0,list=2,pause=0,aim=0,sure=0,del=0;volatile int state=0, S=1;

      //定義全局變量,S為變速變量

      const uint Mode_Data[16]={0,440,494,523,587,659,698,784,880,998,1046,1156,1318,1396,1568};//存放聲音的頻率

      //音高對(duì)應(yīng)定時(shí)器初始化數(shù)值(低la~高la+休止符),cpu頻率1MHz,用8分頻 const uchar tone[]={0x00,0x8E,0x7E,0x77,0x6A,0x5E,0x59,0x4F,0x47,0x3F,0x3B,0x35,0x2F,0x2C,0x27,0x23,0X19,0X15};

      uint Ssong[10][2]={{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}};

      //******************************************** void delay_us(int n)

      //微妙級(jí)延時(shí)函數(shù); {

      第14頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      while(n--){

      asm(“nop”);//自動(dòng)延時(shí)一個(gè)時(shí)鐘周期什么也不做

      } }

      void delay_ms(int n)

      //毫秒級(jí)延時(shí)函數(shù); { int m=14500*n;while(m--){

      asm(“nop”);} } //********************************************** /************************ 屏幕顯示函數(shù)

      ************************/ void write_com(uchar com){ PORTD&=~(1<<4);

      //低電平指令模式。高電平數(shù)據(jù);

      PORTD&=~(1<<6);

      //低電平寫(xiě);

      PORTB=com;PORTD|=(1<<7);

      //高電平使能

      delay_ms(1);PORTD&=~(1<<7);

      }

      void write_dat(uchar dat){

      PORTD|=(1<<4);PORTD&=~(1<<6);PORTB=dat;PORTD|=(1<<7);delay_ms(1);PORTD&=~(1<<7);} /*********************************** *

      音樂(lè)產(chǎn)生函數(shù)

      * * 功能:輸出頻率為x的方波* * 范圍:x:100-20000Hz,0:不發(fā)聲

      * *

      ***********************************/

      第15頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      void sound(int i)

      {

      TIMSK|=(1<<2);sei();

      if(i&&i<17)

      //按了音符鍵了,且在0到F鍵這16個(gè)發(fā)音鍵上,才發(fā)聲

      {

      OCR1A=tone[i];

      TCCR1A=0X50;

      //控制寄存器,選擇可翻轉(zhuǎn)功能,產(chǎn)生方波;

      TCCR1B=0X0a;

      PORTD=(1<<5);}

      else

      {

      TCCR1A = 0x00;

      //頻率為0,休止符,不發(fā)聲

      TCCR1B=0X00;

      OCR1A=0;

      } } /************************************ 彈奏函數(shù)

      ************************************/ void play(int n)

      //參數(shù)為鍵盤(pán)上的數(shù)字;

      {

      write_com(0X80+0X40+n);write_dat(16);sound(n);

      //彈奏音符;

      delay_ms(1);write_dat(20);

      TCCR1A=0x00;

      TCCR1B=0X00;

      //中斷,為下一個(gè)節(jié)拍做準(zhǔn)備;

      PORTD|=(1<<5);

      //PD5作為輸出管腳,接揚(yáng)聲器; } //___________________________________________ void INI_POTR(void){ DDRD|=0xff;DDRB=0xff;

      PORTD=(1<<5);PORTD&=~(1<<7);DDRA=0xff;

      //A口作為鍵盤(pán)輸入口;

      DDRB=0xff;

      } //_____________________________________

      第16頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      void INN_DEVICE(void){ MCUCR=0X00;

      // 中斷寄存器置零;

      } //____________________________________ //檢測(cè)鍵盤(pán)是否被按下的函數(shù) uint isKeyPress(){ DDRA=0xff;

      //初始設(shè)置端口均為輸出

      PORTA=0xf0;

      //設(shè)置端口的初值為11110000 DDRA=0xf0;

      //將低四位設(shè)為輸入

      if(PINA == 0xf0)

      //當(dāng)沒(méi)有按下時(shí),PINA仍然為11110000 {

      DDRA=0xff;

      return 0;

      //返回0,代表未按下

      } else

      //當(dāng)按下后,PINA不再是11110000 {

      DDRA=0xff;

      return 1;

      //返回1,代表按下了

      } } //鍵盤(pán)輸入檢測(cè)函數(shù);

      //_______________________________ int key_in(void)

      {

      DDRA = 0xff;

      //先全部設(shè)置為輸出,再將后四位置為輸入

      PORTA = 0xf0;

      //設(shè)置高低電平

      DDRA = 0xf0;uint i = 0,j = 16,Key = 17;

      unsigned char temp1,temp2;

      if(isKeyPress()){

      temp1 = PINA;

      temp1 &= 0x0f;

      //只關(guān)心低四位的情況

      switch(temp1)

      {

      case 0b00000001:

      j = 0;

      break;

      case 0b00000010:

      j = 1;

      第17頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      break;

      case 0b00000100:

      j = 2;

      break;

      case 0b00001000:

      j = 3;

      break;

      }

      temp2 = PINA;

      temp2 &= 0x0f;

      if(temp1!= temp2)

      return 17;

      DDRA = 0xff;

      PORTA= 0x0f;

      DDRA = 0x0f;

      temp1 = PINA;

      temp1 &= 0xf0;

      switch(temp1)

      {

      case 0b00010000:

      i = 0;

      break;

      case 0b00100000:

      i = 1;

      break;

      case 0b01000000:

      i = 2;

      break;

      case 0b10000000:

      i = 3;

      break;

      }

      temp2 = PINA;

      temp2 &= 0xf0;

      if(temp1!= temp2)

      return 17;

      Key = i*4 + j+1;//

      return Key;

      }

      }

      /*****************************

      //去抖動(dòng)

      //只關(guān)心高四位的情況第18頁(yè)

      北京郵電大學(xué)信息與通信工程學(xué)院

      音樂(lè)播放函數(shù);

      *****************************/ void m_sound(uint a){

      int m=(62500/a)-1;

      //發(fā)聲原理

      OCR1A=m;

      TCCR1A=0X50;

      //控制寄存器,選擇可翻轉(zhuǎn)功能,產(chǎn)生方波;

      TCCR1B=0X0a;}

      //**********************************播放函數(shù); void music_play(uint a[][2]){

      const char Mtable[]=“Music Mode”;

      write_com(0X01);

      //清屏;

      for(int i=0;i<5;i++)

      {

      write_dat(Mtable[i]);

      }

      int i=0;

      char tem=aim,T=1;

      while((a[i][1]!=0)&&(tem==aim)&&state)

      {

      //A 返回 B 暫停 F 模式 C 上一曲你 D 播放

      E 下一曲;

      num=key_in();

      switch(num)

      {

      case 16:

      state=0;

      // F STATE = 0彈奏

      break;

      case 15:

      aim=1;

      //下一首E

      break;

      case 14:

      pause=1;

      //播放D

      break;

      case 13:

      aim=0;

      ///上一首C

      break;

      case 12:

      pause=0;

      ///暫停B

      break;

      case 11:

      第19頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      T=2;

      break;case 10: T=1;

      break;case 9:

      T=0;break;case 5:

      //變速,1代表正常速度A

      //慢速0 //快速9

      //5 降調(diào)

      S=0.5;

      break;

      case 6:

      S=1;

      break;

      default:

      break;

      }

      while(a[i][0]&&pause)

      {

      num=key_in();

      if(num==12)

      {

      pause=0;

      }

      else

      {

      if(S == 0.5)

      m_sound(a[i][0]*S);

      else

      m_sound(a[i][0]);

      if(T==2)

      delay_ms(a[i][1]-100);

      else if(T==0)

      delay_ms(a[i][1]+100);

      else

      delay_ms(a[i][1]);

      i++;

      TCCR1A=0x00;

      TCCR1B=0X00;

      }

      }

      pause=0;

      //6 正常調(diào)

      //加減速

      //下一個(gè)音符; 第20頁(yè)

      北京郵電大學(xué)信息與通信工程學(xué)院

      TCCR1A=0x00;

      TCCR1B=0X00;

      //中斷,為下一個(gè)節(jié)拍做準(zhǔn)備;

      }

      if(a[i][1]==0){

      aim =(++aim)% list;

      } }

      /***************** 錄制音樂(lè)函數(shù); *****************/ void record(void){

      write_com(0X01);

      const uchar R_table[]=“Recording Mode”;

      for(int i=0;i<9;i++){

      write_dat(R_table[i]);}

      pause=1;while(pause){

      uint Skey = key_in();

      if((Skey>0)&&(Skey<11))

      {

      int i=0;//count=0;

      while(i<10)

      {

      Skey=key_in();

      OCR1A=0;

      TCCR1A=0x00;

      TCCR1B=0X00;

      if((Skey>0)&&(Skey<11))

      {

      play(Skey);

      Ssong[i][0]=tone[Skey];

      Ssong[i][1]=600;

      i++;

      delay_ms(20);

      }

      if(Skey==14)

      第21頁(yè)

      //清屏;//開(kāi)始錄制

      //先清零計(jì)數(shù)器

      //錄制完成,北京郵電大學(xué)信息與通信工程學(xué)院

      按D鍵結(jié)束錄制

      {

      i=10;

      }

      }

      pause=0;

      //借助 PAUSE 來(lái)標(biāo)記一下什么時(shí)候退出while

      } } } //***************************歌曲數(shù)據(jù) uint music_data[][2]= { {440,400},{440,400},{659,400},{659,400},{740,400},{740,400},{659,800}, {587,400},{587,400},{554,400},{554,400},{494,400},{494,400},{440,800}, {659,400},{659,400},{587,400},{587,400},{554,400},{554,400},{497,800}, {659,400},{659,400},{587,400},{587,400},{554,400},{554,400},{497,800}, {440,400},{440,400},{659,400},{659,400},{740,400},{740,400},{659,800}, {587,400},{587,400},{554,400},{554,400},{494,400},{494,400},{440,800}, {0,0} };

      // abcdefg

      uint music_1[][2]= {{262,400},{294,400},{330,400},{262,400},{262,400}, //樂(lè)譜 {294,400},{330,400},{262,400},{330,400},{349,400}, {392,800},{330,400},{349,400},{392,800},{392,300}, {440,100},{392,300},{349,100},{262,400},{392,400}, {440,300},{392,100},{349,300},{330,100},{262,400}, {294,400},{196,400},{262,400},{294,800},{196,400}, {262,400},{294,800},{0,0}};//music_1

      int main(void){

      INI_POTR();

      //初始化

      write_com(0X38);

      //顯示光標(biāo)等;

      write_com(0X01);

      //清屏;

      write_com(0X0f);

      //打開(kāi)光標(biāo);

      write_com(0X06);

      write_com(0X80+0X02);

      for(int i=0;i<8;i++)

      第22頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      {

      write_dat(table[i]);

      }

      write_com(0X80+0X11);

      delay_ms(5);

      while(1)

      {

      num = key_in();

      if(num==16)

      //模式選擇

      {

      if(state==1)

      state=0;

      else

      state=1;

      }

      放模式

      if(state==1)

      {

      (state==1)

      {

      switchaim()

      {

      case 0:

      music_play(music_data);

      break;

      case 1:

      music_play(Ssong);

      break;

      default:

      break;

      }while

      delay_ms(10);

      }

      }

      else if(num==11)

      //錄制模式;

      {

      record();

      delay_ms(10);

      }

      else

      {

      write_com(0X01);

      第23頁(yè)

      //播

      北京郵電大學(xué)信息與通信工程學(xué)院

      }

      const uchar Ptable[]=“playing Mode”;

      for(int i=0;i<7;i++)

      {

      write_dat(Ptable[i]);

      }

      while((num!=16)&&(num!=11))

      {

      play(num);

      num=key_in();

      }

      } }

      //彈奏模式

      5.7實(shí)驗(yàn)結(jié)果:

      實(shí)現(xiàn)了最初設(shè)想的功能,所設(shè)計(jì)的電子琴可以進(jìn)行即興彈奏、錄制音樂(lè)、播放音樂(lè)以及音樂(lè)變速。測(cè)試圖片如下:

      第24頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      第25頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      接通電源后,顯示屏以每次顯示一個(gè)字符的形式顯示出“HELLO WELCOM!”的歡迎文字,接著自動(dòng)進(jìn)入彈奏模式,并在LCD的第一行顯示出“Playing Mode”的文字,用戶每次按下按鍵都會(huì)在LCD的第二行的相應(yīng)位置出現(xiàn)對(duì)應(yīng)按鍵順序的光標(biāo)閃爍。在彈奏模式下,按下F鍵會(huì)進(jìn)入播放模式,LCD顯示出“Music Mode”字樣,此時(shí)按下D鍵是播放/繼續(xù),按下B鍵是暫停,C鍵和E鍵分別代表上一首和下一首,9鍵則是將音樂(lè)速度調(diào)整為慢速,再次按下F鍵會(huì)回到彈奏模式。在彈奏模式下,按下A鍵會(huì)進(jìn)入錄制模式,此時(shí)LCD顯示“Recording Mode”字樣,可以使用1~0十個(gè)按鍵進(jìn)行錄音,想要聽(tīng)聽(tīng)錄制好的音樂(lè),可以切換到播放模式下進(jìn)行欣賞。

      六、排錯(cuò)過(guò)程:

      ? 基礎(chǔ)題目訓(xùn)練階段:

      1.硬件連接好之后,在進(jìn)行編程的過(guò)程中發(fā)現(xiàn)端口不夠用,因?yàn)镻B3和PD3這兩個(gè)能產(chǎn)生中斷的端口必須空出來(lái)作為暫停和開(kāi)

      第26頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      始按鍵的接口,于是我重新布線,將數(shù)碼管顯示小數(shù)點(diǎn)的右下角的引腳改接到PC0,同時(shí)在代碼中將此端口設(shè)置為高電平輸出,這樣就解決了該問(wèn)題。

      2.當(dāng)我們簡(jiǎn)單地把流水燈和計(jì)時(shí)器代碼合并在一起然后編譯運(yùn)行時(shí),卻發(fā)現(xiàn)流水燈在工作,計(jì)時(shí)器卻停止了工作。經(jīng)過(guò)仔細(xì)排查,發(fā)現(xiàn)簡(jiǎn)單地將代碼合并會(huì)導(dǎo)致單片機(jī)陷入流水燈的工作循環(huán),而沒(méi)有進(jìn)入計(jì)時(shí)器的工作進(jìn)程。經(jīng)過(guò)一番思考,我們將流水燈的代碼加以修改寫(xiě)入計(jì)時(shí)器的工作循環(huán)中,解決了計(jì)時(shí)器不工作的問(wèn)題。

      3.但是新問(wèn)題又出現(xiàn)了,我們發(fā)現(xiàn)按下計(jì)時(shí)器的暫停按鈕后,會(huì)導(dǎo)致流水燈也停止工作。經(jīng)過(guò)小組的討論,我們決定在中斷程序函數(shù)里面加上流水燈工作的代碼并加以修改使其能夠在中斷函數(shù)里面運(yùn)行。經(jīng)過(guò)多次調(diào)試,終于實(shí)現(xiàn)了計(jì)時(shí)器的計(jì)時(shí)、暫停、繼續(xù)功能,并且流水燈能夠一直工作不受計(jì)時(shí)器的暫停影響。

      4.在調(diào)整計(jì)時(shí)器計(jì)時(shí)精讀的過(guò)程中,我們發(fā)現(xiàn)本實(shí)驗(yàn)中使用的ATmega16頻率不是16MHz,也不是1MHz,為了盡可能的實(shí)現(xiàn)秒表計(jì)時(shí),試驗(yàn)了很多的數(shù)字組合,最后達(dá)到了30秒誤差1秒的精確度,當(dāng)然還可以達(dá)到更高的精確度。

      ? 電子琴設(shè)計(jì)與實(shí)現(xiàn)階段:

      1.在硬件連接的時(shí)候,沒(méi)想到LCD液晶顯示屏的每根管腳都需要

      第27頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      連接,導(dǎo)致在進(jìn)行程序下載驗(yàn)證的時(shí)候,顯示屏總是不能顯示出應(yīng)有的文字,后來(lái)參考了相關(guān)文檔資料發(fā)現(xiàn)是V0這個(gè)管腳也必須接地才可以,解決了問(wèn)題。

      2.在安插矩陣鍵盤(pán)的時(shí)候,費(fèi)了很多功夫,首先,不知道哪根管腳是行線哪根管腳是列線,其次不知道所連接的端口的輸出輸入模式應(yīng)該怎么設(shè)置,導(dǎo)致設(shè)計(jì)過(guò)程受阻,后來(lái)觀看了視頻并查閱相關(guān)資料解決了此問(wèn)題。

      3.在初步完成電子琴的彈奏功能程序時(shí),我們開(kāi)始對(duì)單片機(jī)進(jìn)行測(cè)試,發(fā)現(xiàn)在按下數(shù)次按鈕后單片機(jī)就會(huì)卡死,我們仔細(xì)檢查了彈奏功能的代碼,經(jīng)過(guò)多次排查,我們小組最終將鍵盤(pán)檢測(cè)函數(shù)key_in()和彈奏函數(shù)play()兩條語(yǔ)句的執(zhí)行順序交換,以達(dá)到比較好的邏輯順序效果,提高了程序的穩(wěn)定性,把多次按下按鈕會(huì)導(dǎo)致單片機(jī)卡死的問(wèn)題給基本解決了。

      4.播放音樂(lè)功能也是我們?cè)O(shè)想的一個(gè)重要功能。剛開(kāi)始,按照我們的思路去實(shí)現(xiàn)該功能時(shí),在測(cè)試時(shí)播放音樂(lè)是實(shí)現(xiàn)了,但是暫停和繼續(xù)功能都沒(méi)能夠?qū)崿F(xiàn)。我們小組對(duì)代碼進(jìn)行重新檢查,檢查出幾個(gè)比較嚴(yán)重的邏輯錯(cuò)誤。我們重新調(diào)整播放音樂(lè)函數(shù)的判斷語(yǔ)句和循環(huán)結(jié)構(gòu),并加入一個(gè)pause變量來(lái)標(biāo)志暫停狀態(tài),在按下暫停按鈕時(shí)將pause標(biāo)志為0,使程序退出播放循環(huán)。經(jīng)過(guò)一番努力,我們順利完成了暫停播放和繼續(xù)播放的功能。

      5.錄制音樂(lè)功能的實(shí)現(xiàn)是整個(gè)實(shí)驗(yàn)過(guò)程里面最為困難的一環(huán)。我第28頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      們預(yù)先設(shè)想的實(shí)現(xiàn)方法是每按下一個(gè)按鍵,將對(duì)應(yīng)音階的數(shù)字和節(jié)拍存入數(shù)組中,然后錄制完成后自動(dòng)播放錄制的音樂(lè)。但是,我們實(shí)際測(cè)試時(shí)發(fā)現(xiàn)錄制的音樂(lè)并沒(méi)有能自動(dòng)播放。經(jīng)過(guò)小組討論,我們決定將錄制好的音樂(lè)在播放音樂(lè)模式里面播放,根據(jù)這個(gè)思路,我們將錄制的音樂(lè)對(duì)應(yīng)的數(shù)組用播放音樂(lè)函數(shù)進(jìn)行播放,成功地實(shí)現(xiàn)了錄制音樂(lè)并播放的功能。

      七、心得體會(huì):

      為期9天的單片機(jī)小學(xué)期圓滿結(jié)束,不得不說(shuō),我從中學(xué)到了很多知識(shí),從一個(gè)對(duì)單片機(jī)一竅不通的小白,蛻變成了一個(gè)熟悉單片機(jī)各個(gè)端口的作用和使用方法、懂得如何編程實(shí)現(xiàn)相應(yīng)功能的技術(shù)人員。

      在這九天中,我們通過(guò)觀看老師給的視頻資料和文檔,加上查閱的資料,獨(dú)立完成了所布置的任務(wù)。由于有C++的基礎(chǔ),加上有硬件的端口以及相應(yīng)設(shè)備的使用說(shuō)明文檔的幫助,因此在我看來(lái),在AVR Studio上進(jìn)行C語(yǔ)言的編程從邏輯上比C++更容易理解,所需要的只是在編程時(shí)將端口的配置和邏輯函數(shù)結(jié)合到一起,實(shí)現(xiàn)編寫(xiě)的函數(shù)對(duì)單片機(jī)端口以及內(nèi)部中斷的控制。

      第一天剛接到流水燈和數(shù)碼管秒表計(jì)時(shí)器的任務(wù)的時(shí)候,內(nèi)心真的十分激動(dòng),心想:實(shí)現(xiàn)了這個(gè)不就實(shí)現(xiàn)了街邊廣告牌上滾動(dòng)的文字了么!但是一看到ATmega16芯片時(shí)還是傻了眼,心想:這么多的管腳都該怎么用???“視頻里有”,同學(xué)告訴我,于是我就開(kāi)始認(rèn)真地

      第29頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      研究起老師給的單片機(jī)教學(xué)視頻和它的技術(shù)文檔。由此發(fā)現(xiàn),只需要將單片機(jī)的端口設(shè)置好,再套上一個(gè)循環(huán)結(jié)構(gòu),就可以實(shí)現(xiàn)流水燈的功能了。說(shuō)做就做,于是最初的流水燈就實(shí)現(xiàn)了,可以一個(gè)一個(gè)依次循環(huán)點(diǎn)亮。那時(shí)真是好高興!在做數(shù)碼管的時(shí)候,由于不知道數(shù)碼管的顯示與管腳之間的關(guān)系,于是我先創(chuàng)建了一個(gè)數(shù)組,數(shù)組中的元素都是8位二進(jìn)制數(shù),其中只有一位是1,其余位都是0,如下:

      char a[8] = {

      0b00000001,0b00000010,0b00000100,0b00001000,0b00010000,0b00100000,0b01000000,0b10000000 };

      然后我采用一個(gè)循環(huán),將端口PORTX每次等于一個(gè)a[i],單步運(yùn)行,找出了數(shù)碼管的顯示與管腳之間的對(duì)應(yīng)關(guān)系。這樣,之后的工作就輕松許多,只需要在該亮的位置將對(duì)應(yīng)的PORTX端口置為1,就可以顯示出自己想要的數(shù)字了。流水燈和數(shù)碼管秒表計(jì)時(shí)器都分別完成了,最后只需將它們合在一起共同工作即可。不過(guò)這個(gè)過(guò)程也不是一帆風(fēng)順的,因?yàn)橹袛嗟母拍钗覄傞_(kāi)始覺(jué)得很難理解,也不知道該將中斷的有關(guān)函數(shù)放在代碼的哪個(gè)位置,因此反復(fù)糾結(jié)反復(fù)研究視頻和技術(shù)文檔,持續(xù)了一段時(shí)間。后來(lái)我和同學(xué)決定將兩份流水燈的程序,一份放在主程序main中,和秒表計(jì)時(shí)器的程序放在一起,即實(shí)現(xiàn)兩者同時(shí)工作,且流水燈的閃爍間隔是一秒,另一份放在中斷服務(wù)程序中SIGNAL()中,即實(shí)現(xiàn)按下按鈕進(jìn)入中斷服務(wù)程序后,秒表計(jì)時(shí)器暫停

      第30頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      工作,而流水依舊在依次循環(huán)閃爍。由此實(shí)現(xiàn)了流水燈和秒表計(jì)時(shí)器的獨(dú)立工作,互不影響。

      完成了基礎(chǔ)題目的訓(xùn)練任務(wù),我信心滿滿,迎來(lái)了我的下一個(gè)任務(wù)——電子琴。剛開(kāi)始選題的時(shí)候覺(jué)得電子琴蠻有趣的,可以彈奏可以錄音可以播放,而且原理看起來(lái)也比較簡(jiǎn)單。但是其實(shí)不是這樣的,拿到元器件的時(shí)候,我發(fā)現(xiàn),LCD液晶顯示屏有16個(gè)管腳!矩陣鍵盤(pán)有8個(gè)管腳!但是有了前面對(duì)付ATmega16芯片的經(jīng)驗(yàn),我沉住氣,查閱了有關(guān)LCD液晶顯示屏和矩陣鍵盤(pán)的技術(shù)文檔,以及一些經(jīng)驗(yàn)之作,初步定下了鍵盤(pán)接到A端口,LCD的8個(gè)數(shù)據(jù)口接到B端口,D端口用于LCD的讀寫(xiě)控制使能端以及揚(yáng)聲器的輸入端。至此,硬件的連接工作就完成了,根據(jù)硬件的連接,我們開(kāi)始了程序的編寫(xiě)。鍵盤(pán)檢測(cè)函數(shù)、播放函數(shù)、液晶顯示函數(shù),彈奏功能,錄制功能??一步一步,一個(gè)完整的系統(tǒng)漸漸完善。由于有硬件,因此我們編寫(xiě)的程序可以馬上下載到板子里驗(yàn)證效果,并及時(shí)修改,大大方便了我們排錯(cuò)和系統(tǒng)優(yōu)化。期間由于JTAG下載器和AVR Studio總是出現(xiàn)連接失敗的情況,浪費(fèi)了我們?cè)S多寶貴的時(shí)間,個(gè)人總結(jié)原因是驅(qū)動(dòng)可能用了一段時(shí)間會(huì)失效,解決辦法是重新啟動(dòng)計(jì)算機(jī),并將WINAVR這個(gè)環(huán)境卸載后再次裝上,并且是裝到與上一次不同的盤(pán)中,同時(shí)編譯AVR程序的時(shí)候先接上JTAG下載器,試驗(yàn)了許多次,這個(gè)方法很管用,之后就沒(méi)有出現(xiàn)該問(wèn)題了。最終,電子琴的功能基本完成,并且達(dá)標(biāo),能實(shí)現(xiàn)彈奏、播放、錄制、變速等最初設(shè)想的功能,但是可能還有一些小BUG沒(méi)有調(diào)出來(lái),導(dǎo)致電子琴在運(yùn)行的過(guò)程中有不穩(wěn)定的現(xiàn)象,第31頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      也不能排除是板子的問(wèn)題。

      最終,單片機(jī)小學(xué)期圓滿結(jié)束了!9天的時(shí)間,完全的自己動(dòng)手實(shí)驗(yàn),不僅增加了自己對(duì)單片機(jī)的理解,提高了自己的編程能力,而且在這個(gè)過(guò)程中,我覺(jué)得團(tuán)隊(duì)的合作至關(guān)重要,自己連接的電路或者自己編寫(xiě)的程序,在自己看來(lái)都是對(duì)的,但是旁觀者清,隊(duì)友能很容易地幫你找出其中的錯(cuò)誤;在和隊(duì)友的討論中,我能了解對(duì)方的想法和思路,多種想法和思路的碰撞能讓我收獲更多新的東西;組內(nèi)的分工能讓每個(gè)人都盡到自己的責(zé)任,發(fā)揮自己所長(zhǎng)。

      總之,這次單片機(jī)小學(xué)期是一次難忘的過(guò)程,一次豐富知識(shí)、提升技能的歷程,也激起了我對(duì)單片機(jī)的興趣,我今后會(huì)多多研究單片機(jī),爭(zhēng)取更上一層樓!

      八、參考文獻(xiàn):

      1.AVR C庫(kù)函數(shù)介紹.pdf 2.AVR C語(yǔ)言開(kāi)發(fā)入門(mén)指導(dǎo).pdf 3.AVR單片機(jī)原理及應(yīng)用.pdf 4.AVR高速嵌入式單片機(jī)原理及應(yīng)用(修訂版).pdf 5.深入淺出AVR單片機(jī).pdf 6.1602液晶說(shuō)明.pdf 7.AVR系統(tǒng)板說(shuō)明.doc 8.cn_mega16-16L.pdf 9.EN_TC1602.pdf

      第32頁(yè) 北京郵電大學(xué)信息與通信工程學(xué)院

      10.字符手冊(cè).pdf 11.百度百科《樂(lè)理》

      12.AVR單片機(jī)軟硬件設(shè)計(jì)視頻教程-入門(mén)篇-第二講-AVR硬件電路設(shè)計(jì)教程

      13.AVR單片機(jī)軟硬件設(shè)計(jì)視頻教程-入門(mén)篇-第三講-AVR開(kāi)發(fā)基礎(chǔ)知識(shí)

      14.AVR單片機(jī)軟硬件設(shè)計(jì)視頻教程-入門(mén)篇-第四講-C語(yǔ)言的流水燈驗(yàn)證

      15.AVR單片機(jī)軟硬件設(shè)計(jì)視頻教程-入門(mén)篇-第五講-按鍵與數(shù)碼管的程序設(shè)計(jì)

      16.AVR單片機(jī)軟硬件設(shè)計(jì)視頻教程-入門(mén)篇-第六講-中斷與定時(shí)器

      九、意見(jiàn)與建議: 1.建議老師能稍微講解一下實(shí)驗(yàn)室AVR軟件的用法(視頻中講的是沒(méi)有JTAG下載器的,與實(shí)驗(yàn)室不同,剛開(kāi)始還以為是板子有問(wèn)題);

      2.實(shí)驗(yàn)室的元器件老舊,個(gè)別元器件特別是單片機(jī)芯片有問(wèn)題之后,調(diào)BUG好久都不知道錯(cuò)在哪里,建議更新。

      第33頁(yè)

      第二篇:北郵小學(xué)期c++實(shí)驗(yàn)報(bào)告

      面向?qū)ο蟪绦蛟O(shè)計(jì)與實(shí)踐

      c++實(shí)驗(yàn)總結(jié)報(bào)告

      ——網(wǎng)絡(luò)工程14班饒思哲 ——學(xué)號(hào):2013211574 實(shí)驗(yàn)一簡(jiǎn)單C++程序設(shè)計(jì) 1.猜價(jià)格游戲

      編寫(xiě)C++程序完成以下功能:

      (1)假定有一件商品,程序用隨機(jī)數(shù)指定該商品的價(jià)格(1-1000的整數(shù));

      (2)提示用戶猜價(jià)格,并輸入:若用戶猜的價(jià)格比商品價(jià)格高或低,對(duì)用戶作出相應(yīng)的提示;

      (3)直到猜對(duì)為止,并給出提示。

      題目1-1總結(jié):

      1)本題需要隨機(jī)生成整數(shù),我開(kāi)始只使用rand(),即price=rand();來(lái)生成隨機(jī)整數(shù)

      但這樣只是一個(gè)偽隨機(jī)函數(shù),每一次重新打開(kāi)程序生成的數(shù)都是一致的。因此加入時(shí)間隨機(jī)種子:srand((unsigned)time(NULL))2)個(gè)人改進(jìn)1:定義最大值最小值,在每次猜測(cè)數(shù)字時(shí)顯示應(yīng)猜的數(shù)字范圍,作為提示。

      想到這個(gè)是因?yàn)橛幸淮尾铝撕芏啾槎紱](méi)猜到,一時(shí)突然忘記猜到什么范圍,然后往前翻猜過(guò)的數(shù)字和大小感覺(jué)相當(dāng)麻煩,所以就添上了應(yīng)猜范圍,方便再一次猜數(shù)。3)個(gè)人改進(jìn)2:本來(lái)有一個(gè)判斷條件判斷生成的隨機(jī)數(shù)是不是1~1000范圍內(nèi),而后更進(jìn)為隨機(jī)生成整數(shù)對(duì)1000取余得到0~999整數(shù),再+1得到1~1000的整數(shù)。

      實(shí)驗(yàn)二類與對(duì)象 1.矩形

      編寫(xiě)C++程序完成以下功能:

      (1)定義一個(gè)Point類,其屬性包括點(diǎn)的坐標(biāo),提供計(jì)算兩點(diǎn)之間距離的方法;(2)定義一個(gè)矩形類,其屬性包括左上角和右下角兩個(gè)點(diǎn),提供計(jì)算面積的方法;(3)創(chuàng)建一個(gè)矩形對(duì)象,提示用戶輸入矩形左上角和右下角的坐標(biāo);(4)觀察矩形對(duì)象以及Point類成員的構(gòu)造函數(shù)與析構(gòu)函數(shù)的調(diào)用;(5)計(jì)算其面積,并輸出。

      題目2-1總結(jié):

      1)這一題是第一次用到class類的題目,開(kāi)始并不明白為何要定義class,然后還需要區(qū)分public和private。而后來(lái)去圖書(shū)館借了書(shū)看到c++最大特色就是可以封裝,定義私有屬性和公有函數(shù),以確保有些函數(shù)和參數(shù)不會(huì)被輕易訪問(wèn)到,降低錯(cuò)誤率。2)class類在最起初定義時(shí)總是在class Rectangle那一行報(bào)錯(cuò),經(jīng)查書(shū)發(fā)現(xiàn)class定義最后一個(gè)大括號(hào)后有分號(hào),開(kāi)始并沒(méi)有加上。

      3)起初在調(diào)用class中函數(shù)時(shí)用c調(diào)用的方式,沒(méi)有跟面向的對(duì)象結(jié)合,導(dǎo)致編譯出錯(cuò),而后從distance()改為p.distance()就正確了。

      4)計(jì)算兩點(diǎn)距離和面積運(yùn)用開(kāi)方和絕對(duì)值函數(shù),前面若沒(méi)有加頭文件math.h則會(huì)報(bào)錯(cuò)。5)輸入左上角右下角坐標(biāo)時(shí),若輸入不當(dāng),可能會(huì)出現(xiàn)面積為負(fù)值的情況,所以加上絕對(duì)值函數(shù)保證面積非負(fù)。

      6)起初不知道構(gòu)造函數(shù)和析構(gòu)函數(shù)的定義和用法,經(jīng)翻閱書(shū)籍和運(yùn)行程序得知構(gòu)造函數(shù)在創(chuàng)建對(duì)象時(shí)調(diào)用,可以有多個(gè)。而析構(gòu)函數(shù)則在釋放對(duì)象時(shí)調(diào)用,一般每一個(gè)class中都只有一個(gè)默認(rèn)析構(gòu)函數(shù)。且構(gòu)造函數(shù)與類名稱一致,析構(gòu)函數(shù)則在類名稱前加~。

      2.友元

      編寫(xiě)C++程序完成以下功能:

      (1)定義一個(gè)Boat和Car兩個(gè)類,他們都具有私用屬性——重量;

      (2)編寫(xiě)一個(gè)函數(shù),計(jì)算兩者的重量和。double TotalWeight(Boat& b, Car& c);

      題目2-3總結(jié):

      1)友元函數(shù):在兩個(gè)對(duì)象中都使用到時(shí),可以使用友元函數(shù),并在類外單獨(dú)定義。

      友元函數(shù)是允許在類外訪問(wèn)類中的任何成員的。開(kāi)始在類外單獨(dú)定義時(shí)跟類的成員函數(shù)單獨(dú)定義混淆,寫(xiě)成了double Boat::TotalWeight(),導(dǎo)致編譯錯(cuò)誤,而后發(fā)現(xiàn)友元函數(shù)直接用函數(shù)名和函數(shù)返回值類型定義即可,不需要加上class類的名稱。

      2)起初定義完class Boat和class Car后發(fā)現(xiàn)編譯錯(cuò)誤,在友元函數(shù)的聲明那一行出錯(cuò),而后發(fā)現(xiàn)在這行之前沒(méi)有定義Car類,于是將其在最開(kāi)頭聲明出來(lái),通過(guò)。

      3)起初并沒(méi)有加上boat和car類的構(gòu)造函數(shù)和析構(gòu)函數(shù),可是經(jīng)上網(wǎng)查閱,默認(rèn)構(gòu)造函數(shù)和析構(gòu)函數(shù)可以系統(tǒng)自動(dòng)生成,但析構(gòu)函數(shù)只能刪除成員指針,并不能釋放指針指向的空間,所以若沒(méi)有申請(qǐng)動(dòng)態(tài)內(nèi)存,析構(gòu)函數(shù)可不寫(xiě)出,若申請(qǐng),則需自行在析構(gòu)函數(shù)中delete。

      實(shí)驗(yàn)三數(shù)組與指針 1.矩陣

      (一)編寫(xiě)C++程序完成以下功能:

      (1)假定矩陣大小為4×5(整型數(shù)組表示);

      (2)定義矩陣初始化函數(shù),可以從cin中輸入矩陣元素;(3)定義矩陣輸出函數(shù),將矩陣格式化輸出到cout;

      (4)定義矩陣相加的函數(shù),實(shí)現(xiàn)兩個(gè)矩陣相加的功能,結(jié)果保存在另一個(gè)矩陣中;(5)定義矩陣相減的函數(shù),實(shí)現(xiàn)兩個(gè)矩陣相減的功能,結(jié)果保存在另一個(gè)矩陣中;(6)定義三個(gè)矩陣:A1、A2、A3;(7)初始化A1、A2;

      (8)計(jì)算并輸出:A3 = A1加A2,A3 = A1減A2。

      題目3-1總結(jié):

      1)起初在矩陣相加相減的賦值中所用語(yǔ)句為:m.matrix[i][j]=a.matrix[i][j]+b.matrix[i][j] 但是運(yùn)行程序發(fā)現(xiàn)m矩陣所有元素都是0。經(jīng)單步調(diào)試,發(fā)現(xiàn)并沒(méi)有賦值成功。經(jīng)查閱書(shū)籍,了解到this指針是指向類的對(duì)象的地址,便改用this->matrix[i][j]作為賦值對(duì)象,最后程序正確。

      2)個(gè)人改進(jìn):將行數(shù)列數(shù)在文件開(kāi)頭用define定義,可以隨時(shí)更改。

      3)經(jīng)多次調(diào)試后,程序運(yùn)行結(jié)果正確,但矩陣看起來(lái)非常混亂,因?yàn)椴](méi)有行列對(duì)齊,于是在打印矩陣中每列直接用table空格隔開(kāi),保證美觀。2.矩陣

      (二)編寫(xiě)C++程序完成以下功能:

      (1)假定矩陣大小為4×5(整型);

      (2)矩陣空間采用new動(dòng)態(tài)申請(qǐng),保存在指針中;

      (3)定義矩陣初始化函數(shù),可以從cin中輸入矩陣元素;(4)定義矩陣輸出函數(shù),將矩陣格式化輸出到cout;

      (5)定義矩陣相加的函數(shù),實(shí)現(xiàn)兩個(gè)矩陣相加的功能,結(jié)果保存在另一個(gè)矩陣中;(6)定義矩陣相減的函數(shù),實(shí)現(xiàn)兩個(gè)矩陣相減的功能,結(jié)果保存在另一個(gè)矩陣中;(7)動(dòng)態(tài)申請(qǐng)三個(gè)矩陣:A1、A2、A3;(8)初始化A1、A2;

      (9)計(jì)算并輸出A3 = A1加A2,A3 = A1減A2;(10)釋放矩陣空間。

      題目3-2總結(jié):

      1)與3-1題目的區(qū)別在int main中用new函數(shù)動(dòng)態(tài)申請(qǐng)內(nèi)存,然后析構(gòu)函數(shù)需要釋放申請(qǐng)的空間而不只是自動(dòng)刪除指向空間的指針。析構(gòu)函數(shù)如圖。

      一開(kāi)始并不知道該怎么動(dòng)態(tài)申請(qǐng)內(nèi)存,在c中使用malloc可是c++中并不一樣。經(jīng)查閱書(shū)籍,發(fā)現(xiàn)c++中申請(qǐng)釋放內(nèi)存用new和delete非常簡(jiǎn)便。2)指針調(diào)用類成員函數(shù)一開(kāi)始不知道該怎么寫(xiě),寫(xiě)成A1.input()結(jié)果編譯錯(cuò)誤。經(jīng)查閱書(shū)籍,得知指針調(diào)用成員函數(shù)需寫(xiě)成A1->input()的形式。

      3)在釋放動(dòng)態(tài)內(nèi)存時(shí),用到delete函數(shù)。但開(kāi)始的時(shí)候?qū)慸elete matrix時(shí)候會(huì)出問(wèn)題。上網(wǎng)查詢后得到以下delete用法。

      Delete用法:當(dāng)釋放內(nèi)部類型,如int double型時(shí),直接delete a 即可。若是釋放自己定義的class類型,需用delete[]matrix來(lái)釋放內(nèi)存。3.矩陣

      (三)編寫(xiě)C++程序完成以下功能:

      (1)用類來(lái)實(shí)現(xiàn)矩陣,定義一個(gè)矩陣的類,屬性包括:

      ? 矩陣大小,用 lines, rows(行、列來(lái)表示);

      ? 存貯矩陣的數(shù)組指針,根據(jù)矩陣大小動(dòng)態(tài)申請(qǐng)(new)。(2)矩陣類的方法包括:

      ? 構(gòu)造函數(shù),參數(shù)是矩陣大小,需要?jiǎng)討B(tài)申請(qǐng)存貯矩陣的數(shù)組; ? 析構(gòu)函數(shù),需要釋放矩陣的數(shù)組指針; ? 拷貝構(gòu)造函數(shù),需要申請(qǐng)和復(fù)制數(shù)組; ? 輸入,可以從cin中輸入矩陣元素; ? 輸出,將矩陣格式化輸出到cout; ? 矩陣相加的函數(shù),實(shí)現(xiàn)兩個(gè)矩陣相加的功能,結(jié)果保存在另一個(gè)矩陣類,但必須矩陣大小相同; ? 矩陣相減的函數(shù),實(shí)現(xiàn)兩個(gè)矩陣相減的功能,結(jié)果保存在另一個(gè)矩陣類,但必須矩陣大小相同。

      (3)定義三個(gè)矩陣:A1、A2、A3;(4)初始化A1、A2;

      (5)計(jì)算并輸出A3 = A1加A2,A3=A1減A2;

      (6)用new動(dòng)態(tài)創(chuàng)建三個(gè)矩陣類的對(duì)象:pA1、pA1、pA3;(7)初始化pA1、pA2;

      (8)計(jì)算并輸出pA3=pA1加pA2,pA3=pA1減pA2;(9)釋放pA1、pA1、pA3。

      題目3-3總結(jié):

      1)拿到這道題我認(rèn)為要定義一個(gè)矩陣類對(duì)象,其中包括3-1和3-2一樣的input函數(shù),print函數(shù),plus函數(shù),subtract函數(shù),還有新增的構(gòu)造函數(shù)析構(gòu)函數(shù)。一上來(lái)我認(rèn)為class中屬性不再是之前的某行某列的數(shù)值,而是行數(shù)和列數(shù)還有矩陣的頭指針。根據(jù)輸入的行數(shù)列數(shù)來(lái)申請(qǐng)內(nèi)存,再將數(shù)值存入不同的位置。然后在主函數(shù)中分為兩個(gè)部分,一個(gè)是直接創(chuàng)建對(duì)象,另一個(gè)是創(chuàng)建矩陣數(shù)組指針。

      2)第一部分跟前兩題類似,所以很快就調(diào)試完成并且得到了正確的結(jié)果,但是指針部分一直出現(xiàn)問(wèn)題。最開(kāi)始是三個(gè)矩陣分別申請(qǐng)內(nèi)存,這樣的后果就是要輸入三次行數(shù)和列數(shù)的數(shù)值,有可能出現(xiàn)行列數(shù)不相等的情況,給之后的加減操作帶來(lái)麻煩。因此想到讓A1矩陣申請(qǐng)內(nèi)存,而讓A2、A3矩陣都與A1相等,就可以避免多次輸入行列數(shù),且保證了矩陣大小相等。但這樣輸入第一個(gè)矩陣數(shù)值后,矩陣元素獲取正常??僧?dāng)輸入第二個(gè)矩陣的數(shù)值以后,A1和A2矩陣的元素都變?yōu)榈诙€(gè)矩陣的元素,即第一個(gè)矩陣的元素被覆蓋掉。導(dǎo)致和矩陣為第二個(gè)矩陣的2倍,差矩陣都是零。經(jīng)過(guò)反復(fù)調(diào)試,曾經(jīng)試過(guò)將含參構(gòu)造函數(shù)中輸入行列數(shù)改到主函數(shù)中,再給A1申請(qǐng)動(dòng)態(tài)內(nèi)存。但是因?yàn)锳2和A3還是初始化跟A1相等,結(jié)果并沒(méi)有改變,還是錯(cuò)誤的。而后想到用含參構(gòu)造函數(shù)來(lái)申請(qǐng)動(dòng)態(tài)內(nèi)存,輸入固定的行列數(shù)后,用確定的行列數(shù)來(lái)new Matrix(x,y),這樣一來(lái)不僅矩陣大小相等,而且也不會(huì)存在前一個(gè)矩陣的值被后一個(gè)覆蓋掉的問(wèn)題。經(jīng)過(guò)調(diào)試,終于得到了正確的結(jié)果。

      3)調(diào)試過(guò)程中我了解到指針初始化和賦值過(guò)程中是容易發(fā)生樹(shù)脂覆蓋的,所以盡量不要將指針初始化成跟某個(gè)指針相等。

      實(shí)驗(yàn)四繼承與派生

      1、形狀

      (一)編寫(xiě)C++程序完成以下功能:

      (1)聲明一個(gè)基類Shape(形狀),其中包含一個(gè)方法來(lái)計(jì)算面積;(2)從Shape派生兩個(gè)類矩形和圓形;(3)從矩形派生正方形;

      (4)分別實(shí)現(xiàn)派生類構(gòu)造函數(shù)、析構(gòu)函數(shù)和其他方法;

      (5)創(chuàng)建派生類的對(duì)象,觀察構(gòu)造函數(shù)、析構(gòu)函數(shù)調(diào)用次序;(6)不同對(duì)象計(jì)算面積。

      題目4-1總結(jié):

      1)這一題主要是函數(shù)的派生方法使用,經(jīng)過(guò)查閱書(shū)籍,得知在class定義后加上:: public(基類名稱)便是作為一個(gè)派生類的定義,可以沿用基類中的成員函數(shù)。

      2)并且經(jīng)過(guò)對(duì)構(gòu)造函數(shù)和析構(gòu)函數(shù)調(diào)用,得知是先調(diào)用基類的構(gòu)造函數(shù),再調(diào)用派生類的構(gòu)造函數(shù)創(chuàng)建派生類對(duì)象,在程序結(jié)束時(shí),先調(diào)用派生類的析構(gòu)函數(shù)釋放派生類對(duì)象,再調(diào)用基類的析構(gòu)函數(shù)釋放基類對(duì)象。

      2、形狀

      (二)——虛函數(shù)(1)將【形狀

      (一)】中的基類計(jì)算面積的方法定義為虛函數(shù),比較與【形狀

      (一)】程序的差異;

      (2)將【形狀

      (一)】中的基類定義抽象類,比較與【形狀

      (一)】程序的差異。

      題目4-2總結(jié):

      1)起初并不知道虛函數(shù)的作用,后來(lái)經(jīng)過(guò)查閱書(shū)籍得知在基類中定義虛函數(shù),是為了在派生類中定義這一函數(shù)的不同操作方式。并且起初只改變了基類中area函數(shù),在其前面加了virtual,但并沒(méi)有體現(xiàn)出虛函數(shù)的運(yùn)用。而后看到書(shū)上虛函數(shù)的應(yīng)用,發(fā)現(xiàn)虛函數(shù)是可以讓一個(gè)基類指針調(diào)用派生類相應(yīng)函數(shù)的。于是經(jīng)過(guò)改進(jìn),在主函數(shù)中定義了3個(gè)基類指針,分別指向派生矩形類對(duì)象、派生圓形類對(duì)象、派生正方形對(duì)象,然后并非通過(guò)對(duì)象名稱調(diào)用成員函數(shù),而是用基類指針調(diào)用派生類中的area函數(shù),充分體現(xiàn)出對(duì)虛函數(shù)的應(yīng)用。

      2)這一題雖然跟上一題相似,但卻因?yàn)檫\(yùn)用了虛函數(shù)而變得不同。這一題讓我對(duì)虛函數(shù)有了更加深入的了解。也了解到調(diào)用類中的成員函數(shù)不一定非要用對(duì)象名或者對(duì)象指針調(diào)用,也可以用其基類的指針通過(guò)虛函數(shù)調(diào)用。

      實(shí)驗(yàn)五多態(tài)性

      1、對(duì)Point類重載++和――運(yùn)算符

      編寫(xiě)C++程序完成以下功能:

      (1)Point類的屬性包括點(diǎn)的坐標(biāo)(x,y);(2)實(shí)現(xiàn) Point類重載++和――運(yùn)算符:

      ? ++p,--p,p++,p--。

      ? ++和――分別表示x,y增加或減少1。

      題目5-1總結(jié):

      1)對(duì)于符號(hào)的重載開(kāi)始并不理解什么意思,后來(lái)得知是重新定義一下++、--操作的過(guò)程,包括自加自減和賦值。

      2)通過(guò)這一道題,對(duì)于自加符號(hào)的前后置的區(qū)別又有了更深的印象。起初在—p和++p的時(shí)候都只是將x和y加一,并沒(méi)有賦值,導(dǎo)致在主函數(shù)中寫(xiě)q=++p和q=--p時(shí)q保持原值,造成結(jié)果錯(cuò)誤。單步調(diào)試后發(fā)現(xiàn)這一錯(cuò)誤,及時(shí)改正過(guò)來(lái)。3)程序結(jié)果正確后編寫(xiě)菜單界面,使其操作步驟更加清晰明了。實(shí)驗(yàn)六流式IO

      1、流式IO

      (一)編寫(xiě)C++程序完成以下功能:

      (1)使用ofstream向一個(gè)文本文件中輸出各種類型的數(shù)據(jù),并打開(kāi)文件觀察結(jié)果:

      ? 整數(shù)、無(wú)符號(hào)整型、長(zhǎng)整型、浮點(diǎn)型、字符串、……

      (2)用十進(jìn)制、八進(jìn)制、十六進(jìn)制方式向文本文件中輸出整數(shù);(3)使用控制符和成員函數(shù)來(lái)控制輸出的格式:

      ? set()precision()...題目6-1總結(jié):

      1)文件流主要是向文件中輸入信息和從文件讀取信息。而跟c語(yǔ)言不同的是c需要fopen來(lái)打開(kāi)一個(gè)文件,而c++中只需要用fstream函數(shù)。且文件輸入方式也比c語(yǔ)言簡(jiǎn)便很多。2)轉(zhuǎn)換進(jìn)制開(kāi)始想到的是用數(shù)學(xué)的方法算出不同進(jìn)制下的數(shù)值,再輸入文件中,但非常的麻煩。后經(jīng)查閱書(shū)籍,看到有指定進(jìn)制的函數(shù),可以用來(lái)修改默認(rèn)的十進(jìn)制:oct和hex。3)最后程序正確后,編輯menu顯示菜單,使操作更加清晰明了。

      2、流式

      (三)編寫(xiě)C++程序完成以下功能:(1)輸入一個(gè)文本文件名;

      (2)打開(kāi)文件名,在該文件的每一行前面加上一個(gè)行號(hào),保存在另外一個(gè)文本文件中。

      題目6-3總結(jié):

      1)因?yàn)榈谝活}流式已經(jīng)嘗試過(guò)向文件中輸入信息,而經(jīng)過(guò)翻閱書(shū)籍得知從文件中可以用getline整行讀取字符串,便可以輕易的將文件內(nèi)容加上行數(shù),并輸出到另一個(gè)文本文件中。

      2)本題我覺(jué)得最大的困難在于輸入文本文件名,并打開(kāi)文件名。書(shū)上也并沒(méi)有關(guān)于打開(kāi)文件名的相關(guān)資料,于是上網(wǎng)查詢,發(fā)現(xiàn)可以用string.h中的c_str()函數(shù)來(lái)獲取鍵盤(pán)輸入的文件名字符串,并打開(kāi)文件名。

      3)因?yàn)槲募幚聿](méi)有在屏幕上有所顯示,為了讓每一步操作更加明了,在復(fù)制完一行后會(huì)在屏幕上打出某某行復(fù)制成功,使程序運(yùn)行過(guò)程更清晰。實(shí)驗(yàn)七 C++程序設(shè)計(jì)應(yīng)用

      1、電話本

      編寫(xiě)C++程序完成以下功能:

      (1)實(shí)現(xiàn)簡(jiǎn)單電話本功能,用姓名來(lái)搜索電話號(hào)碼;(2)用戶輸入姓名,程序查找并輸出結(jié)果;(3)用戶可以通過(guò)輸入,添加姓名和電話號(hào)碼;(4)用戶可以刪除姓名和電話號(hào)碼;(5)電話本可以保存在指定文件中;(6)電話可被從指定文件中讀入到內(nèi)存。

      題目7-1總結(jié):

      1)電話本分為幾大部分:讀到內(nèi)存、輸出到文件、新增聯(lián)系人、刪除聯(lián)系人、查找聯(lián)系人。因?yàn)槭亲x到內(nèi)存,就想到了可以用數(shù)組或者鏈表來(lái)構(gòu)成電話本的框架。而這兩種方式在c語(yǔ)言用過(guò),所以邏輯方便很熟悉,于是選擇了比較簡(jiǎn)便的數(shù)組,這樣不易出現(xiàn)指針錯(cuò)誤的情況。

      2)個(gè)人改進(jìn)1: 新增聯(lián)系人函數(shù)中,就是將聯(lián)系人信息從鍵盤(pán)逐項(xiàng)讀入,然后選擇將聯(lián)系人插入到什么位置。若一共6個(gè)聯(lián)系人,插入位置輸入3,則插入第三個(gè)位置,后面的聯(lián)系人依次向后移一位。但若是一共6個(gè)聯(lián)系人,插入位置輸入8,則會(huì)提醒輸入位置不當(dāng),直接將聯(lián)系人插入到最后一個(gè)位置,即第七。

      3)刪除、查找、修改函數(shù)中都用到了用姓名查找,于是將其單獨(dú)摘出來(lái)定義findposition,找到聯(lián)系人位置。起初寫(xiě)的是將輸入的字符串逐個(gè)跟name比較,即a == name,但卻發(fā)現(xiàn)這樣程序查找出來(lái)聯(lián)系人永遠(yuǎn)不存在。經(jīng)上網(wǎng)查閱,發(fā)現(xiàn)字符串相等不能直接像字符一樣用==來(lái)判斷,而是用><來(lái)判斷,于是將其改為>=&&<=。但一開(kāi)始由于疏忽,將&&且關(guān)系寫(xiě)成||或關(guān)系,導(dǎo)致查找出來(lái)永遠(yuǎn)是第一個(gè)聯(lián)系人。后來(lái)單步調(diào)試發(fā)現(xiàn)錯(cuò)誤,改正過(guò)來(lái)。

      4)個(gè)人改進(jìn)2: 刪除、查找、修改中,若是聯(lián)系人不存在,需要輸出提示。而我另外又加了一句,并不是說(shuō)不存在就直接返回,而是讓用戶自己選擇是繼續(xù)輸入姓名還是返回主菜單。也讓手誤的時(shí)候不再把前面的操作進(jìn)行一遍,留有手誤的余地。5)修改聯(lián)系人模塊,一開(kāi)始class類中只有setPhone函數(shù),并沒(méi)有setname,setmobile等等,而是直接將所有屬性值組合起來(lái)構(gòu)建聯(lián)系人。這樣的后果就是在修改聯(lián)系人的時(shí)候,只修改了一項(xiàng),但是并不能賦值進(jìn)去。表面上雖然修改了,可查找后發(fā)現(xiàn)聯(lián)系人的信息并沒(méi)有改變。后來(lái)將每一項(xiàng)信息都分別set,經(jīng)過(guò)調(diào)試最終結(jié)果正確。

      6)從指定文件將電話本讀入內(nèi)存,就跟實(shí)驗(yàn)6第三題的流式很相似,都是逐行讀取信息,只是讀取后是存入數(shù)組的不同屬性值中。開(kāi)始不知道該怎么確定文本文件中不再有聯(lián)系人信息,而后上網(wǎng)查資料發(fā)現(xiàn)當(dāng)文件中不再有信息可以讀的時(shí)候,infile>>name>>mobile…的值就是0,便可停止操作。而姓名等信息也可以逐個(gè)賦值到phone類數(shù)組里。

      7)個(gè)人改進(jìn)3: 電話本不需要手動(dòng)保存在指定文件中,主菜單也不再顯示這一操作,而是當(dāng)選擇退出電話本時(shí)自動(dòng)保存到輸出的output.txt中。

      8)最后程序執(zhí)行結(jié)果正確,編寫(xiě)menu菜單界面,美化界面并且讓操作編號(hào)更加清晰。

      第三篇:北郵單片機(jī)學(xué)習(xí)心得

      單片機(jī)學(xué)習(xí)心得

      電子工程學(xué)院

      其實(shí)就在不久前,我對(duì)單片機(jī)的認(rèn)識(shí)還只是停留在它是一塊能夠進(jìn)行有限運(yùn)算和控制的,小型化的,成本低的芯片還有一些外設(shè)口的集合,通常用于一些低端的家電產(chǎn)品,因?yàn)槲矣薪佑|過(guò)計(jì)算機(jī)軟件的設(shè)計(jì),例如運(yùn)用C語(yǔ)言、C++、Java語(yǔ)言開(kāi)發(fā)一些簡(jiǎn)單的小程序,在我的直觀印象里,單片機(jī)的運(yùn)用和程序設(shè)計(jì)應(yīng)該不會(huì)比計(jì)算機(jī)軟件的設(shè)計(jì)與開(kāi)發(fā)難,畢竟計(jì)算機(jī)比單片機(jī)要復(fù)雜得多。可是,當(dāng)我真正接觸到單片機(jī),真正觸碰并且嘗試讓它按照我的要求運(yùn)轉(zhuǎn)起來(lái)的時(shí)候,往往事與愿違,這時(shí)候開(kāi)始我才真正感受到單片機(jī)程序設(shè)計(jì)與開(kāi)始的看法大相近庭,也是從這時(shí)候起,我才算真正理解并且體會(huì)到單片機(jī)的魅力。

      單片機(jī)的誕生可以追朔到20實(shí)際70年代,在1970—1974年之間,誕生了第一代4位單片機(jī),這一類單片機(jī)就已經(jīng)具有了并行I/O(輸入輸出)接口以及一些常用的A/D(模擬信號(hào)到數(shù)字信號(hào)轉(zhuǎn)換)和D/A(數(shù)字信號(hào)到模擬信號(hào)轉(zhuǎn)換)等資源。隨后,潘多拉的盒子邊打開(kāi),人能認(rèn)識(shí)到單片機(jī)的潛在能力和市場(chǎng)價(jià)值,在1974—1978年,單片機(jī)進(jìn)入8位時(shí)代,此后,單片機(jī)進(jìn)入了高速發(fā)展的時(shí)代,在此后短短10年內(nèi),單片機(jī)的工作頻率、硬件資源和RAM/ROM容量等都有極大的突破,創(chuàng)新地加入了串口通信接口及多級(jí)中斷處理系統(tǒng),其中以Intel公司的MCS-51為代表,51系列單片機(jī)以其強(qiáng)大的可重復(fù)編程能力和高的性價(jià)比等優(yōu)點(diǎn)而得到廣泛的應(yīng)用,在家電產(chǎn)品,例如電視、電話、冰箱、空調(diào)、洗衣機(jī)、家用防盜報(bào)警器等,還有隨身影音設(shè)備,例如MP3、MP4、錄音筆等,以及電子玩具、幾點(diǎn)一體化設(shè)備、數(shù)據(jù)通信、測(cè)控設(shè)備等領(lǐng)域都能見(jiàn)到它的身,所以掌握單片機(jī)已經(jīng)成為學(xué)習(xí)、從事電子專業(yè)的必備能力。

      單片機(jī)的發(fā)展到現(xiàn)在,稱其為一個(gè)小型的計(jì)算機(jī)已經(jīng)一點(diǎn)也不為過(guò)了,單片機(jī)集成了一個(gè)計(jì)算機(jī)應(yīng)有的各個(gè)模塊,但是它的使用方法和計(jì)算機(jī)有著很大的區(qū)別,在學(xué)習(xí)之處,由于沒(méi)有注意到這一點(diǎn),而仍然簡(jiǎn)單的按照自己之前運(yùn)用C語(yǔ)言在計(jì)算機(jī)上編程的思想與方法去操作它,發(fā)現(xiàn)它就像不受控制一樣,完全不能按照自己程序設(shè)定的套路運(yùn)行,讓我很是頭疼,這個(gè)問(wèn)題困擾了我很久,知道我了解了單片機(jī)的工作原理之后。

      單片機(jī)雖然是“微型計(jì)算機(jī)”,但是它畢竟不是計(jì)算機(jī),它的編程方法自然與我們現(xiàn)在接觸到的計(jì)算機(jī)不同,單片機(jī)可以看成是一臺(tái)資源“極其”有限的計(jì)算機(jī),正由于這個(gè)原因,單片機(jī)的運(yùn)行機(jī)理和控制與普通的軟件編程有著天壤之別。

      首先,我第一個(gè)覺(jué)得單片機(jī)編程與計(jì)算機(jī)編程有著很大不同的是:?jiǎn)纹瑱C(jī)的系統(tǒng)時(shí)鐘,時(shí)鐘是單片機(jī)的生命,而在計(jì)算機(jī)軟件編程中,我們從來(lái)不用考慮時(shí)鐘這一回事,這讓我第一次接觸單片機(jī)編程時(shí)候很是茫然,時(shí)鐘它就像單片機(jī)的心臟,規(guī)定了單片機(jī)運(yùn)行的節(jié)拍,所以任何單片機(jī)程序編程的設(shè)計(jì)中,時(shí)鐘如何設(shè)置,應(yīng)該是首要考慮的事情,單片機(jī)的時(shí)鐘分為主系統(tǒng)時(shí)鐘、輔助系統(tǒng)時(shí)間、外部時(shí)鐘等,而且每一個(gè)模塊的時(shí)鐘都可以再經(jīng)過(guò)分頻器分頻產(chǎn)生各種不同的時(shí)鐘組合,時(shí)鐘的快慢直接影響到單片機(jī)的性能、運(yùn)行速度和精度,尤其是在采樣的時(shí)候,選擇一個(gè)合適的時(shí)鐘是我們得到可靠的采樣數(shù)據(jù)的最基礎(chǔ)的保障,也是讓單片機(jī)工作在一個(gè)既滿足工作需求又能節(jié)約能耗的基礎(chǔ)。

      再者,單片機(jī)的程序結(jié)構(gòu)也與計(jì)算機(jī)軟件程序結(jié)構(gòu)有著很大的不同,單片機(jī)的程序一般為初始化加上一個(gè)死循環(huán),這起初讓我很那一理解,一個(gè)死循環(huán),并且死循環(huán)里一般都沒(méi)有多少操作語(yǔ)句,這樣單片機(jī)怎么能完成那么強(qiáng)大的功能能呢,而且讓程序進(jìn)入一個(gè)死循環(huán),這在計(jì)算機(jī)編程中都是極力避免的,然后,后來(lái)才發(fā)現(xiàn)單片機(jī)程序主體結(jié)構(gòu)設(shè)計(jì)為這樣的奇妙之處,這也是單片機(jī)為何能被稱為低功耗,甚至超低功耗的原因,也是模塊化程序結(jié)構(gòu)的精華所在,而單片機(jī)如此美妙的締造者,就是它的:中斷。

      真正懂得單片機(jī)的人都稱,如果你不會(huì)用中斷,那么你就根本不會(huì)單片機(jī),單片機(jī)主程序里就是一個(gè)簡(jiǎn)單的死循環(huán),那么它是如何完成那么多強(qiáng)大的功能(例如A/D、D/A、計(jì)時(shí)、通信等)呢?這多虧了單片機(jī)的中斷機(jī)制,中斷的概念來(lái)自于現(xiàn)實(shí)生活,某人正在打掃房間,突然電話響了,這個(gè)人便要接電話,接完電話后再回來(lái)打掃房間。這個(gè)過(guò)程便是“執(zhí)行主程序(打掃房間)——中斷(電話響,接電話)——中斷返回(繼續(xù)打掃房間)”的過(guò)程,單單片機(jī)CPU正在執(zhí)行程序的過(guò)程中,如果外部硬件或內(nèi)部組件有緊急的請(qǐng)求,此時(shí)中斷系統(tǒng)可以將當(dāng)前的程序暫停,優(yōu)先處理中斷請(qǐng)求。當(dāng)中斷請(qǐng)求處理完畢的時(shí)候,再返回來(lái)繼續(xù)執(zhí)行主程序。有了中斷系統(tǒng),便可以使單片機(jī)具備對(duì)外部的異步事件進(jìn)行處理的能力。所以,主程序雖然是個(gè)死循環(huán),但是每當(dāng)外界有中斷請(qǐng)求的時(shí)候,它就跳轉(zhuǎn)到中斷程序中去執(zhí)行,所以我們看到,大部分,也是最主要的程序一般都位于中斷服務(wù)程序中,這樣,單片機(jī)的各個(gè)模塊既能單獨(dú)地并行地互不干擾地運(yùn)行,又能夠保證主程序順序執(zhí)行,這樣就發(fā)揮了模塊化程序設(shè)計(jì)思想的高效特點(diǎn),并且既充分利用了各個(gè)硬件的資源,又能減少能量損耗。

      最后,單片機(jī)中的對(duì)各個(gè)硬件資源的控制有嚴(yán)格的控制寄存器來(lái)控制,并且各個(gè)單片機(jī)都不同,所以在設(shè)計(jì)單片機(jī)并且運(yùn)用它的某些硬件功能的時(shí)候,一定要仔細(xì)閱讀單片機(jī)的用戶手冊(cè),充分了解各個(gè)控制寄存器的設(shè)定方法時(shí)候才能正確使用其硬件,并且還要時(shí)刻注意各個(gè)硬件之間的中斷的相互影響關(guān)系,否則程序運(yùn)行后極容易出現(xiàn)讓人不知所源的錯(cuò)誤。

      總之,在這一學(xué)期的51單片機(jī)的學(xué)習(xí)過(guò)程中,我對(duì)于單片機(jī)的編程思想以及方法有了初步的入門(mén),并且自己也動(dòng)手編寫(xiě)并且下載到單片機(jī)上運(yùn)行,雖然都是一些最簡(jiǎn)單的程序,但是對(duì)于我學(xué)習(xí)單片機(jī)的入門(mén)有極大的幫助,讓我有很大的收獲,同時(shí)也激起了我對(duì)單片機(jī)的濃厚興趣,單片機(jī)的強(qiáng)大功能一直讓我著迷,如何能夠使單片機(jī)在利用最少的硬件資源,能量資源的條件下完成我們所需要的功能,一直是讓許許多多電子工程師為之努力的方向,這也是我今后繼續(xù)學(xué)習(xí)單片機(jī)所要重視的方面。

      第四篇:北郵嵌入式實(shí)驗(yàn)報(bào)告

      北京郵電大學(xué)

      嵌入式系統(tǒng)開(kāi)發(fā)實(shí)驗(yàn)報(bào)告

      學(xué)院:

      班級(jí): 姓名: 學(xué)號(hào):

      序號(hào):

      目錄

      一、實(shí)驗(yàn)?zāi)康?.............................................................................................1

      二、實(shí)驗(yàn)設(shè)備..............................................................................................1

      三、基礎(chǔ)實(shí)驗(yàn)(實(shí)驗(yàn)一~實(shí)驗(yàn)七)............................................................1

      1.實(shí)驗(yàn)五..................................................................................................1 2.實(shí)驗(yàn)六..................................................................................................1 3.實(shí)驗(yàn)七..................................................................................................1

      四、驅(qū)動(dòng)程序..............................................................................................5

      1.設(shè)備驅(qū)動(dòng)程序的概念..........................................................................5 2.驅(qū)動(dòng)程序結(jié)構(gòu)......................................................................................6 3.設(shè)備注冊(cè)和初始化..............................................................................7 4.設(shè)備驅(qū)動(dòng)程序的開(kāi)發(fā)過(guò)程..................................................................8

      五、基本接口實(shí)驗(yàn)......................................................................................8

      1.實(shí)驗(yàn)十二簡(jiǎn)單設(shè)備驅(qū)動(dòng)程序..............................................................9 2.實(shí)驗(yàn)十三 CPU GPIO驅(qū)動(dòng)程序設(shè)計(jì)...................................................9 3.實(shí)驗(yàn)十四中斷實(shí)驗(yàn)...........................................................................10 4.實(shí)驗(yàn)十五數(shù)碼管顯示實(shí)驗(yàn)................................................................12 5.實(shí)驗(yàn)十六 LED點(diǎn)陣驅(qū)動(dòng)程序設(shè)計(jì)...................................................19 6.實(shí)驗(yàn)十七 AD驅(qū)動(dòng)實(shí)驗(yàn)....................................................................23 7.實(shí)驗(yàn)十八 DA驅(qū)動(dòng)實(shí)驗(yàn)....................................................................26

      六、實(shí)驗(yàn)中遇到的問(wèn)題及解決方法........................................................30

      七、實(shí)驗(yàn)總結(jié)及心得................................................................................31

      一、實(shí)驗(yàn)?zāi)康?/p>

      通過(guò)實(shí)驗(yàn)熟悉Linux環(huán)境,并掌握一些基本接口驅(qū)動(dòng)的寫(xiě)法和用C語(yǔ)言編寫(xiě)簡(jiǎn)單的實(shí)驗(yàn)程序。學(xué)習(xí)LINUX開(kāi)發(fā)環(huán)境的搭建,通訊配置等。并熟練掌握LINUX驅(qū)動(dòng)程序的編寫(xiě)及開(kāi)發(fā)流程。對(duì)嵌入式系統(tǒng)有進(jìn)一步的了解。

      二、實(shí)驗(yàn)設(shè)備

      1.一套PXA270EP嵌入式實(shí)驗(yàn)箱

      2.安裝Redhat9的宿主PC機(jī),并且配置好ARM Linux的開(kāi)發(fā)環(huán)境

      三、基礎(chǔ)實(shí)驗(yàn)(實(shí)驗(yàn)一~實(shí)驗(yàn)七)

      實(shí)驗(yàn)一~七為基礎(chǔ)實(shí)驗(yàn),目的是為后續(xù)實(shí)驗(yàn)搭建好軟、硬件環(huán)境,配置好相關(guān)的協(xié)議、服務(wù),并通過(guò)編寫(xiě)最簡(jiǎn)單的HelloWorld程序進(jìn)行測(cè)試。由于后面的實(shí)驗(yàn)都要依靠前面實(shí)驗(yàn)的配置,故本段只著重?cái)⑹鰧?shí)驗(yàn)七的具體實(shí)現(xiàn)。

      1.實(shí)驗(yàn)五

      實(shí)驗(yàn)五為宿主PC機(jī)配置了TFTP服務(wù)。TFTP(Trivial File Transfer Protocol)是簡(jiǎn)單文件傳輸協(xié)議,由于特定開(kāi)發(fā)環(huán)境的制約,這一服務(wù)是必須的。在配置完成后,每次重啟宿主PC機(jī)時(shí),都須先輸入命令:service xinetd restart,以啟動(dòng)TFTP服務(wù)。

      2.實(shí)驗(yàn)六

      實(shí)驗(yàn)六為宿主PC機(jī)配置了NFS服務(wù)。NFS(Network File System)指網(wǎng)絡(luò)文件系統(tǒng),它實(shí)現(xiàn)了文件在不同的系統(tǒng)間使用。當(dāng)我們想用遠(yuǎn)端檔案時(shí),只需調(diào)用“mount”就可以遠(yuǎn)端系統(tǒng)掛接在自己的檔案系統(tǒng)之下。每次重啟宿主PC機(jī)時(shí),都須先輸入命令:service nfs restart,以啟動(dòng)nfs服務(wù)。

      3.實(shí)驗(yàn)七

      實(shí)驗(yàn)七通過(guò)用c語(yǔ)言編寫(xiě)的簡(jiǎn)單程序HelloWorld,測(cè)試前面幾個(gè)實(shí)驗(yàn)是否成功配置好環(huán)境,從超級(jí)終端可以看到HelloWorld程序的運(yùn)行結(jié)果。

      實(shí)驗(yàn)步驟如下: 1)硬件連接:

      連接宿主 PC 機(jī)和一臺(tái) PXA270-RP目標(biāo)板。2)打開(kāi)宿主PC 機(jī)電源,進(jìn)入 Linux操作系統(tǒng)。

      3)啟動(dòng)RedHat 9.0 的圖形界面,如下圖,若您是以 root 身份登陸在文本模式下,則輸入命令startx啟動(dòng)圖形界面。進(jìn)入RedHat 9.0 圖形界面后,打開(kāi)一個(gè)終端窗(Terminal)。

      4)輸入minicom然后回車,minicim設(shè)置為115200 8NI無(wú)流控。

      5)打開(kāi)PXA270_RP目標(biāo)板電源,按目標(biāo)板上的BOOT鍵,在minicom中應(yīng)該會(huì)看到如下圖:

      6)在minicom終端窗口中,如圖,輸入下列四條命令 root ifconfig eth 192.168.0.50 up mount-o nolock 192.168.0.100:/ /mnt cd /mnt 此時(shí),先將該窗口最小化,在后面的第 10 操作步驟中還將會(huì)回到該窗口中進(jìn)行操作。

      7)宿主機(jī)上打開(kāi)一個(gè)終端窗口(Terminal),點(diǎn)擊【紅帽/System Tools/Terminal】啟動(dòng)終端窗口,輸入下列 4 條命令: ① cd /home

      ②mkdir HW

      ③ cd HW

      ④ vi

      HelloWorld.c

      /*請(qǐng)您輸入程序 7.1 程序清單*/

      此時(shí)會(huì)顯示一個(gè)空白的屏幕,這條命令的含義是,使用 Vi 編輯器,對(duì)一個(gè)名叫HelloWorld.c的文件進(jìn)行編輯,我們看到的空白窗口是對(duì)文件進(jìn)行編輯的窗口,如下圖。就像在 Windows系統(tǒng)下面使用寫(xiě)字板等一樣道理。

      在 vi 里面先單擊鍵盤(pán) A 鍵,然后左下角會(huì)變成—INSER。輸入程序的時(shí)候和其他編輯器是一樣的,如下圖。

      當(dāng)輸入程序完畢后,單擊鍵盤(pán) Esc 鍵,然后按“:”(冒號(hào))此時(shí)左下角會(huì)出現(xiàn)冒號(hào)然后輸入“wq”最后按“Enter”確認(rèn)存盤(pán)退出 vi 編輯器,如下圖。

      8)在上面同一個(gè)終端窗口中,輸入下列 2 條命令交叉編譯HelloWorld.c源程序,并查看生成的.o 目標(biāo)文件,如圖 7-10,圖7-11: ①

      arm-linux-gcc–oHelloWorldHelloWorld.c ②ls 等到再次出現(xiàn)提示符,代表程序已經(jīng)正確編譯。如果此步出現(xiàn)錯(cuò)誤信息,請(qǐng)查看錯(cuò)誤信息,并且重新編輯原來(lái)的 C文件,修改錯(cuò)誤。直到正確編譯。

      9)重新打開(kāi)第 7 步最小化的開(kāi)有minicom的終端窗口,即到 PXA270-RP 目標(biāo)板的mnt目錄下,請(qǐng)您輸入下列 3 條命令,運(yùn)行HelloWorld編譯成功的HelloWorld目標(biāo)程序:

      ① cd home/HW

      /*回到minicom中目標(biāo)板的/mnt/home/HW目錄下*/ ②ls ③./ HelloWorld

      /*此時(shí)會(huì)看到如下圖*/

      四、驅(qū)動(dòng)程序

      1.設(shè)備驅(qū)動(dòng)程序的概念

      設(shè)備驅(qū)動(dòng)程序?qū)嶋H是處理和操作硬件控制器的軟件,從本質(zhì)上講,是內(nèi)核中具有最高特權(quán)級(jí)的、駐留內(nèi)存的、可共享的底層硬件處理例程。驅(qū)動(dòng)程序是內(nèi)核的一部分,是操作系統(tǒng)內(nèi)核與硬件設(shè)備的直接接口,驅(qū)動(dòng)程序屏蔽了硬件的細(xì)節(jié),完成以下功能:

      ?對(duì)設(shè)備初始化和釋放;

      ?對(duì)設(shè)備進(jìn)行管理,包括實(shí)時(shí)參數(shù)設(shè)置,以及提供對(duì)設(shè)備的操作接口; ?讀取應(yīng)用程序傳送給設(shè)備文件的數(shù)據(jù)或者回送應(yīng)用程序請(qǐng)求的數(shù)據(jù); ?檢測(cè)和處理設(shè)備出現(xiàn)的錯(cuò)誤。

      Linux操作系統(tǒng)將所有的設(shè)備全部看成文件,并通過(guò)文件的操作界面進(jìn)行操作。對(duì)用戶程序而言,設(shè)備驅(qū)動(dòng)程序隱藏了設(shè)備的具體細(xì)節(jié),對(duì)各種不同設(shè)備提供了一致的接口,一般來(lái)說(shuō),是把設(shè)備映射為一個(gè)特殊的設(shè)備文件,用戶程序可以像對(duì)其他文件一樣對(duì)此設(shè)備文件進(jìn)行操作。這意味著:

      ?由于每一個(gè)設(shè)備至少由文件系統(tǒng)的一個(gè)文件代表,因而都有一個(gè)“文件名”。?應(yīng)用程序通常可以通過(guò)系統(tǒng)調(diào)用open()打開(kāi)設(shè)備文件,建立起與目標(biāo)設(shè)備的連接。

      ?打開(kāi)了代表著目標(biāo)設(shè)備的文件,即建立起與設(shè)備的連接后,可以通過(guò)read()、write()、ioctl()等常規(guī)的文件操作對(duì)目標(biāo)設(shè)備進(jìn)行操作。

      設(shè)備文件的屬性由三部分信息組成:第一部分是文件的類型,第二部分是一個(gè)主設(shè)備號(hào),第三部分是一個(gè)次設(shè)備號(hào)。其中類型和主設(shè)備號(hào)結(jié)合在一起惟一地確定了設(shè)備文件驅(qū)動(dòng)程序及其界面,而次設(shè)備號(hào)則說(shuō)明目標(biāo)設(shè)備是同類設(shè)備中的第幾個(gè)。

      由于Linux 中將設(shè)備當(dāng)做文件處理,所以對(duì)設(shè)備進(jìn)行操作的調(diào)用格式與對(duì)文件的操作類似,主要包括open()、read()、write()、ioctl()、close()等。應(yīng)用程序發(fā)出系統(tǒng)調(diào)用命令后,會(huì)從用戶態(tài)轉(zhuǎn)到核心態(tài),通過(guò)內(nèi)核將open()這樣的系統(tǒng)調(diào)用轉(zhuǎn)換成對(duì)物理設(shè)備的操作。

      2.驅(qū)動(dòng)程序結(jié)構(gòu)

      一個(gè)設(shè)備驅(qū)動(dòng)程序模塊的基本框架

      在系統(tǒng)內(nèi)部,I/O設(shè)備的存取通過(guò)一組固定的入口點(diǎn)來(lái)進(jìn)行,入口點(diǎn)也可以理解為設(shè)備的句柄,就是對(duì)設(shè)備進(jìn)行操作的基本函數(shù)。字符型設(shè)備驅(qū)動(dòng)程序提供如下幾個(gè)入口點(diǎn):

      ?

      open入口點(diǎn)。打開(kāi)設(shè)備準(zhǔn)備I/O操作。對(duì)字符設(shè)備文件進(jìn)行打開(kāi)操作,都會(huì)調(diào)用設(shè)備的open入口點(diǎn)。open子程序必須對(duì)將要進(jìn)行的I/O操作做好必要的準(zhǔn)備工作,如清除緩沖區(qū)等。如果設(shè)備是獨(dú)占的,即同一時(shí)刻只能有一個(gè)程序訪問(wèn)此設(shè)備,則open子程序必須設(shè)置一些標(biāo)志以表示設(shè)備處于忙狀態(tài)。

      ?

      close入口點(diǎn)。關(guān)閉一個(gè)設(shè)備。當(dāng)最后一次使用設(shè)備完成后,調(diào)用close子程序。獨(dú)占設(shè)備必須標(biāo)記設(shè)備方可再次使用。

      ?

      read入口點(diǎn)。從設(shè)備上讀數(shù)據(jù)。對(duì)于有緩沖區(qū)的I/O操作,一般是從緩沖區(qū)里讀數(shù)據(jù)。對(duì)字符設(shè)備文件進(jìn)行讀操作將調(diào)用read子程序。

      ?

      write入口點(diǎn)。往設(shè)備上寫(xiě)數(shù)據(jù)。對(duì)于有緩沖區(qū)的I/O操作,一般是把數(shù)據(jù)寫(xiě)入緩沖區(qū)里。對(duì)字符設(shè)備文件進(jìn)行寫(xiě)操作將調(diào)用write子程序。

      ?ioctl入口點(diǎn)。執(zhí)行讀、寫(xiě)之外的操作。

      select入口點(diǎn)。檢查設(shè)備,看數(shù)據(jù)是否可讀或設(shè)備是否可用于寫(xiě)數(shù)據(jù)。select系統(tǒng)調(diào)用在檢查與設(shè)備文件相關(guān)的文件描述符時(shí)使用select入口點(diǎn)。

      3.設(shè)備注冊(cè)和初始化

      設(shè)備的驅(qū)動(dòng)程序在加載的時(shí)候首先需要調(diào)用入口函數(shù)init_module(),該函數(shù)最重要的一個(gè)工作就是向內(nèi)核注冊(cè)該設(shè)備,對(duì)于字符設(shè)備調(diào)用register_chrdev()完成注冊(cè)。register_chrdev的定義為:intregister_chrdev(unsigned int major, const char *name, struct file_ operations *fops);其中,major是為設(shè)備驅(qū)動(dòng)程序向系統(tǒng)申請(qǐng)的主設(shè)備號(hào),如果為0,則系統(tǒng)為此驅(qū)動(dòng)程序動(dòng)態(tài)分配一個(gè)主設(shè)備號(hào)。name是設(shè)備名,fops是對(duì)各個(gè)調(diào)用的入口點(diǎn)說(shuō)明。此函數(shù)返回0時(shí)表示成功;返回-EINVAL,表示申請(qǐng)的主設(shè)備號(hào)非法,主要原因是主設(shè)備號(hào)大于系統(tǒng)所允許的最大設(shè)備號(hào);返回-EBUSY,表示所申請(qǐng)的主設(shè)備號(hào)正在被其他設(shè)備程序使用。如果動(dòng)態(tài)分配主設(shè)備號(hào)成功,此函數(shù)將返回所分配的主設(shè)備號(hào)。如果register_chrdev()操作成功,設(shè)備名就會(huì)出現(xiàn)在/proc/dvices文件中。

      Linux在/dev目錄中為每個(gè)設(shè)備建立一個(gè)文件,用ls–l命令列出函數(shù)返回值,若小于0,則表示注冊(cè)失??;返回0或者大于0的值表示注冊(cè)成功。注冊(cè)以后,Linux將設(shè)備名與主、次設(shè)備號(hào)聯(lián)系起來(lái)。當(dāng)有對(duì)此設(shè)備名的訪問(wèn)時(shí),Linux通過(guò)請(qǐng)求訪問(wèn)的設(shè)備名得到主、次設(shè)備號(hào),然后把此訪問(wèn)分發(fā)到對(duì)應(yīng)的設(shè)備驅(qū)動(dòng),設(shè)備驅(qū)動(dòng)再根據(jù)次設(shè)備號(hào)調(diào)用不同的函數(shù)。

      當(dāng)設(shè)備驅(qū)動(dòng)模塊從Linux內(nèi)核中卸載,對(duì)應(yīng)的主設(shè)備號(hào)必須被釋放。字符設(shè)備在cleanup_ module()函數(shù)中調(diào)用unregister_chrdev()來(lái)完成設(shè)備的注銷。unregister_chrdev()的定義為:intunregister_chrdev(unsigned int major, const char *name);包括設(shè)備注冊(cè)在內(nèi),設(shè)備驅(qū)動(dòng)的初始化函數(shù)主要完成的功能是有以下5項(xiàng)。(1)對(duì)驅(qū)動(dòng)程序管理的硬件進(jìn)行必要的初始化。

      對(duì)硬件寄存器進(jìn)行設(shè)置。比如,設(shè)置中斷掩碼,設(shè)置串口的工作方式、并口的數(shù)據(jù)方向等。

      (2)初始化設(shè)備驅(qū)動(dòng)相關(guān)的參數(shù)。

      一般說(shuō)來(lái),每個(gè)設(shè)備都要定義一個(gè)設(shè)備變量,用以保存設(shè)備相關(guān)的參數(shù)。在這一步驟里對(duì)設(shè)備變量中的項(xiàng)進(jìn)行初始化。

      (3)在內(nèi)核注冊(cè)設(shè)備。

      調(diào)用register_chrdev()函數(shù)來(lái)注冊(cè)設(shè)備。(4)注冊(cè)中斷。

      如果設(shè)備需要IRQ支持,則要使用request_irq()函數(shù)注冊(cè)中斷。(5)其他初始化工作。

      初始化部分一般還負(fù)責(zé)給設(shè)備驅(qū)動(dòng)程序申請(qǐng)包括內(nèi)存、時(shí)鐘、I/O端口等在內(nèi)的系統(tǒng)資源,這些資源也可以在open子程序或者其他地方申請(qǐng)。這些資源不用時(shí),應(yīng)該釋放,以利于資源的共享。

      若驅(qū)動(dòng)程序是內(nèi)核的一部分,初始化函數(shù)則要按如下方式聲明: int __initchr_driver_init(void);其中__init是必不可少的,在系統(tǒng)啟動(dòng)時(shí)會(huì)由內(nèi)核調(diào)用chr_driver_init,完成驅(qū)動(dòng)程序的初始化。

      當(dāng)驅(qū)動(dòng)程序是以模塊的形式編寫(xiě)時(shí),則要按照如下方式聲明: intinit_module(void)當(dāng)運(yùn)行后面介紹的insmod命令插入模塊時(shí),會(huì)調(diào)用init_module函數(shù)完成初始化工作。

      4.設(shè)備驅(qū)動(dòng)程序的開(kāi)發(fā)過(guò)程

      由于嵌入式設(shè)備由于硬件種類非常豐富,在默認(rèn)的內(nèi)核發(fā)布版中不一定包括所有驅(qū)動(dòng)程序。所以進(jìn)行嵌入式Linux系統(tǒng)的開(kāi)發(fā),很大的工作量是為各種設(shè)備編寫(xiě)驅(qū)動(dòng)程序。除非系統(tǒng)不使用操作系統(tǒng),程序直接操縱硬件。嵌入式Linux系統(tǒng)驅(qū)動(dòng)程序開(kāi)發(fā)與普通Linux開(kāi)發(fā)沒(méi)有區(qū)別??梢栽谟布a(chǎn)廠家或者Internet上尋找驅(qū)動(dòng)程序,也可以根據(jù)相近的硬件驅(qū)動(dòng)程序來(lái)改寫(xiě),這樣可以加快開(kāi)發(fā)速度。實(shí)現(xiàn)一個(gè)嵌入式Linux設(shè)備驅(qū)動(dòng)的大致流程如下。

      (1)查看原理圖,理解設(shè)備的工作原理。一般嵌入式處理器的生產(chǎn)商提供參考電路,也可以根據(jù)需要自行設(shè)計(jì)。

      (2)定義設(shè)備號(hào)。設(shè)備由一個(gè)主設(shè)備號(hào)和一個(gè)次設(shè)備號(hào)來(lái)標(biāo)識(shí)。主設(shè)備號(hào)惟一標(biāo)識(shí)了設(shè)備類型,即設(shè)備驅(qū)動(dòng)程序類型,它是塊設(shè)備表或字符設(shè)備表中設(shè)備表項(xiàng)的索引。次設(shè)備號(hào)僅由設(shè)備驅(qū)動(dòng)程序解釋,區(qū)分被一個(gè)設(shè)備驅(qū)動(dòng)控制下的某個(gè)獨(dú)立的設(shè)備。

      (3)實(shí)現(xiàn)初始化函數(shù)。在驅(qū)動(dòng)程序中實(shí)現(xiàn)驅(qū)動(dòng)的注冊(cè)和卸載。(4)設(shè)計(jì)所要實(shí)現(xiàn)的文件操作,定義file_operations結(jié)構(gòu)。(5)實(shí)現(xiàn)所需的文件操作調(diào)用,如read、write等。

      (6)實(shí)現(xiàn)中斷服務(wù),并用request_irq向內(nèi)核注冊(cè),中斷并不是每個(gè)設(shè)備驅(qū)動(dòng)所必需的。

      (7)編譯該驅(qū)動(dòng)程序到內(nèi)核中,或者用insmod命令加載模塊。(8)測(cè)試該設(shè)備,編寫(xiě)應(yīng)用程序,對(duì)驅(qū)動(dòng)程序進(jìn)行測(cè)試。

      五、基本接口實(shí)驗(yàn)

      在完成了基本實(shí)驗(yàn)后,我們開(kāi)始著手基本接口實(shí)驗(yàn)。在這些實(shí)驗(yàn)中,我們學(xué)習(xí)如何編寫(xiě)設(shè)備驅(qū)動(dòng)程序,及如何用測(cè)試程序檢驗(yàn)驅(qū)動(dòng)程序是否正確,并通過(guò)改寫(xiě)測(cè)試程序正常地對(duì)驅(qū)動(dòng)程序進(jìn)行相關(guān)操作。

      1.實(shí)驗(yàn)十二 簡(jiǎn)單設(shè)備驅(qū)動(dòng)程序

      本次實(shí)驗(yàn)的任務(wù)是編寫(xiě)一個(gè)字符型設(shè)備驅(qū)動(dòng)程序,并學(xué)習(xí)在應(yīng)用程序中調(diào)用驅(qū)動(dòng)??紤]到我們初次接觸驅(qū)動(dòng)程序的編寫(xiě),對(duì)此還十分陌生,因此指導(dǎo)書(shū)中提供了本次實(shí)驗(yàn)所要用到的程序源代碼。雖然這樣一個(gè)字符型設(shè)備驅(qū)動(dòng)程序并沒(méi)有任何實(shí)際作用,但是它讓我們輕松掌握了嵌入式驅(qū)動(dòng)的編寫(xiě)過(guò)程,因?yàn)閺?fù)雜繁瑣的驅(qū)動(dòng),其骨架都是相同的。因此,看懂本實(shí)驗(yàn)的源代碼,學(xué)習(xí)并模仿其編寫(xiě)方法,對(duì)于后續(xù)實(shí)驗(yàn)有著非常重要的意義。

      2.實(shí)驗(yàn)十三 CPU GPIO驅(qū)動(dòng)程序設(shè)計(jì)

      在本實(shí)驗(yàn)中,我們要編寫(xiě)第一個(gè)針對(duì)實(shí)際硬件的驅(qū)動(dòng)程序。我們知道,凡是操作系統(tǒng)控制外部設(shè)備,即使是最簡(jiǎn)單的硬件電路,也是需要驅(qū)動(dòng)的。本實(shí)驗(yàn)涉及的外部硬件只有電阻和發(fā)光二極管。我們使用自己編寫(xiě)的驅(qū)動(dòng)程序與應(yīng)用程序控制 GPIO96的電平,通過(guò) LED 的亮滅來(lái)判斷,是否 CPU 做出了正確的響應(yīng)。

      補(bǔ)充代碼(1)

      //-------------------WRITE-----------------------ssize_tSIMPLE_GPIO_LED_write(struct file * file ,const char * buf, size_t count, loff_t * f_ops){ #ifdef OURS_GPIO_LED_DEBUG printk(“SIMPLE_GPIO_LED_write [--kernel--]n”);

      #endif

      return count;}

      補(bǔ)充代碼(2)

      //-------------------OPEN------------------------ssize_tSIMPLE_GPIO_LED_open(structinode * inode ,struct file * file){ #ifdef OURS_GPIO_LED_DEBUG printk(“SIMPLE_GPIO_LED_open [--kernel--]n”);

      #endif

      MOD_INC_USE_COUNT;

      return 0;}

      補(bǔ)充代碼(3)

      //------------------structfile_operationsGPIO_LED_ctl_ops ={ open:SIMPLE_GPIO_LED_open, read:SIMPLE_GPIO_LED_read, write:SIMPLE_GPIO_LED_write, ioctl:SIMPLE_GPIO_LED_ioctl, release:SIMPLE_GPIO_LED_release, };實(shí)驗(yàn)作業(yè)

      要求在目標(biāo)板上LED閃爍產(chǎn)生亮7秒,滅2秒的效果 在測(cè)試程序中有這樣一段代碼: while(1){ ioctl(fd,LED_OFF);sleep(1);

      sleep(1);while(1){ ioctl(fd,LED_OFF);sleep(2);

      sleep(7);} 3.實(shí)驗(yàn)十四

      中斷實(shí)驗(yàn)

      // 滅2秒 // 亮7秒 ioctl(fd,LED_ON);}

      // 休眠1秒

      ioctl(fd,LED_ON);只需將上面的代碼改為如下代碼即可:

      在理論課中,我們學(xué)習(xí)了許多中斷方面的知識(shí),包括中斷向量、中斷優(yōu)先級(jí)、中斷過(guò)程等。在PXA270系統(tǒng)里,中斷控制器分外部設(shè)備和 PXA270X 處理器設(shè)備產(chǎn)生的兩個(gè)層次的中斷,前者是初級(jí)的中斷源,后者是次級(jí)中斷源,大量的次級(jí)中斷源通常被映射為一個(gè)初級(jí)中斷源。

      補(bǔ)充代碼1 voidshowversion(void){ printk(“*********************************************n”);

      printk(“t %s tn”, VERSION);

      printk(“*********************************************nn”);

      } static intSimpleINT_temp_count = 0;補(bǔ)充代碼2 //-------------------READ------------------------ssize_tSIMPLE_INT_read(struct file * file ,char * buf, size_t count, loff_t * f_ops){

      #ifdef OURS_INT_DEBUG

      #endif return count;printk(“SIMPLE_INT_read [--kernel--]n”);} 補(bǔ)充代碼3 //-------------------WRITE-----------------------ssize_tSIMPLE_INT_write(struct file * file ,const char * buf, size_t count, loff_t * f_ops){

      #ifdef OURS_INT_DEBUG

      } 補(bǔ)充代碼4 //------------------structfile_operationsINT_ctl_ops ={ open: SIMPLE_INT_open, read: SIMPLE_INT_read, #endif return count;printk(“SIMPL_INT_write [--kernel--]n”);write:SIMPLE_INT_write, ioctl:SIMPLE_INT_ioctl, release:SIMPLE_INT_release, };

      通過(guò)此實(shí)驗(yàn),我了解了硬件中斷管腳與中斷號(hào)的對(duì)應(yīng)關(guān)系,以及中斷號(hào)與中斷處理程序的對(duì)應(yīng)關(guān)系,對(duì)于今后編寫(xiě)更為復(fù)雜的中斷程序打下基礎(chǔ)。

      4.實(shí)驗(yàn)十五

      數(shù)碼管顯示實(shí)驗(yàn)

      在此實(shí)驗(yàn)中,我們要編寫(xiě)針對(duì) 74LV164 的驅(qū)動(dòng)程序,并用其串并轉(zhuǎn)換功能來(lái)控制八段LED數(shù)碼管的顯示。

      補(bǔ)充代碼1 voidshowversion(void){ printk(“*********************************************n”);

      printk(“t %s tn”, VERSION);

      printk(“*********************************************nn”);

      } 補(bǔ)充代碼2 //-------------------READ------------------------ssize_tSERIAL_LED_read(struct file * file ,char * buf, size_t count, loff_t * f_ops){ #ifdef OURS_HELLO_DEBUG

      } 補(bǔ)充代碼3 //-------------------WRITE-----------------------ssize_tSERIAL_LED_write(struct file * file ,const char * buf, size_t count, loff_t * f_ops)return count;printk(“SERIAL_LED_read [--kernel--]n”);#endif { #ifdef OURS_HELLO_DEBUG

      } 補(bǔ)充代碼4 //-------------------IOCTL-----------------------ssize_tSERIAL_LED_ioctl(structinode * inode ,struct file * file, unsigned intcmd, long data){ #ifdef OURS_HELLO_DEBUG

      #endif

      } 補(bǔ)充代碼5 //-------------------OPEN------------------------ssize_tSERIAL_LED_open(structinode * inode ,struct file * file){ #ifdef OURS_HELLO_DEBUG

      #endif

      return 0;} MOD_INC_USE_COUNT;printk(“SERIAL_LED_open [--kernel--]n”);return 0;printk(“SERIAL_LED_ioctl [--kernel--]n”);return count;#endif write_byte(* buf);printk(“SERIAL_LED_write [--kernel--]n”);補(bǔ)充代碼6 //-------------------RELEASE/CLOSE---------------ssize_tSERIAL_LED_release(structinode *inode ,struct file * file){ #ifdef OURS_HELLO_DEBUG

      printk(“SERIAL_LED_release [--kernel--]n”);

      #endif MOD_DEC_USE_COUNT;return 0;} 補(bǔ)充代碼7 //------------------structfile_operationsSERIAL_LED_ops ={ open: SERIAL_LED_open,read: SERIAL_LED_read,write:SERIAL_LED_write,ioctl:SERIAL_LED_ioctl,release:SERIAL_LED_release, };補(bǔ)充代碼8 staticint __initHW_SERIAL_LED_init(void){ int ret =-ENODEV;

      ret =

      devfs_register_chrdev(SERIAL_LED_MAJOR, &SERIAL_LED_ops);

      showversion();if(ret < 0)“serial_led_ctl”,} {

      } else { } return ret;printk(“ pxa270 serial_led_driver register success!![--kernel--]n”);printk(“ pxa270 init_module failed with %dn [--kernel--]”, ret);return ret;補(bǔ)充代碼9 staticint __init pxa270_SERIAL_LED_init(void){ int ret =-ENODEV;

      printk(“pxa270_SERIAL_LED_init [--kernel--]n”);

      #endif

      ret = HW_SERIAL_LED_init();if(ret)return ret;return 0;} 補(bǔ)充代碼10 static void __exit cleanup_SERIAL_LED(void){ #ifdef OURS_HELLO_DEBUG #ifdef OURS_HELLO_DEBUG

      #endif }

      補(bǔ)充代碼11 MODULE_DESCRIPTION(“serial_led driver module”);

      MODULE_AUTHOR(“l(fā)iduo”);

      MODULE_LICENSE(“GPL”);

      module_init(pxa270_SERIAL_LED_init);module_exit(cleanup_SERIAL_LED);使用測(cè)試程序看到的測(cè)試結(jié)果是數(shù)碼管按0-9顯示輸出。實(shí)驗(yàn)作業(yè)要求在上述基礎(chǔ)上,分別實(shí)現(xiàn)一下兩個(gè)功能:

      ①要求您再編寫(xiě)一個(gè)測(cè)試程序,實(shí)現(xiàn) PXA270-EP 目標(biāo)板上的 LED 數(shù)碼管循環(huán)顯示的數(shù)字9-0。

      ②要求您再編寫(xiě)一個(gè)測(cè)試程序,實(shí)現(xiàn) PXA270-EP 目標(biāo)板上的 LED 數(shù)碼管循環(huán)顯示的數(shù)字02468。

      由于在測(cè)試程序中定義了數(shù)組buf[10]分別存儲(chǔ)了0-9是個(gè)數(shù),因此上述功能的實(shí)現(xiàn)方法是,分別對(duì)測(cè)試程序做如下修改:

      原測(cè)試程序: while(1){ for(count=0;count<10;count++){ data[0] = buf[count];ret=write(fd,data,1);sleep(1);} } 實(shí)現(xiàn)功能①: while(1){ for(count=9;count>=0;count--)} } 結(jié)果顯示

      // 倒序顯示數(shù)字

      { data[0] = buf[count];ret=write(fd,data,1);sleep(1);devfs_unregister_chrdev(SERIAL_LED_MAJOR, “serial_led”);printk(“cleanup_SERIAL_LED [--kernel--]n”);實(shí)現(xiàn)功能②: while(1){ for(count=0;count<9;count=count+2)} } 結(jié)果顯示

      // 更改顯數(shù)順序

      { data[0] = buf[count];ret=write(fd,data,1);sleep(1);

      通過(guò)更改顯數(shù)的順序,很容易實(shí)現(xiàn)實(shí)驗(yàn)作業(yè)里要求的功能。

      5.實(shí)驗(yàn)十六 LED點(diǎn)陣驅(qū)動(dòng)程序設(shè)計(jì)

      通過(guò)本實(shí)驗(yàn)的操作,我們將 8X8 的點(diǎn)陣 LED 驅(qū)動(dòng)起來(lái)并通過(guò)編寫(xiě)測(cè)試程序,使其能夠按照您的意圖進(jìn)行顯示。要求您還編寫(xiě)更多的測(cè)試程序

      補(bǔ)充代碼1 voidshowversion(void){ printk(“*********************************************n”);printk(“t %s tn”, VERSION);printk(“*********************************************nn”);

      } 補(bǔ)充代碼2 //-------------------READ------------------------ssize_tSIMPLE_LED_read(struct file * file ,char * buf, size_t count, loff_t * f_ops){ #ifdef OURS_LED_DEBUG

      #endif return count;printk(“SIMPLE_LED_read [--kernel--]n”);} 補(bǔ)充代碼3 //-------------------IOCTL-----------------------ssize_tSIMPLE_LED_ioctl(structinode * inode ,struct file * file, unsigned intcmd, long data){

      #endif

      } 補(bǔ)充代碼4 //------------------structfile_operationsLED_ctl_ops ={ open: SIMPLE_LED_open, read:

      SIMPLE_LED_read, write: SIMPLE_LED_write, ioctl: SIMPLE_LED_ioctl, release:SIMPLE_LED_release, };補(bǔ)充代碼5 staticint __init pxa270_LED_CTL_init(void){ int ret =-ENODEV;

      printk(“pxa270_LED_CTL_init [--kernel--]n”);

      #endif

      ret = HW_LED_CTL_init();if(ret)

      return ret;#ifdef OURS_LED_DEBUG return 0;printk(“SIMPLE_LED_ioctl [--kernel--]n”);#ifdef OURS_LED_DEBUG return 0;} 補(bǔ)充代碼6 static void __exit cleanup_LED_ctl(void){

      #ifdef OURS_LED_DEBUG

      #endif

      } ①要求您再編寫(xiě)一個(gè)測(cè)試程序,實(shí)現(xiàn)按橫的方向隔行順序掃描 LED 點(diǎn)陣數(shù)碼管。

      ②要求您再編寫(xiě)一個(gè)測(cè)試程序,實(shí)現(xiàn)按豎的方向順序掃描 LED 點(diǎn)陣數(shù)碼管。作業(yè)一,隔行掃描:

      printk(“cleanup_LED_ctl [--kernel--]n”);outw(0x0000,ioremap_addr);

      devfs_unregister_chrdev(SIMPLE_LED_MAJOR, “l(fā)ed_ary_ctl”);for(i=1;i<=8;i2++){

      buf[0]=c;buf[1]=~r;// row for(j=1;j<=8;j++){

      } r = 1;c = c<<1;

      write(fd,buf,2);

      printf(“buf[0],buf[1]: [%x,%x]n”,buf[0],buf[1]);usleep(200000);// sleep 0.2 second r=r<<1;

      buf[1]=~r;// column

      結(jié)果顯示

      作業(yè)二,豎向掃描:

      for(i=1;i<=8;i++){

      buf[0]=c;buf[1]=~r;// row for(j=1;j<=8;j++){

      } r = 1;c = c<<1;

      write(fd,buf,2);

      printf(“buf[0],buf[1]: [%x,%x]n”,buf[0],buf[1]);usleep(200000);// sleep 0.2 second r=r<<1;

      buf[1]=~r;// column

      結(jié)果顯示

      6.實(shí)驗(yàn)十七 AD驅(qū)動(dòng)實(shí)驗(yàn)

      通過(guò)本實(shí)驗(yàn)的操作,我們將 AD 轉(zhuǎn)換器驅(qū)動(dòng)起來(lái)并通過(guò)編寫(xiě)測(cè)試程序,使其能夠?qū)⒛M信號(hào)量按照我們的要求轉(zhuǎn)換成數(shù)字信號(hào)量。為了更加清楚地理解 AD 轉(zhuǎn)換器的工作過(guò)程,請(qǐng)您再編寫(xiě)一個(gè)測(cè)試程序,將 UCB_ADC_INP_AD0 換成其他通道,來(lái)觀察其他 AD 通道情況。

      補(bǔ)充代碼1 voidshowversion(void){ printk(“%sn”,VERSION);} struct ucb1x00 *ad_ucb;

      補(bǔ)充代碼2 //-------------------READ------------------------staticssize_tadctl_read(struct file * file ,char *buf, size_t count, loff_t *offset){

      } 補(bǔ)充代碼3 //-------------------WRITE-----------------------ssize_tadctl_write(struct file * file ,const char *buf, size_t count, loff_t *offset){

      #ifdef OURS_HELLO_DEBUG printk(“writen”);

      #endif

      } 補(bǔ)充代碼4 //-------------------OPEN------------------------ssize_tadctl_open(structinode * inode ,struct file * file){

      #ifdef OURS_HELLO_DEBUG printk(“openn”);

      #endif

      }

      補(bǔ)充代碼5 //-------------------RELEASE/CLOSE---------------ssize_tadctl_release(structinode *inode ,struct file * file){

      #ifdef OURS_HELLO_DEBUG printk(“releasen”);

      #endif return 0;return 0;return count;#ifdef OURS_HELLO_DEBUG printk(“readn”);#endif return count;} 補(bǔ)充代碼6 staticstructfile_operationsadctl_ops = {

      };補(bǔ)充代碼7 //-------------------INIT------------------------staticint __initHW_AD_CTL_init(void){

      return ret;}

      補(bǔ)充代碼8 staticint __init pxa270_AD_CTL_init(void){ int ret =-ENODEV;#ifdef OURS_HELLO_DEBUG int ret =-ENODEV;ret = devfs_register_chrdev(ADCTL_MAJOR, “adctl”, &adctl_ops);showversion();ad_ucb=ucb1x00_get();if(ret < 0){

      } else { } adctl_dev_handle = devfs_register(NULL, “ad_ctl”, DEVFS_FL_DEFAULT, printk(“adctl driver register success!n”);printk(“fail %dn”,ret);return 0;read: ioctl: adctl_read, adctl_ioctl, write: adctl_write, open: adctl_open, release:adctl_release,ADCTL_MAJOR, 0, S_IFCHR, &adctl_ops, NULL);printk(“initn”);#endif ret=HW_AD_CTL_init();if(ret)}

      補(bǔ)充代碼9 static void __exit cleanup_AD_ctl(void){

      }

      7.實(shí)驗(yàn)十八 DA驅(qū)動(dòng)實(shí)驗(yàn)

      通過(guò)本實(shí)驗(yàn)的操作,我們使用示波器看到了通過(guò)DA轉(zhuǎn)換而輸出的波形。在此基礎(chǔ)上,要求試寫(xiě)一個(gè)實(shí)現(xiàn)輸出三角波的測(cè)試程序。

      補(bǔ)充代碼1 #include #include #include #include #include #include #include #include 補(bǔ)充代碼2 voidshowversion(void){ printk(“*****************************n”);#ifdef OURS_HELLO_DEBUG printk(“cleanupn”);#endif devfs_unregister_chrdev(ADCTL_MAJOR,“ad_ctl”);devfs_unregister(adctl_dev_handle);return ret;return 0;

      } printk(“t %st n”,VERSION);printk(“*****************************n”);static long ioremap_addr;補(bǔ)充代碼3 //-------------------READ------------------------ssize_tSIMPLE_DA_read(struct file * file ,char * buf, size_t count, loff_t * f_ops){ #ifdef OURS_DA_DEBUG

      } 補(bǔ)充代碼4 //-------------------WRITE-----------------------ssize_tSIMPLE_DA_write(struct file * file ,const char * buf, size_t count, loff_t * f_ops){

      printk(“SIMPLE_DA_write[--kernel--]n”);

      #endif

      return count;} 補(bǔ)充代碼5 //-------------------IOCTL-----------------------ssize_tSIMPLE_DA_ioctl(structinode * inode ,struct file * file, unsigned intcmd, outb(buf[0],ioremap_addr);#ifdef OURS_DA_DEBUG return count;#endif printk(“SIMPLE_DA_read[--kernel--]n”);long data){ #ifdef OURS_DA_DEBUG

      printk(“SIMPLE_DA_ioctl[--kernel--]n”);

      #endif return 0;} 補(bǔ)充代碼6 //-------------------OPEN------------------------ssize_tSIMPLE_DA_open(structinode * inode ,struct file * file){

      #ifdef OURS_DA_DEBUG printk(“SIMPLE_DA_open [--kernel--]n”);

      MOD_INC_USE_COUNT;return 0;

      #endif } 補(bǔ)充代碼7 /------------------structfile_operationsDA_ctl_ops ={

      read: SIMPLE_DA_read,};

      補(bǔ)充代碼8 release:

      SIMPLE_DA_release, ioctl:

      SIMPLE_DA_ioctl, write:

      SIMPLE_DA_write, //-------------------INIT------------------------staticint __initHW_DA_CTL_init(void){ int ret =-ENODEV;

      }

      補(bǔ)充代碼9 staticint __init pxa270_DA_CTL_init(void){ int ret =-ENODEV;

      printk(“pxa270_DA_CTL_init [--kernel--]n”);

      #endif #ifdef OURS_DA_DEBUG } printk(“ pxa270 led_driver register success!![--kernel--]n”);{ else } return ret;printk(“ pxa270: init_module failed with %dn [--kernel--]”, ret);{ if(ret < 0)showversion();ret = devfs_register_chrdev(SIMPLE_DA_MAJOR, “da_ctl”, &DA_ctl_ops);

      ret = HW_DA_CTL_init();if(ret)

      return ret;return 0;} 補(bǔ)充代碼10 static void __exit cleanup_DA_ctl(void){

      #endif } 補(bǔ)充代碼11 MODULE_DESCRIPTION(“DA_ctl driver module”);MODULE_AUTHOR(“l(fā)iduo”);MODULE_LICENSE(“GPL”);module_init(pxa270_DA_CTL_init);module_exit(cleanup_DA_ctl);printk(“cleanup_DA_ctl [--kernel--]n”);#ifdef OURS_DA_DEBUG

      六、實(shí)驗(yàn)中遇到的問(wèn)題及解決方法

      每一次上課重新啟動(dòng)后,當(dāng)需要將宿主PC機(jī)的根目錄掛在到PXA270-EP目標(biāo)板的mnt目錄下(即在超級(jí)終端中輸入命令“mount –o soft,timeo=100,rsize=1024 192.168.0.100:/ /mnt”)時(shí),常顯示無(wú)法掛載。

      解決方法:在超級(jí)終端下的掛載命令應(yīng)該用”mount –o nolock 192.168.0.100:/ /mnt”,如果依然不能掛載需要重啟NFS服務(wù),即在PC機(jī)終端中輸入命令”service nfs restart”兩遍后就可以掛載,當(dāng)然有時(shí)候也可能是因?yàn)榫W(wǎng)線沒(méi)插好。

      在每次重啟機(jī)器之后都需要將PC機(jī)終端的IP地址和開(kāi)發(fā)板中的系統(tǒng)的IP地址設(shè)定正確,不然也無(wú)法掛載。

      七、實(shí)驗(yàn)總結(jié)及心得

      本學(xué)期的所有實(shí)驗(yàn)均在宿主PC機(jī)與PXA270-EP目標(biāo)板上進(jìn)行。在實(shí)驗(yàn)中,我們先建立硬件實(shí)驗(yàn)平臺(tái),又建立主機(jī)軟件開(kāi)發(fā)環(huán)境,接著為實(shí)驗(yàn)進(jìn)行各項(xiàng)配置,最后完成了各個(gè)實(shí)驗(yàn)中的多種功能。值得注意的是,前期的硬件、軟件準(zhǔn)備必須完整無(wú)誤地實(shí)現(xiàn),后續(xù)的實(shí)驗(yàn)才能順利進(jìn)行。所以,打基礎(chǔ)的工作一定要仔細(xì)謹(jǐn)慎。后續(xù)實(shí)驗(yàn)中雖然給出了驅(qū)動(dòng)程序的框架,仍需要我們自己補(bǔ)充完整,并開(kāi)動(dòng)腦筋舉一反三,在原代碼的基礎(chǔ)上進(jìn)行一定修改以實(shí)現(xiàn)新的功能。

      通過(guò)這學(xué)期的實(shí)驗(yàn),我逐步完成了建立實(shí)驗(yàn)軟件開(kāi)發(fā)平臺(tái),搭建實(shí)驗(yàn)編譯軟件環(huán)境,在PC上編輯、編譯一個(gè)應(yīng)用程序,并且在嵌入式系統(tǒng)上運(yùn)行和調(diào)試它的過(guò)程。在實(shí)驗(yàn)中,不難發(fā)現(xiàn),編譯驅(qū)動(dòng)程序大體框架都是一樣的,比如里面的讀函數(shù)、寫(xiě)函數(shù)、ioctl函數(shù)、打開(kāi)、關(guān)閉以及函數(shù)模塊的初始化并且在超級(jí)終端上顯示出等。但所不同的是,要根據(jù)不同的實(shí)驗(yàn)要求修改名稱,并且對(duì)其中必要的部分進(jìn)行修改。

      除此之外,我認(rèn)為很多基礎(chǔ)知識(shí)對(duì)實(shí)驗(yàn)的進(jìn)行也起著非常大的作用,例如數(shù)碼管的顯示原理。在掌握了基礎(chǔ)知識(shí)之后,上機(jī)的過(guò)程會(huì)顯得相對(duì)簡(jiǎn)單,尤其是代碼框架已經(jīng)給出,我們所以需要做的就是根據(jù)需要稍作改動(dòng)來(lái)得到我們想要的結(jié)果。

      在實(shí)驗(yàn)過(guò)程中常常會(huì)遇到各種各樣的問(wèn)題,剛開(kāi)始時(shí)我不知如何是好,只能求助于老師和同學(xué),后來(lái)隨著實(shí)驗(yàn)的進(jìn)行,我對(duì)實(shí)驗(yàn)的內(nèi)容和虛擬機(jī)都有了一定的了解,遇到問(wèn)題時(shí)也可以靜下心來(lái)思考其原因,自己嘗試各種方法去解決問(wèn)題。整個(gè)實(shí)驗(yàn)讓我了解了一套完整的嵌入式系統(tǒng)驅(qū)動(dòng)程序開(kāi)發(fā)的全過(guò)程,學(xué)到的內(nèi)容非常豐富,相信在學(xué)習(xí)了這些內(nèi)容后,在今后的學(xué)習(xí)工作中接觸到類似內(nèi)容,我不會(huì)感到無(wú)從下手,而是能夠有條不紊。

      感謝老師的辛勤指導(dǎo)!

      第五篇:北郵數(shù)據(jù)庫(kù)實(shí)驗(yàn)報(bào)告

      數(shù)據(jù)庫(kù)實(shí)驗(yàn)報(bào)告

      (三)姓名:學(xué)號(hào):班級(jí):

      1.用Transact-SQL語(yǔ)句、數(shù)據(jù)導(dǎo)入、SQL Server Management Studio(企業(yè)管理器)輸入的方法對(duì)所給定的8張表的數(shù)據(jù)輸入到數(shù)據(jù)庫(kù)中。自行決定每張表的數(shù)據(jù)導(dǎo)入辦法,但每種方法各針對(duì)二或三張表。

      ? Transact-SQL語(yǔ)句: 導(dǎo)入department,student, student_course表。

      insertinto department select*from openrowset

      ('microsoft.jep.oledb.4.0','excel 5.0;hdr=yes;database=D:課件數(shù)據(jù)庫(kù)database2.xls',department$);

      insertinto student select*from openrowset

      ('microsoft.jep.oledb.4.0','excel 5.0;hdr=yes;database=D:課件數(shù)據(jù)庫(kù)database2.xls',student$);

      insertinto student_course select*from openrowset

      ('microsoft.jep.oledb.4.0','excel 5.0;hdr=yes;database=D:課件數(shù)據(jù)庫(kù)database2.xls',student_course$);

      ? 數(shù)據(jù)導(dǎo)入:

      操作:選中數(shù)據(jù)庫(kù)studentsdb,右鍵-任務(wù)-導(dǎo)入數(shù)據(jù)。導(dǎo)入book, class, course表。

      SQL Server Management Studio: 操作:右鍵需要編輯的表,選擇編輯前200行。

      Teacher:

      Teacher_course_class:

      導(dǎo)入結(jié)果: Book:

      Class:

      Course:

      Department:

      Student:

      Student_course:

      Teacher:

      Teacher_course_class:

      2.用Transact-SQL向Course表中插入一條記錄,course_name為空,看運(yùn)行的結(jié)果。

      SQL語(yǔ)句:

      INSERTINTO course VALUES('dep02_s002', null,'dep02_s002', '72', '5', '4');運(yùn)行結(jié)果:

      分析:course_name有not null的約束,因此這條語(yǔ)句不能執(zhí)行。

      3.用Transact-SQL修改Course表中credit為5的記錄,將其credit改為7, credit小于4的改為2,看運(yùn)行的結(jié)果。

      SQL語(yǔ)句:

      update course set credit=7 where credit=5;執(zhí)行結(jié)果:

      分析:約束C1指定了credit的范圍為1至6.SQL語(yǔ)句:

      update course set credit=2 where credit<4;執(zhí)行結(jié)果:

      4.刪除一條學(xué)生記錄,看運(yùn)行結(jié)果,對(duì)運(yùn)行結(jié)果進(jìn)行分析。SQL語(yǔ)句:

      deletefrom student where student_id='g9940201';執(zhí)行結(jié)果:

      分析:因?yàn)橛袇⒄胀暾约s束,不能刪除。

      5.用Transact-SQL完成將編號(hào)為dep04_b001的課程的選修信息插入到一個(gè)新的選課信息表中。

      SQL語(yǔ)句:

      Creattablestudent_course2(course_idchar(20), student_idchar(20)gradeint, creditint, semesterint,school_yearchar(20),primarykey(course_id,student_id));

      insertintostudent_course2 select*fromstudent_course wherecourse_id='dep04_b001';執(zhí)行結(jié)果:

      6.用Transact-SQL完成刪除單片機(jī)原理課程的選課信息,分析運(yùn)行結(jié)果。

      SQL語(yǔ)句:

      deletefrom student_course where course_id in(select course_id from course

      where course_name='單片機(jī)原理')執(zhí)行結(jié)果: 分析:所有課程號(hào)為dep04_s003的課程被刪除。

      本實(shí)驗(yàn)中遇到的問(wèn)題和解決方法:

      本實(shí)驗(yàn)的順利完成需要預(yù)先作很多準(zhǔn)備工作。以下就是我在遇到缺少組件accessdatabaseengine時(shí)的解決過(guò)程的記錄。

      AccessDatabaseEngine的安裝

      accessdatabaseengine用于和office連接,導(dǎo)入導(dǎo)出數(shù)據(jù),本實(shí)驗(yàn)中需要導(dǎo)入excel文件。安裝配合office的版本,我安裝的是accessdatabaseengine2017(English)版本。安裝32位版本,因office2016是32位。之前誤操作安裝了不能使用的老舊版本accessdatabaseengine2007,通過(guò)控制面板-應(yīng)用程序卸載將其卸載了。安裝accessdatabaseengine依然報(bào)錯(cuò),是因?yàn)閙icrosoftofficeclicktorun阻礙sqlserver的一些功能,需要將其卸載。這是微軟推出的用于減少office打開(kāi)速度的應(yīng)用程序,安裝office2016時(shí)會(huì)自動(dòng)安裝上,原理是開(kāi)機(jī)時(shí)將一部分內(nèi)容放到內(nèi)存中,因此打開(kāi)文件時(shí)會(huì)更快一些。檢測(cè)自己的office是通過(guò)clickto run 還是MSI安裝的,可以在word中點(diǎn)擊文件-賬戶,查看產(chǎn)品信息,如果有下圖中“office更新”這個(gè)選項(xiàng),則說(shuō)明安裝過(guò)click to run。這個(gè)程序在控制面板-應(yīng)用程序中找不到,因此用刪除注冊(cè)表的方式卸載。快捷鍵“win+R”輸入“regedit”打開(kāi)注冊(cè)表編輯器,左邊HKEY_CLASSES_ROOT-Installer-Product-00006開(kāi)頭的選項(xiàng),有四個(gè)。單擊這幾個(gè)選項(xiàng),在右側(cè)查看詳細(xì)信息,可以看到ProductNam是Microsoft Access database engine 2007(我原來(lái)誤安裝的老版本)。刪除之前先備份注冊(cè)表。方法一:選中要?jiǎng)h除的文件,右鍵-導(dǎo)出,保存。只保存了要?jiǎng)h除的文件。方法二:注冊(cè)表編輯器,文件-導(dǎo)出,保存。保存了注冊(cè)表所有信息。這是因?yàn)槿绻`刪了重要文件會(huì)導(dǎo)致嚴(yán)重后果,可能需要重裝系統(tǒng),留此備份是為了可以恢復(fù)系統(tǒng)。

      備份完之后,選中要?jiǎng)h除的文件(00006開(kāi)頭的四個(gè)),右鍵-刪除即可?;氐紸ccess database engine 32位的程序安裝包,安裝。我無(wú)法安裝64位,可能是因?yàn)閛ffice是32位。安裝成功之后就可以在sqlserver中導(dǎo)入excel文件了。

      下載北郵小學(xué)期AVR單片機(jī)電子琴實(shí)驗(yàn)報(bào)告word格式文檔
      下載北郵小學(xué)期AVR單片機(jī)電子琴實(shí)驗(yàn)報(bào)告.doc
      將本文檔下載到自己電腦,方便修改和收藏,請(qǐng)勿使用迅雷等下載。
      點(diǎn)此處下載文檔

      文檔為doc格式


      聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn)自行上傳,本網(wǎng)站不擁有所有權(quán),未作人工編輯處理,也不承擔(dān)相關(guān)法律責(zé)任。如果您發(fā)現(xiàn)有涉嫌版權(quán)的內(nèi)容,歡迎發(fā)送郵件至:645879355@qq.com 進(jìn)行舉報(bào),并提供相關(guān)證據(jù),工作人員會(huì)在5個(gè)工作日內(nèi)聯(lián)系你,一經(jīng)查實(shí),本站將立刻刪除涉嫌侵權(quán)內(nèi)容。

      相關(guān)范文推薦

        北郵小學(xué)期c++文檔

        1. ++程序設(shè)計(jì)實(shí)驗(yàn)報(bào)告姓名: 班級(jí): 學(xué)號(hào): C 要求: 猜價(jià)格游戲 編寫(xiě)C++程序完成以下功能: (1) 假定有一件商品,程序用隨機(jī)數(shù)指定該商品的價(jià)格(1-1000的整數(shù)); (2) 提示用戶猜價(jià)格,并輸入:若用......

        北郵小學(xué)期實(shí)驗(yàn)報(bào)告-簡(jiǎn)易紅外遙控系統(tǒng)

        簡(jiǎn)易紅外遙控系統(tǒng) 實(shí)驗(yàn)報(bào)告 班級(jí): 姓名: 學(xué)號(hào): 指導(dǎo)老師: 學(xué)院: 北京郵電大學(xué) 一、 實(shí)驗(yàn)要求 1、遙控對(duì)象8個(gè),被控制設(shè)備用LED分別代替,LED發(fā)光表示工作。 接收機(jī)與發(fā)射機(jī)的距離不......

        北郵嵌入式實(shí)驗(yàn)報(bào)告[五篇]

        嵌入式系統(tǒng)開(kāi)發(fā)實(shí)驗(yàn)報(bào)告 班級(jí): 姓名: 班內(nèi)序號(hào): 學(xué)號(hào): 日期: 目錄 一、 實(shí)驗(yàn)?zāi)康?.........................................................................................

        北郵數(shù)據(jù)庫(kù)第一次實(shí)驗(yàn)報(bào)告

        《數(shù)據(jù)庫(kù)原理》實(shí)驗(yàn)報(bào)告 實(shí)驗(yàn)名稱班級(jí)組號(hào)組員姓名 數(shù)據(jù)庫(kù)實(shí)驗(yàn)平臺(tái)的安裝、數(shù)據(jù)庫(kù)創(chuàng)建與維護(hù)實(shí)驗(yàn) 計(jì)算機(jī)科學(xué)與技術(shù)8班2011211308 梁展偉、李安一、實(shí)驗(yàn)?zāi)康?1.通過(guò)對(duì)Micr......

        北郵數(shù)據(jù)結(jié)構(gòu)實(shí)驗(yàn)報(bào)告-排序范文大全

        北京郵電大學(xué) 數(shù)據(jù)結(jié)構(gòu)試驗(yàn)報(bào)告 實(shí)驗(yàn)名稱: 實(shí)驗(yàn)四排序 學(xué)生姓名:班級(jí):班內(nèi)序號(hào):學(xué)號(hào): 日期: 2014年1月4日 1 實(shí)驗(yàn)?zāi)康?學(xué)習(xí)、實(shí)現(xiàn)、對(duì)比各種排序算法,掌握各種排序算法的優(yōu)劣,以......

        北郵日歷java實(shí)驗(yàn)報(bào)告

        Java日歷實(shí)驗(yàn)報(bào)告 信息工程27班項(xiàng)明鈞 一、實(shí)驗(yàn)要求 寫(xiě)一個(gè)建議日歷圖形用戶界面二、設(shè)計(jì)思路 此次作業(yè)主要用到了窗口布局設(shè)計(jì)及各個(gè)組件的功能顯示,事件處理機(jī)制。首先需......

        北郵數(shù)據(jù)庫(kù)實(shí)驗(yàn)報(bào)告[最終版]

        數(shù)據(jù)庫(kù)實(shí)驗(yàn)報(bào)告(四) 姓名:學(xué)號(hào):班級(jí): 1. 簡(jiǎn)單查詢:SQL語(yǔ)句: select credit from course where course_name='SQL Server數(shù)據(jù)庫(kù)開(kāi)發(fā)技術(shù)'; 查詢“數(shù)據(jù)庫(kù)開(kāi)發(fā)技術(shù)”課程的學(xué)分;......

        北郵現(xiàn)場(chǎng)總線實(shí)驗(yàn)報(bào)告

        現(xiàn)場(chǎng)總線實(shí)驗(yàn)報(bào)告 實(shí)驗(yàn)名稱: CAN總線技術(shù)與iCAN模塊實(shí)驗(yàn)學(xué)院: 自動(dòng)化學(xué)院專業(yè): 自動(dòng)化專業(yè)班級(jí): 2010211411 姓名: 韓思宇學(xué)號(hào): 10212006 指導(dǎo)老師: 楊軍一、實(shí)驗(yàn)名稱: 實(shí)驗(yàn)一:CAN總......