一天:51單片機從入門到一個動態數碼管顯示數字控制


最近進的公司是一個做路由器的。。很多嵌入式工程師。有個項目( 智能空調控制)是跟嵌入式工程師對接,我做APP+PHP。。他做服務器。我們用MQTT(由於emqtt是用erlang寫的,所以我也學了點erlang,后期有時間分享一下,這個語言很好,很強大。特別抽象)。這個項目激發了我對嵌入式的興趣,於是乎。開始從51單片機搞起了。。所以就有了這篇文章。。。今天搞得東西挺多。我最近都是筆記形式,不想以前寫的那么詳細。。。因為學的東西太多,白天在公司搞項目,沒時間寫太具體。。。

今天學了什么呢?

 

>keil安裝和使用,下載程序到開發板

>點亮第一個led燈,這個很簡單。給單片機的p0口 的最低位,輸入一個高電平,就可以點亮一個動態數碼管【當然下載程序之后,要連線】

#include <reg52.h>
sbit led1 = P0^0;
void main(){
    led1 = 1;
}

>在點亮led之后,再加點程序控制,讓led閃爍。。。閃爍的思路也簡單: 一下高電平。然后延時,再低電平。。再延時。。就OK了。。延時多少秒合適? 可以通過keil軟件仿真算出。仿真的時候,記得把晶振調整跟開發板一樣。我的開發板是12M

#include <reg52.h>

sbit led = P0^0;
typedef unsigned char u8;
typedef unsigned int u16;

void delay( u16 i ){
    while( i-- );
}

void main (){
    while( 1 ) {
        led = 1;
        //delay( 5000 ); //  通過軟件仿真得出 執行5000次循環 需要45ms
        delay( 50000 );
        led = 0;
        //delay( 5000 ); 
        delay( 50000 );
    }
}

>點亮led之后,再來一個流水燈,思路就是循環設置一個數碼管的某一段 為 高電平。其他段為低電平。。然后,延時循環。就可以達到流水燈的效果

#include <reg52.h>
#include <intrins.h>
#include <stdio.h>

#define led P0
typedef unsigned char u8;
typedef unsigned int u16;

void delay( u16 i ){
    while( i-- );
}

void main (){
    u8 i = 0;
    //led = 0x01; //p0的 最低位為高電平  0x01( p0端口的第8位為1 即,高電平 )

    led = 0x80;
    while( 1 ) {
        /*  方法一: 不用庫函數
        for( i = 0; i < 8; i++ ){
            led = ( 0x01 << i ); //循環移位, 把p0端口從p0.0--->p0.7循環設置為高電平
            delay( 50000 );
        }
        */

        //方法二,使用庫函數
        /*
        for( i = 0 ; i < 8; i++ ){
            led = _crol_( led, 1 ); //每次向左移動1位
            delay( 50000 );
        }    
        */
    
        for( i = 0 ; i < 8; i++ ){
            led = _cror_( led, 1 ); //每次向右移動1位
            delay( 50000 );
        }

    }
}

>再然后,控制蜂鳴器。。我的開發板是無源蜂鳴器靠頻率驅動。把頻率換算成周期: F = 1 / T,周期通過延時函數實現。 然后改變高低電平的占空比,可以實現蜂鳴器的聲音大小。頻率改變的是蜂鳴器

的音色。

#include <reg52.h>

#define led P0
typedef unsigned char u8;
typedef unsigned int u16;

sbit beep = P1^5; //用p1口的第5位

void delay( u16 i ){
    while( i-- );
}

void main (){
    //無源蜂鳴器靠頻率驅動, 假設10k能驅動, 那么T = 1 / 10k,  T = 0.1 毫秒
     //之前的測試是循環50000次 = 450 ms(毫秒 ) 那0.1 ms = 12.8次
    
    while( 1 ) {
        beep = ~beep; //~:取反操作
        delay( 50 );
        
        //改變高低電平的占空比(比例) 控制蜂鳴器聲音大小
        beep = 1;
        delay( 50 );
        beep = 0;
        delay( 5 );
    }
}

>在然后,控制一個繼電器。這個很簡單。跟點亮led燈同樣的思路

#include <reg52.h>

#define led P0
typedef unsigned char u8;
typedef unsigned int u16;

//繼電器控制
sbit relay = P1^4; //用p1口的第4位

void main (){
    relay = 0; //給一個低電平 繼電器開啟    
    while( 1 ) {
        
    }
}

>再然后,在靜態數碼管上做了個循環顯示0~F的程序,思路就是 1~F 怎么在靜態數碼管上表示? 因為我的開發板靜態數碼管是共陽數碼管。要用低電平才能點亮對應的段。然后把每一位數字(0~F)對應的

二進制算出對應的十六進制,就是我程序中定義的那個數組表示的就是( 0 ~ F).

#include <reg52.h>

#define led P0
typedef unsigned char u8;
typedef unsigned int u16;

void delay( u16 i ){
    while( i-- );
}

void main (){
    u8 character [16] = { 0xC0, 0xF9 , 0xA4 , 0xB0 , 0x99 , 0x92, 
                         0x82 , 0xF8 , 0x80  , 0x90 , 0x88 , 0x83,
                         0xC6 , 0xA1 , 0x86 , 0x8E};
    int i = 0;
    while( 1 ) {
        for( i = 0; i < 16; i++ ){
            led = character[i];
            delay( 50000 );
            delay( 50000 );
        }
    }
}

>在然后,在8個動態數碼上顯示1~8,用到38譯碼器模塊的輸入,輸出,我的第一版(傻瓜版程序)

#include <reg52.h>

sbit A1 = P2^2;
sbit B1 = P2^3;
sbit C1 = P2^4;
#define led P0
typedef unsigned char u8;
typedef unsigned int u16;

void delay( u16 i ){
    while( i-- );
}

void main (){
    while( 1 ){
        A1 = 0x0;
        B1 = 0x0;
        C1 = 0x0;
        //0x06 , 0x5b , 0x4f , 0x66 , 0x6d, 0x7d , 0x07 , 0x7f 
        led = 0x06;

        delay( 100 );
    
        A1 = 0x1;
        B1 = 0x0;
        C1 = 0x0;
        led = 0x5b;
        delay( 100 );

        A1 = 0x0;
        B1 = 0x1;
        C1 = 0x0;
        led = 0x4f;
        delay( 100 );
        
        A1 = 0x1;
        B1 = 0x1;
        C1 = 0x0;
        led = 0x66;
        delay( 100 );

        A1 = 0x0;
        B1 = 0x0;
        C1 = 0x1;
        led = 0x6d;
        delay( 100 );

        A1 = 0x1;
        B1 = 0x0;
        C1 = 0x1;
        led = 0x7d;
        delay( 100 );

        A1 = 0x0;
        B1 = 0x1;
        C1 = 0x1;
        led = 0x07;
        delay( 100 );

        A1 = 0x1;
        B1 = 0x1;
        C1 = 0x1;
        led = 0x7f;
        delay( 100 );
    }
}

然后經過封裝改造的程序:

#include <reg52.h>

sbit A1 = P2^2;
sbit B1 = P2^3;
sbit C1 = P2^4;
#define led P0
typedef unsigned char u8;
typedef unsigned int u16;

void delay( u16 i ){
    while( i-- );
}

u8 digital[16] = { 0x3f  , 0x06 , 0x5b , 0x4f , 0x66 , 0x6d, 
                        0x7d , 0x07 , 0x7f  , 0x6f , 0x77 , 0x7c,
                        0x39 , 0x5e , 0x79 , 0x71 };

void showDigital(){
    int i = 0;
    for ( i = 0; i < 8; i++ ) {
        switch( i ) {
            case 0:  //位選第一個數碼管
                A1 = 0x0; B1 = 0x0; C1 = 0x0;
                break;
            case 1:
                A1 = 0x1; B1 = 0x0; C1 = 0x0;
                break;
            case 2:
                A1 = 0x0; B1 = 0x1; C1 = 0x0;
                break;
            case 3:
                A1 = 0x1; B1 = 0x1; C1 = 0x0;
                break;
            case 4:
                A1 = 0x0; B1 = 0x0; C1 = 0x1;
                break;
            case 5:
                A1 = 0x1; B1 = 0x0; C1 = 0x1;
                break;
            case 6:
                A1 = 0x0; B1 = 0x1; C1 = 0x1;
                break;
            case 7:
                A1 = 0x1; B1 = 0x1; C1 = 0x1;
                break;
        }
        led = digital[ i ];
        delay( 100 );
    }
}

void main (){
    while( 1 ){
        showDigital();    
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM