一天:51单片机从入门到一个动态数码管显示数字控制
Posted ghostwu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一天: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(); } }
以上是关于一天:51单片机从入门到一个动态数码管显示数字控制的主要内容,如果未能解决你的问题,请参考以下文章
利用51单片机,4个数码管设计一个计时器,要求在数码管上显示的数据从0开始每1秒钟加1。