一天: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();    
    }
}

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
相信很多爱好电子的朋友,对单片机这个词应该都不会陌生了吧。不过有些朋友可能只听说他叫单片机,他的全称是什么也许并不太清楚, 更不用说他的英文全称和简称了。单片机是一块在集成电路芯片上集成了一台有一定规模的微型计算机。简称为:单片微型计算机或单片机 (Single Chip Computer)。单片机的应用到处可见,应用领域广泛,主要应用在智能仪表、实时控制、通信、家电等方面。不过这一切都没什么关系,因为我(当然也包括任何人)都是从不知道转变成知道的,再转变成精通的。现在我只想把我学习单片机的经历,详细地讲叙给大家听听,可能有些大虾会笑话我,想:那么简单的东西还在这里卖弄。但是你错了,我只是把我个人学习的经历讲述一遍而已,仅仅对那些想 学习单片机,但又找不到好方法或者途径的朋友,提供一个帮助,使他们在学习过程中,尽量少走些弯路而已! 首先,你必须有学习单片机的热情,不是说今天去图书馆看了一个下午关于单片机的书,而明天玩上半天,后天就不知道那个本书在讲什么东西了。还是先说说我吧,我从大二的第一个学期期末的时候才开始接触单片机,但在这之前,正如上面所说的:我知道有种芯片叫单片机,具体长成什么样子,却一点也不知道!看到这里很多朋友一定会忍不住发笑。嘿嘿,你可千万别笑,有些大四毕业的人也同样不知道单片机长成什么样子呢!而我对单片机的痴迷更是常人所不能想象的地步,大二的期末考试,我全放弃了复习,每当室友拿着书在埋头复习的时候,我却捧着自己从图书馆借的单片机书在那看,虽然有很多不懂,但是我还是坚持了下来,当时我就想过,为了单片机值不值得我这样去付出,或许这也是在一些三流学校的好处吧,考试挂科后,明年开学交上几十元一门的补考费,应该大部分都能过了。于是,我横下一条心,坚持看我的单片机书和资料。 当你明白了单片机是这么一回事的时候,显而易见的问题出来了:我要选择那种语言为单片机编写程序呢?这个问题,困扰了我好久。具体选择C51还是A51呢?汇编在我们大二之前并没有开过课,虽然看着人家的讲解,很容易明白单片机的每一时刻的具体工作情况,但是一合上书或者资料,自己却什么也不知道了,根本不用说自己写程序了。于是,我最终还是决定学C51,毕竟C51和我们课上讲的C语言,有些类似,编程的思想可以说是相通的。而且C51还有更大的优点就是编写大程序时的优越性更不言而喻,当然在那时,我并没有想的那么深远,C51的特点,还是在后来的实践过程中,渐渐体会到的!朋友如果你选择了C51,那么请继续往下看,如果你选择了A51,那么你可以不要看了!因为下面讲的全是C方面的,完全在浪费你的时间! 呵呵 ^_^ 第二,既然你想学好单片机,你必须得舍得花钱,如果不买些芯片回来自己动手焊焊拆拆的(但是在后期会介绍给大家一个很好用的硬件仿真软件,并不需要你用实验板和仿真器了,直接在你的PC上完成,但是软件毕竟是软件,从某个特定的意义上来说是并不能代替硬件的),即使你每天捧着本书,把那本书翻烂,也永远学不会单片机的!刚接触单片机的朋友,看了资料,一定会对以下几个词见的比较多,但是具体的概念还是比较模糊,现作如下说明:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值