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

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 51單片機(jī)學(xué)習(xí)總結(jié)實(shí)例

          51單片機(jī)學(xué)習(xí)總結(jié)實(shí)例

          作者: 時(shí)間:2016-11-19 來源:網(wǎng)絡(luò) 收藏
          馬上大四了,即將找工作。所以便把我學(xué)過的東西總結(jié)一下,系統(tǒng)一下。

          接下來,就把我總結(jié)的結(jié)果跟大家分享下。

          本文引用地址:http://www.ex-cimer.com/article/201611/318259.htm

          這一章是51單片機(jī),主要是程序?qū)嵗?。代碼參考郭天祥的單片機(jī)教材。

          是總括性的,適合于有一定單片機(jī)基礎(chǔ)的同學(xué),也可以給初學(xué)者做一個(gè)系統(tǒng)的學(xué)習(xí)主線。

          這個(gè)博客里的涉及的源代碼大家可以在這里下載http://download.csdn.net/detail/zhaole20094463/4427745

          1.流水燈

          /流水燈/
          #include
          #include//包含_crol_函數(shù)所在的頭文件
          #define uint unsigned int //宏定義 定義uint 在大項(xiàng)目中更加的方便
          #define uchar unsigned char
          void delayms(uint);
          uchar aa;
          void main()
          {
          aa=0xfe;
          while(1)
          {
          P1=aa;
          delayms(500);
          aa=_crol_(aa,1);//aa左移一位
          }
          }
          void delayms(uint xms)//延時(shí)時(shí)間約為1ms通過程序單步執(zhí)行,看運(yùn)行時(shí)間可得到
          {
          uint i,j;
          for(i=xms;i>0;i--)
          for(j=110;j>0;j--);
          }

          通過調(diào)用系統(tǒng)函數(shù)的方式使流水燈實(shí)現(xiàn)循環(huán)左移。

          2.數(shù)碼管顯示程序

          /*鎖存器用的是74HC573高電平通,低電平鎖存*/
          /*作用:高阻態(tài) ,數(shù)據(jù)鎖存 ,數(shù)據(jù)緩沖 (加強(qiáng)驅(qū)動(dòng)能力)*/
          /*循環(huán)顯示1-A的數(shù)據(jù)*/
          #include
          #define uint unsigned int
          #define uchar unsigned char
          sbit dula=P2^6;
          sbit wela=P2^7;
          uchar num;
          uchar code table[]={數(shù)碼管段碼表};
          void main()
          {
          wela=1;//打開鎖存器
          P0=0xc0;//送入鎖存信號(hào)
          wela=0;//關(guān)閉鎖存器
          while(1)
          {
          for(num=0;num<16;num++)
          dula=1;
          P0=table[num];
          delayms(500);
          }
          }
          void delayms(uint xms)
          {
          uint i,j;
          for(i=xms;i>0;i--)
          for(j=110;j>0;j--);
          }

          3.獨(dú)立鍵盤檢測(cè)

          /*通過按鍵控制led亮滅*/
          #include
          #define uint unsigned int
          #define uchar unsigned char
          sbit key1=P3^4;
          sbit led=P1^0;
          void delay(uint z)
          {
          uint x,y;
          for(x=z;x>0;x--)
          for(y=110;y>0;y--);
          }
          void main()
          {
          P3=0xff;//在對(duì)51單片機(jī)進(jìn)行按鍵檢測(cè)時(shí),先要將引腳置1;
          while(1)
          {
          if(key1==0)
          {
          delay(5);
          if(key1==0)//按鍵消抖
          {
          led=0;
          num++;
          if(num==2)
          num=0;
          led=1;
          }
          }

          4.矩陣鍵盤檢測(cè)

          /*檢測(cè)矩陣鍵盤數(shù)碼管顯示0-F/
          矩陣鍵盤的四列與P3.4~P3.7相連
          4行與P3.0~P3.3
          #include
          #define uchar unsinged char
          #define uint unsigned int
          sbit dula=P2^6;
          sbint wela=P2^7;
          uchar code table[]={段碼表};
          void delayms(uint xms);
          {
          uint i,j;
          for(i=xms;i>0;i--)
          for(j=110;j>0;j--);
          }
          void display(uchar num)顯示函數(shù)
          {
          P0=table[num];
          dula=1;
          dula=0;
          }
          void matrixkeyscan()//矩陣鍵盤的檢測(cè)
          {
          uchar temp,key;
          P3=0xfe;//打開P3.7,P3.7置0.檢測(cè)高四位
          temp=P3;
          temp=temp&0xf0;
          if(temp!=0xf0)//是否有鍵被按下
          {
          delayms(10);
          temp=P3;
          temp=temp&0xf0;
          if(temp!=0xf0)//按鍵消抖
          {
          temp=P3;
          switch(temp)
          {
          case 0xee:key=0;break;
          case 0xde:key=1;break;
          case 0xbe:key=2;break
          case 0x7e:key=3:break;
          }
          while(temp!=0xf0)//檢測(cè)按鍵是否彈起,如果沒有彈起循環(huán)停在這里。
          {
          temp=P3;
          temp=temp&0xf0;
          }
          display(key);
          }
          }
          。。。。。。。。。。。。。。。。。。。
          如下程序依次增加
          令P3=0xfd,打開P3.6,P3.6置低,檢測(cè)高四位 依次為 4,5,6,7
          然后令P3= 0xfb 0xf7
          }
          void main()
          {
          P0=0;//關(guān)閉所有數(shù)碼管的段選
          dula=1;
          dula=0;
          P0=0xc0;
          wela=1;
          wela=0;
          while(1)
          {
          matrixkeyscan();//不停調(diào)用鍵盤掃描程序
          此程序關(guān)鍵在于這個(gè)函數(shù),矩陣鍵盤的掃描算法
          }
          }

          5.1602液晶屏顯示子函數(shù)

          //
          這個(gè)程序主要是有這樣幾個(gè)子函數(shù),關(guān)于lcd寫命令和寫數(shù)據(jù)的
          #include
          #define uchar unsigned char
          #define uint unsigned int
          uchar code table[]="zhaole20094463";
          uchar code table1[]="love Embedded systems";
          sbit lcden=P3^4;//lcd使能端
          sbit lcdrs=P3^5;//lcd數(shù)據(jù)命令選擇端
          uchar num;
          void delay(uint z)
          {
          uint x,y;
          for(x=z;x>0;x--)
          for(y=110;y>0;y--);
          }
          void write_com(uchar com)//lcd寫命令函數(shù)
          {
          lcdrs=0;
          P0=com;
          delay(5);
          lcden=1;
          delay(5);
          lceen=0;
          }


          void write_data(uchar date)//lcd寫數(shù)據(jù)
          {
          lcdrs=1;
          P0=date;
          delay(5);
          lcden=1;
          delay(5);
          lcden=0;
          }


          void init()
          {
          lcden=0;
          write_com(0x38);//設(shè)置16*2顯示,5*7點(diǎn)陣,8位數(shù)據(jù)接口
          write_com(0x0c);//設(shè)置開顯示,不顯示光標(biāo)
          write_com(0x06);//寫第一個(gè)字符后地址指針加1
          write_com(0x01);//顯示清0,數(shù)據(jù)指針清0
          }
          void main()
          {
          init();
          write_com(0x80);//數(shù)據(jù)指針定位在第一行的第一個(gè)字處
          for(num=0;num<14;num++)
          {
          write_data(table[num]);
          delay(5);
          }
          write_com(0x80+0x40);//數(shù)據(jù)指針定位在第二行的第一個(gè)字處
          for(num=0;num<21;num++)
          {
          write_data(table1[num]);
          delay(5);
          }
          while(1);
          }

          5.2 12864顯示子函數(shù)

          #include
          #include
          #include


          #define uchar unsigned char
          #define uint unsigned int


          #define LCD_data P0;//數(shù)據(jù)口


          sbit LCD_RS=P3^5; //數(shù)據(jù)選擇輸入
          sbit LCD_RW=P3^6; //液晶讀寫控制
          sbit LCD_EN=P3^4; //液晶使能控制端
          sbit LCD_PSB=P3^7; //串并方式控制


          void delay_1ms(uint )
          {
          uint i,j;
          for(j=0j for(i=0;i<110;i++);
          }
          /*PS=L,RW=L,E=高脈沖,D0~D7=指令碼*/
          void write_cmd(uchar cmd)
          {
          LCD_RS=0;
          LCD_RW=0;
          LCD_EN=0;
          P0=cmd;
          delay_1ms(5);
          LCD_EN=0;
          }
          /*寫顯示數(shù)據(jù)到LCD*/
          /*RS=H,RW=L,E=高脈沖,D0~D7=數(shù)據(jù)
          void write_dat(uchar dat)
          {
          LCD_RS=1;
          LCD_RW=0;
          LCD_EN=0;
          P0=dat;
          delay_1ms(5);
          LCD_EN=1;
          dealy_1ms(5);
          LCD_EN=0;
          }
          /*設(shè)定顯示位置*/
          void LCD_pos(uchar X,uchar Y)
          {
          uchar pos;
          if(X==0)
          {X=0x80;}
          else if(X==1);
          {X=0x90;}
          else if(x==2)
          {X=0x88;}
          else if(X==3)
          {X=0x98;}
          pos=X+Y;
          write_cmd(pos);//顯示地址
          }


          /*LCD初始化設(shè)置*/
          void lcd_init()
          {
          LCD_PSB=1; //并口方式
          write_cmd(0x30);//基本指令操作
          delay_1ms(5);
          write_cmd(0x0C);//先是開,關(guān)光標(biāo)
          delay_1ms(5);
          write_cmd(0x01);//清除LCD的顯示內(nèi)容
          delay_1ms(5);
          }

          6.定時(shí)器中斷

          /*用定時(shí)器0的方式1實(shí)現(xiàn)第一個(gè)發(fā)光管以1s亮滅*/
          定時(shí)器/計(jì)數(shù)器4種工作方式
          1,方式0 13位計(jì)數(shù)器 高8位和低5位
          2,方式1 16位計(jì)數(shù)器
          3,方式2 自動(dòng)恢復(fù)初值 8位
          4,方式3 只適用于T0,不適用于T1 8位

          45872初值的計(jì)算
          晶振:11.0592M
          機(jī)器周期:計(jì)數(shù)一次的時(shí)間=12*(1/11.0592M)51單片機(jī)是12個(gè)時(shí)鐘周期為一個(gè)機(jī)器周期
          =1.09US 指令周期由整數(shù)個(gè)機(jī)器周期組成
          45872 =50Ms/1.09us


          //
          #include
          #define uchar unsigned char
          #define uint unsigned int
          sbit led1=P1^0;
          uchar num;
          void main()
          {
          TMOD=0x01;//設(shè)置定時(shí)器0工作方式1
          TH0=(65535-45872)/256;//裝初值11.0592M晶振定時(shí)50ms為45872
          TL0=(65535-45872)%256;
          EA=1; //開總中斷
          ET0=1; //開定時(shí)器0中斷
          TR0=1; //啟動(dòng)定時(shí)器0
          while(1) //程序停在這里等待中斷的發(fā)生
          }


          void T0_time() interrupt 1
          {
          TH0=(65535-45872)/256;
          TL0=(65535-45872)%256;
          num++;
          if(num==20)
          {
          num=0;
          led1=~led1;
          }
          }

          7.串口通信

          //
          上位機(jī)通過串口調(diào)試助手發(fā)送一個(gè)字符x,單片機(jī)收到字符后返回給上位機(jī)“I get x”
          串口波特率設(shè)置為9600bps。
          #include
          #define uchar unsigned char
          #define uint unsigned int
          uchar flag,a,i;
          uchar code table[]="I get";
          void init()
          {
          TMOD=0x20;//設(shè)置T1定時(shí)器工作方式為2 8位初值自動(dòng)重裝的8位定時(shí)器
          TH1=0xfd;//T1定時(shí)器裝初值(高八位) 控制串口通信的波特率(由定時(shí)器1的溢出率控制)
          TL1=0xfd;///T1定時(shí)器裝入初值(低八位)
          TR1=1; //定時(shí)器1運(yùn)行控制位 置一啟動(dòng)定時(shí)器
          REN=1; //允許串口接收
          SM0=0;
          SM1=1; //設(shè)置串口工作方式為一
          EA=1; //全局中斷允許位 置一開全局中斷
          ES=1; //串口中斷允許位
          }


          void main()
          {
          init();
          ` while(1)
          {
          if(flag==1)
          {
          ES=0;
          for(i=0;i<6;i++)
          {
          SBUF=table[i];
          while(!TI)
          TI=0;//發(fā)送中斷標(biāo)志 發(fā)送數(shù)據(jù)完成后觸發(fā)中斷 硬件置一 必須軟件清零
          }
          SBUF=a;// 串口發(fā)送數(shù)據(jù)
          while(!TI);
          TI=0;
          ES=1;
          flag=0;
          }

          }


          void ser() interrupt 4 //串口中斷服務(wù)程序
          {
          RI=0; // 收到數(shù)據(jù)硬件置一,由軟件清零
          a=SBUF; //將寄存器的值 賦給a
          flag=1; //標(biāo)志位
          }
          注意:51單片機(jī)的特殊之處在于,SBUF既是串口接收寄存器也是串口發(fā)送寄存器,取決于
          SBUF所在賦值符號(hào)“=”左右的位置


          此程序中共用的串口中斷,


          定時(shí)器1中斷 特殊功能寄存器SBUF


          中斷響應(yīng)的條件


          中斷源有中斷請(qǐng)求 此中斷源允許位為1 cpu開中斷(即EA=1)以上三個(gè)條件同時(shí)滿足


          串口通信設(shè)置


          確定串口通信波特率(編程TMOD寄存器定時(shí)器工作方式寄存器)

          計(jì)算定時(shí)器初值轉(zhuǎn)載THX TLX

          確定串行口工作方式(編程SCON寄存器串行口控制方式寄存器)

          串行口工作在中斷方式時(shí),要進(jìn)行中斷設(shè)置如TI,RI軟件清零

          8.I2C總線通信模擬子函數(shù)

          /*/
          因?yàn)?1單片機(jī)沒有I2C總線,所以采用模擬I2C通信
          1,總線初始化
          void init()
          {
          SCL=1;
          delay();
          SDA=1;
          delay();
          }
          2,啟動(dòng)信號(hào)
          void start()
          {
          SDA=1;
          delay(1);
          SCL=1;
          delay();
          SDA=0;
          delay();
          }
          3,應(yīng)答信號(hào)
          void respons()
          {
          uchar i=0;
          SCL=1;
          delay();
          while((SDA==1)&&(i<255))
          i++;
          SCL=0;
          delay();
          }
          4,停止信號(hào)
          void stop()
          {
          SDA=0;
          delay();
          SCL=1;
          delay();
          SDA=1;
          delay();
          }
          5,寫一個(gè)字節(jié)
          void writebyte(uchar date)
          {
          uchar i,temp;
          temp=date;
          for(i=0;i<8;i++)
          {
          temp=temp<<1;
          SCL=0;
          delay();
          SDA=CY;
          delay();
          SCL=1;
          delay();
          }
          SCL=0;
          delay();
          SDA=1;
          delay();
          }
          6,讀一個(gè)字節(jié)
          uchar readbyte()
          {
          uchar i,k;
          SCL=0;
          delay();
          SDA=1;
          for(i=0;i<8;i++)
          {
          SCL=1;
          delay();
          k=(k<<1)|SDA;
          SCL=0;
          delay();
          }
          delay();
          return k;
          }

          9.看門狗

          //
          關(guān)于51單片機(jī)中的看門狗寄存器
          D5 EN_WDT 看門狗允許位
          D4 CLK_WDT 看門狗清零
          D3 IDLE_WDT 看門狗IDLE模式位
          PS0 PS1 PS2 看門狗定時(shí)器預(yù)分頻值
          這三個(gè)寄存器置不同的值決定不同的看門狗溢出時(shí)間
          看門狗溢出時(shí)間=(N*預(yù)分頻數(shù)*32768)/晶振頻率
          #include
          #define uchar unsigned char
          #define uint unsigned int
          sfr WDT_CONTR=0xe1;//定義看門狗寄存器 reg52.h中沒有對(duì)它進(jìn)行定義
          sbit led1=P1^0;
          void delayms(uint xms)
          {
          uint i,j;
          for(i=xms;j>0;j--)
          for(j=110;j>0;j--);
          }

          void main()
          {
          WDT_CONTR=0x35;//0x35=0011 0101設(shè)置預(yù)分頻數(shù)為 64 溢出時(shí)間為2.0971s
          led1=0;
          delayms(500);
          led1=1;
          while(1)
          {
          delayms(1000);
          WDT_CONTR=0x35;//喂狗語句將D4不斷置1,一旦D4被清零則看門狗復(fù)位
          }
          }

          10.軟件實(shí)現(xiàn)系統(tǒng)復(fù)位

          STC ISP/IAP控制寄存器(ISP_CONTR)
          D7 ISPEN 功能允許位 0禁止編程改變flash 1允許
          D6 SWBS 0軟件選擇從用戶應(yīng)用程序區(qū)啟動(dòng) 1從ISP程序區(qū)啟動(dòng)
          D5 SWRST 不操作 1產(chǎn)生系統(tǒng)軟件復(fù)位,硬件自動(dòng)清零
          D2 WT2
          D1 WT1
          D0 WT0 編程設(shè)定CPU等待的最長(zhǎng)時(shí)間,對(duì)flash進(jìn)行讀操作,寫操作,擦除操作必須在這個(gè)時(shí)間內(nèi)
          SWBS=0 SWRST=1(軟復(fù)位) 從用戶應(yīng)用程序區(qū)(AP區(qū))軟件復(fù)位并切換到用戶應(yīng)用程序區(qū)開始執(zhí)行程序
          從哪里復(fù)位取決于程序在哪里執(zhí)行
          SWBS=1 SWRST=1 從ISP監(jiān)控程序區(qū)軟件復(fù)位并切換ISP監(jiān)控程序區(qū)開始執(zhí)行程序
          使用方法:
          進(jìn)行軟件復(fù)位時(shí)
          首先
          sfr ISP_CONTR=0xe7;定義ISP/IAP控制寄存器
          然后再需要軟件復(fù)位的地方加入如下語句即可
          ISP_CONTR=0x20//用軟件復(fù)位到用戶應(yīng)用程序區(qū)(AP),重新開始執(zhí)行程序

          11.DS18B20編程應(yīng)用子函數(shù)

          //
          Ds18B20的編程子函數(shù)
          DS18B20是單總線接口的溫度傳感器,應(yīng)用范圍很廣泛

          #include
          #include
          #define uchar unsigned char
          #define uint unsigned int
          sbit ds=P2^2;//溫度傳感器信號(hào)線
          uint temp;//定義整型的溫度數(shù)據(jù)
          float temp;//定義浮點(diǎn)型的溫度數(shù)據(jù)
          void delay(uint z)
          {
          uint x,y;
          for(x=z;x>0;x--)
          for(y=110;y>0;y--);
          }




          void dsreset(void)//DS18B20復(fù)位,初始化函數(shù)
          {
          uint i;
          ds=0;
          i=103;
          while(i>0)i--;
          ds=1;
          i=4;
          while(i>0)i--;
          }


          bit tempreadbit(void)//讀1位數(shù)據(jù)函數(shù)
          {
          uint i;
          bit dat;
          ds=0;i++;//i++起延時(shí)作用
          ds=1;i++;i++;
          dat=ds;
          i=8;while(i>0)i--;
          return(dat);
          }


          uchar tempread(void)//讀1個(gè)字節(jié)數(shù)據(jù)函數(shù)
          {
          uchar i,j,dat;
          dat=0;
          for(i=1;i<=8;i++)
          {
          j=tempreadbit();
          dat=(j<<7)|(dat>>1);//讀出的數(shù)據(jù)最低位在最前面,這樣剛好一個(gè)字節(jié)在dat里
          }
          return(dat);
          }
          void tempwritebyte(uchar dat)//向DS18B20寫一個(gè)字節(jié)數(shù)據(jù)函數(shù)
          {
          uint i;
          uchar j;
          bit testb;
          for(j=1;j<=8;j++)
          {
          testb=dat&0x01;
          dat=dat>>1;
          if(testb)//寫1
          {
          ds=0;
          i++;i++;
          ds=1;
          i=8;while(i>0)i--;
          }
          else//寫0
          {
          ds=0;
          i=8;while(i>0)i--;
          ds=1;
          i++;i++;
          }
          }
          }


          void tempchange(void)//DS18B20 開始獲取溫度并轉(zhuǎn)換
          {
          dsreset();
          delay(1);
          tempwritebyte(0xcc);//寫 跳過讀ROM指令
          tempwritebyte(0x44);//寫 溫度轉(zhuǎn)換指令
          }


          uint get_temp()
          {
          uchar a,b;
          dsreset();
          delay(1);
          tempwritebyte(0xcc);
          tempwritebyte(0xbe);//讀內(nèi)部ram中的9字節(jié)
          a=tempread();//讀低8位
          b=tempreda();//讀高8位
          temp=b;
          temp<<=8;
          temp=temp | a;//兩個(gè)字節(jié)組合為1個(gè)字
          f_temp = temp*0.0625;//溫度在寄存器中為12位,分辨率為0.0625 廠家出廠時(shí)默認(rèn)精度為12位,所以乘以0.0625
          temp=f_temp*10+0.5; //乘以10表示小數(shù)點(diǎn)后面只取一位,加0.5是為了四舍五入
          f_temp=f_temp+0.05;
          return temp;
          }

          12.內(nèi)部ram的擴(kuò)展

          51單片機(jī)存儲(chǔ)器模式一共有三種
          small模式 默認(rèn)變量存儲(chǔ)在單片機(jī)內(nèi)部的128B RAM中
          無聲明均以這個(gè)模式存儲(chǔ)
          compact模式 默認(rèn)變量存儲(chǔ)在單片機(jī)內(nèi)部的 256B RAM中
          關(guān)鍵字 pdata :unsinged char pdata a[100]
          large 模式 默認(rèn)變量均存儲(chǔ)在64K的RAM區(qū)包括內(nèi)部ram和外部ram
          關(guān)鍵字 xdata:unsingned char xdata a[100]
          三種模式的不同:訪問速度由快到慢

          這個(gè)博客里的涉及的源代碼大家可以在這里下載http://download.csdn.net/detail/zhaole20094463/4427745



          評(píng)論


          技術(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); })();