2015-09-05 16:26:35 yunfeiyang62 阅读数 19225
  • LCD1602和12864显示器-第1季第17部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第17个课程,主要讲解LCD1602和LCD12864这两种单片机常用LCD显示器的显示原理、以及英文、中文、图片等如何编程显示。本课程对于显示编程具有重要的启蒙作用,是学习各种深入复杂的显示知识的基础。

    4088 人正在学习 去看看 朱有鹏

51单片机 数码管的静态显示和动态显示

数码管(Segment Displays)由多个发光二极管封装在一起组成“8”字型的器件,引线已在内部连接完成,只需引出它们的各个笔划,公共电极。数码管实际上是由七个发光管组成8字形构成的,加上小数点就是8个。这些段分别由字母a,b,c,d,e,f,g,dp来表示。

数码管原理图:

数码管共阴极接法:

数码管共阳极接法:


数码管中有位选和段选,位选就是选择哪个数码管,段选就是被选择的数码管要显示什么数字!

根据数码管的段选,可以总结出数码管的显示数据表:

符号

不显示

0

1

2

3

4

5

6

7

8

9

A

B

C

D

E

F

.

编码

0x00

0x3F

0x06

0x5B

0x4F

0x66

0x6D

0x7D

0x07

0x7F

0x6F

0x77

0x7C

0x39

0x5E

0x79

0x71

0x80


数码管的静态显示:

/*======================================================*/
/*	时间:2015年8月3日 21:19:03 						*/
/*	功能:数码管的静态显示								*/
/*	目的:51单片机学习 									*/
/*		^_^……!											*/
/*======================================================*/

#include 
#include "commLib.h"

sbit WLE  = P2^7;		// 位选
sbit DLE  = P2^6;		// 段选

#define DIGITAL_ARR_NUM		18
unsigned char code digital[DIGITAL_ARR_NUM] = {				// 数码管显示数据表
/*	 0,    1,    2,    3,    4,     5,   6,    7,    8, 	*/
	0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 
/*	 9,    A,    B,    C,    D,    E,    F,    .,   不显示 	*/
	0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x80, 0x00
};

int main(void)
{
	unsigned int i;
	
	// 位选
	WLE = 1;		// 位选端锁存器置高,送数据
	P0 = 0xC0;		// 送数据
	WLE = 0;		// 位选端锁存器置低,保存数据
	
	while(1)
	{
		for (i = 0; i < DIGITAL_ARR_NUM; i++)
		{
			// 段选
			DLE = 1;			// 段选端锁存器置高,送数据
			P0 = digital[i];	// 送数据
			DLE = 0;			// 位选端锁存器置低,保存数据
			
			delay(500);			// 延时500ms
		}
	}

	return 0;
}

效果截图:


数码管的动态显示:
/*======================================================*/
/*	时间:2015年8月6日 20:45:09 						*/
/*	功能:数码管的动态显示								*/
/*	目的:51单片机学习 									*/
/*		^_^……!											*/
/*======================================================*/

#include 
#include "commLib.h"

sbit WLE  = P2^7;		// 位选
sbit DLE  = P2^6;		// 段选

#define DIGITAL_ARR_NUM		18
unsigned char code digital[DIGITAL_ARR_NUM] = {				// 数码管显示数据表
/*	 0,    1,    2,    3,    4,     5,   6,    7,    8, 	*/
	0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 
/*	 9,    A,    B,    C,    D,    E,    F,    .,   不显示 	*/
	0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x80, 0x00
};

int main(void)
{
	unsigned int i;
	
	while (1)
	{
		for (i = 0; i < 6; i++)
		{
			P0 = 0xFF;				// 消影(必须有)
			WLE = 1;				// 位选端锁存器置高,送数据
			P0 = ccCrol(0xFE, i);	// 送数据
			WLE = 0;				// 位选端锁存器置低,保存数据
			
			DLE = 1;				// 段选端锁存器置高,送数据
			P0 = digital[i];		// 送数据
			DLE = 0;				// 位选端锁存器置低,保存数据
			
			delay(1);
		}
	}
	
	return 0;
}

效果截图:



2019-11-11 21:55:58 nknkkn 阅读数 73
  • LCD1602和12864显示器-第1季第17部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第17个课程,主要讲解LCD1602和LCD12864这两种单片机常用LCD显示器的显示原理、以及英文、中文、图片等如何编程显示。本课程对于显示编程具有重要的启蒙作用,是学习各种深入复杂的显示知识的基础。

    4088 人正在学习 去看看 朱有鹏

51的单片机的数码管显示

  • 基于51单片机的LED数码管动态显示 LED数码管动态显示就是一位一位地轮流点亮各位数码管,对于每一位LED数码管来说,每隔一段时间点亮一次,利用人眼的“视觉暂留"效应,采用循环扫描的方式,分时轮流选通各数码管的公共端,使数码管轮流导通显示。当扫描速度达到一定程度时,人眼就分辨不出来了。尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,认为各数码管是同时发光的。若数码管的位数不大于8位时,只需两个8位I/O口。

以下附一个 数码管
以下是一个电子秒表的代码


```c
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit we=P2^7;
sbit du=P2^6;
sbit s2=P3^0;
sbit s3=P3^1;
sbit s4=P3^2;
uchar a,b,c,d,e,f,t,x, num,num1,num2;
uchar code yidaojiu[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void delay(uint);
void play1(uchar,uchar,uchar,uchar,uchar,uchar);
void play2(uchar);
void main()
{ 
  TMOD=0x01;
  TH0=(65535-9216)/256;
        TL0=(65535-9216)%256;
  EA=1;  
  ET0=1;    
  TR0=1;
    while(s2)          
      play1(a,b,c,d,e,f);  
   }
   void play1(uchar a,uchar b,uchar c,uchar d,uchar e,uchar f)
    {
   du=1;
   P0=yidaojiu[a];
   du=0;
    P0=0xff;   
     we=1;
   P0=0X7f;
   we=0;
    delay(3);
     du=1;
   P0=yidaojiu[b];
   du=0;
   P0=0XFF;
     we=1;
   P0=0Xbf;
   we=0;
    delay(3);

   du=1;
   P0=yidaojiu[c];
   du=0;
   P0=0XFF;
     we=1;
   P0=0XDF;
   we=0;
    delay(3);
    du=1;
   P0=yidaojiu[d];
   du=0;
   P0=0xff;
  we=1;
   P0=0Xef;
   we=0;
  delay(3);
du=1;
   P0=yidaojiu[e];
   du=0;
   P0=0xff;
  we=1;
   P0=0Xf7;
   we=0;
  delay(3);

   du=1;
   P0=yidaojiu[f];
   du=0;
   P0=0xff;
  we=1;
   P0=0Xfb;
   we=0;
  delay(3);
   }
    void delay(uint z)
   {
    uint x,y;
 for(x=z;x>0;x--)
 for(y=114;y>0;y--);
   }
    void dingshizhongduan0() interrupt 1
   { 
   char flat;
   TH0=(65535-9216)/256;
   TL0=(65535-9216)%256;
  if(s4==0)
  flat2=0;
   if(flat==0)
  num++;
  if(num==100)
  { 
   num=0;
   num1++;
  }
  if(num1==60)
  {
  num1=0;
  num2++; 
  }
  if(num2==100)
  num2=0;
  s2=1;
  a=num%10;
  b=num/10;
  c=num1%10;
  d=num1/10;
  e=num2%10;
  f=num2/10;
  }
 

2018-12-09 20:50:23 YouCanDoIt_ 阅读数 3109
  • LCD1602和12864显示器-第1季第17部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第17个课程,主要讲解LCD1602和LCD12864这两种单片机常用LCD显示器的显示原理、以及英文、中文、图片等如何编程显示。本课程对于显示编程具有重要的启蒙作用,是学习各种深入复杂的显示知识的基础。

    4088 人正在学习 去看看 朱有鹏

数码管显示分为静态数码管显示动态数码管显示
学习掌握数码管相关的内容,可以从以下三方面入手:
1.数码管电路图
2.译码器
3.进制转化

直接上图

数码管电路图

在这里插入图片描述
数码管电路的接法有共阴和共阳两种,这里采用共阴接法
从其中取出一个数码管进行分析
单个数码管
在这里插入图片描述
此处为一个8位的数码管,想要数码管显示出想要的数字,则需要对数码管进行高低电平的设置
1为高电平,0为低电平
分别对 a,b,c,d,e,f,g,dp进行1和0的编写,此处可以理解为二进制进行十六进制的转化
在这里插入图片描述
如图中所示,数字2的 八位二进制就可以表示为 0101 1011,读数为从dp依次读到a,转化为十六进制则是0x5b
数码管中各个数值对应的字节
0: 0x3f 1: 0x06 2: 0x5b 3: 0x4f 4: 0x66 5: 0x6d 6: 0x7d 7: 0x07
8: 0x7f 9: 0x6f A: 0x77 B: 0x7c C: 0x39 D: 0x5e E: 0x79 F: 0x71

在这里插入图片描述
打开电脑中的计算器中的程序员模式就可以进行检验
下面就剩译码器的问题,本次采用的138译码器,译码器的不同可能会有所差别

先来了解下138译码器的电路图
在这里插入图片描述
在138译码器中主要是P22,P23,P24管角的问题,三个管角对数码管LED1~8的控制

138译码器

管角定义
在这里插入图片描述
管角说明
在这里插入图片描述
真值表
在这里插入图片描述
看懂138译码器的真值表非常重要,H代表高电平,L代表低电平,当A0,A1,A2同时为L时,Y0(LED1)才会亮

简单代码演示

#include "reg51.h"
typedef unsigned char u8;
typedef unsigned int u16;

sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

u8 code dizhi[]={0x3f,0x5e};

void main(){
   LSC=0;		   
   LSA=0;
   LSB=0;
   P0=dizhi[0];
}

通过按键实现数码管转化视频

2018-08-27 21:49:25 zlllg 阅读数 7501
  • LCD1602和12864显示器-第1季第17部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第17个课程,主要讲解LCD1602和LCD12864这两种单片机常用LCD显示器的显示原理、以及英文、中文、图片等如何编程显示。本课程对于显示编程具有重要的启蒙作用,是学习各种深入复杂的显示知识的基础。

    4088 人正在学习 去看看 朱有鹏

数码管作为最廉价的输出设备,在各种自动化设备中有很大的应用,最简单普通的显示方式为动态刷新显示,称为假动态显示,即通过分时扫描每一位,利于人眼的视觉停留现象,造成一种静态显示的效果,如下图所示:

C51单片机由于运行速度很慢,在高刷新频率下,单片机的资源耗费很厉害,这样单片机就不可以再进行大量的计算工作,实际上,单片机在刷新时,只需要周期性的改变GPIO口的状态就可以了,剩下的时间其实都是在空转的状态下,我们能不能将这个空转的状态拿来用呢?当然是可以的啦,这里,我们利用单片机的定时器周期地产能中断,在中断内进行数码管的刷新工作,就可以将等待中断的这个CPU时间拿来做别的事情了。

硬件电路:

代码贴过来:

主函数

#include "shumaguan.h"
#include "timer.h"


sbit sw_jdq=P1^0;//定义一位继电器操作
void main(void)
{
  int cnt=0;//设定初值
  timer_init();//初始化定时器
  while(1)
  {
    value_now = cnt;//送初值到显示缓存
    delay(50);
    cnt++;
    sw_jdq=~sw_jdq;//切换继电器状态
    if(cnt>9999)//数值超出界线,回归最小
      cnt=-999;
  }
}

数码管驱动函数

#include "shumaguan.h"

#define DType	1			//define the Digital LED type, 1: VCC in common, 0: GND in common
#if DType==1
/*--------------------------------------------------------
Set the digital LED display code 
From left to right for
0,1,2,3,4,5,6,7,8,9,a.b,c,d,e,f,dp,-, 
--------------------------------------------------------*/
uchar code DS_BUF[]={0xc0 , 0xf9 , 0xa4 , 0xb0 , 0x99 , 0x92 , 0x82 , 0xf8 , 0x80 , 0x90 , 0x88 , 
0x83 , 0xc6 , 0xa1 , 0x86 , 0x8e , 0x7f , 0xbf , 0xff };
#else
uchar code DS_BUF[]={0x3f , 0x06 , 0x5b , 0x4f , 0x66 , 0x6b , 0x7d , 0x07 , 0x7f , 0x6f , 0x77 , 
0x7c , 0x39 , 0x5e , 0x79 , 0x71 , 0x80 , 0x40 , 0x00 };
#endif
uchar xdata buf_sm[4];            //set display buffer
  
uchar frash_cnt=0;//刷新计数器
uchar wei_buf=0x10;//位输出计数器
 
/*--------------------------
Compute the number from Value
value: something to display, range from -999 to 9999, suport float
--------------------------*/
void calc_sm(float value)
{
	uint tmp=0;
	if(value>=0)//输入值为正数,不显示负号
	{
		if(value>9999)//输入值大于9999,显示----
		{
			buf_sm[0]=17;
			buf_sm[1]=17;
			buf_sm[2]=17;
			buf_sm[3]=17;
		}
		else if(value>=1000)//输入值大于999,只显示整数
		{
			tmp=value;
			buf_sm[0]=tmp/1000;
			buf_sm[1]=tmp%1000/100;
			buf_sm[2]=tmp%100/10;
			buf_sm[3]=tmp%10;
		}
		else if(value>=100)//显示一位小数
		{
			tmp=value*10;
			buf_sm[0]=tmp/1000;
			buf_sm[1]=tmp%1000/100;
			buf_sm[2]=(tmp%100/10)+20;
			buf_sm[3]=tmp%10;
		}
		else if(value>=10)//显示两位小数
		{
			tmp=value*100;
			buf_sm[0]=tmp/1000;
			buf_sm[1]=(tmp%1000/100)+20;
			buf_sm[2]=tmp%100/10;
			buf_sm[3]=tmp%10;
		}
		else//显示三位小数
		{
			tmp=value*1000;
			buf_sm[0]=(tmp/1000)+20;
			buf_sm[1]=tmp%1000/100;
			buf_sm[2]=tmp%100/10;
			buf_sm[3]=tmp%10;
		}
	}
	else//输入值小于0,显示负号,其余同上
	{
		if((value<0)&&(value>-10))
		{
			tmp=value*100;
			tmp=abs(tmp);
			buf_sm[0]=17;
			buf_sm[1]=(tmp/100)+20;
			buf_sm[2]=tmp%100/10;
			buf_sm[3]=tmp%10;
		}
		else if((value<=-10)&&(value>-100))
		{
			tmp=value*10;
			tmp=abs(tmp);
			buf_sm[0]=17;
			buf_sm[1]=(tmp/100);
			buf_sm[2]=tmp%100/10+20;
			buf_sm[3]=tmp%10;
		}
		else if((value<=-100)&&(value>-1000))
		{
			tmp=value;
			tmp=abs(tmp);
			buf_sm[0]=17;
			buf_sm[1]=(tmp/100);
			buf_sm[2]=tmp%100/10;
			buf_sm[3]=tmp%10;
		}
    
	}
  
}
/*
显示部分,每执行一次,显示的位左移一位,移到最左边时,重新回到最右边,开始下一次刷新。
定义有小数点的位+20,每次送断码,检查大于20,段与0x7f添加小数点。
*/
void display()
{
  if(frash_cnt<=3)
  {
    wei |=0xf0;//数码管的消隐
    
    if(buf_sm[3-frash_cnt]>=20)
    {
      duan = (DS_BUF[(buf_sm[3-frash_cnt])-20]&0x7f);//显示小数点
    }
    else
      duan = DS_BUF[buf_sm[3-frash_cnt]];//不显示小数点
    
    wei = ~wei_buf;
    wei_buf <<=1;//显示位左移一位
    frash_cnt++;
  }
  else
  {
    wei |=0xf0;//数码管的消隐
    frash_cnt=0;
    wei_buf=0x10;//显示位回到最右边
  }
}
/*
数码管自用延时
*/
void delay(uint i)
{
  uchar j;
  for(;i>0;i--)
  for(j=0;j<120;j++);

}

数码管头文件

#ifndef _shumaguan_h_
#define _shumaguan_h_
#include "math.h"
#include "reg52.h"
#define duan P0
#define wei P2

#define uchar unsigned char
#define uint unsigned int
  
extern uchar frash_cnt;
extern uchar wei_buf;

void calc_sm(float value);
void display();
void delay(uint i);


#endif

定时器配置及中断服务函数

#include "reg52.h"
#include "timer.h"
#include "shumaguan.h"


float xdata value=0 , value_now = 0;

void timer_init()
{
  TMOD = 0x02;                    //set timer0 as mode1 (16-bit)
  TL0 = T1MS;                     //initial timer0 low byte
  TH0 = T1MS;                //initial timer0 high byte
  TR0 = 1;                        //timer0 start running
  ET0 = 1;                        //enable timer0 interrupt
  EA = 1;                         //open global interrupt switch
}



/* Timer0 interrupt routine */
void tm0_isr() interrupt 1 using 1
{
    if(value!=value_now)//检测显示值与当前值是否匹配
    {
      value=value_now;//刷新显示值
      calc_sm(value_now);//重新计算显示值的输出缓冲区
    }
    display();//刷新数码管显示

}

定时器头文件

#ifndef _timer_h_
#define _timer_h_
#include "reg52.h"
#define uchar unsigned char
#define uint unsigned int
  
//-----------------------------------------------

/* define constants */
//#define FOSC 11059200L
#define FOSC 12000000L

#define T1MS 0   //1ms timer calculation method in 12T mode


//-----------------------------------------------

extern float xdata value , value_now;


void timer_init();


#endif

 

2017-01-20 12:45:28 fhb1922702569 阅读数 633
  • LCD1602和12864显示器-第1季第17部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第17个课程,主要讲解LCD1602和LCD12864这两种单片机常用LCD显示器的显示原理、以及英文、中文、图片等如何编程显示。本课程对于显示编程具有重要的启蒙作用,是学习各种深入复杂的显示知识的基础。

    4088 人正在学习 去看看 朱有鹏
 #include<reg52.h>
// unsigned int LED[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
//unsigned char LED[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7d,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
unsigned char  seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
unsigned char  wei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};


 sbit LATCH_seg = P2^2;
 sbit LATCH_bit = P2^3;
void delay(unsigned int n);
void show1(unsigned int n);
void show2();


 void main()
 {
      //show1(8);
 show2();


 }


 void delay(unsigned int n)
 {
while(--n);
 }


void show2()
{
unsigned int i;
while(1)
{
for(i = 0;i < 8;i++)
{
show1(i);
}
}
}


 void show1(unsigned int n)
 {
    unsigned char w;
unsigned int m,i,j;
w = 0x01;
m = 400;
i = n;
j = n + 8;
    while(--m)
{
  /*P1=0x4f; //取位码 
       LATCH_bit=1;     //位锁存
       LATCH_bit=0;


       P0=0x7d; //取显示数据
       LATCH_seg=1;     //段锁存
       LATCH_seg=0; */
  P1 = seg[n] ;
  LATCH_seg = 1;
  LATCH_seg = 0;
  P1 = ~w ;  
  LATCH_bit = 1;
  LATCH_bit = 0; 


  w <<= 1;
  if(w == 0x00)
  {
      w = 0x01;
  } 
       /*w >>= 1;
  if(w == 0x00)
  {
      w = 0x80;
  }*/
  


  delay(300);
  n++;
  if(n == j)
  {
      n = i;
  } 
}
 }
没有更多推荐了,返回首页