zoukankan      html  css  js  c++  java
  • 一天: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();    
        }
    }
  • 相关阅读:
    微信开发 之 开启开发模式
    微信公众号开发 之 编辑模式使用
    分析各种Android设备屏幕分辨率与适配
    【面向对象设计模式】 适配器模式 (二)
    重构 之 总结代码的坏味道 Bad Smell (一) 重复代码 过长函数 过大的类 过长参数列 发散式变化 霰弹式修改
    【Android 应用开发】Android资源文件
    java 创建并写入文件
    隐藏 HttpClient 在console的日志
    HOW TO CHANGE THE DEFAULT KEY-VALUE SEPARATOR OF A MAPREDUCE JOB
    java 时间戳转换
  • 原文地址:https://www.cnblogs.com/ghostwu/p/9130177.html
Copyright © 2011-2022 走看看