2015-09-05 16:26:35 yunfeiyang62 阅读数 19228
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

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

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-05-24 14:00:13 Entronk_star 阅读数 952
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

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

/***************************************/

该代码使用的硬件有DHT11温湿度传感器、lcd1602,at89c52单片机,外加按键电位器等器件,具体电路图没有给出,但应该问题不大,电路按照各模块的数据手册要求的来就行,很简单(lcd接线两种方式,和我的不同的话,代码略有不同,自己琢磨)。

此外改代码没有写报警功能,只写显示功能。虽然运行成功过,但是我只是在keil上把代码复制过来,可能会因为文字格式不兼容导致一些复制不一样,仅供参考不一定完全正确。欢迎大佬评论区指点错误,或者分享更好的算法

注释我已经尽量给详细,若还不懂只能看数据手册了,太多细节不好在这赘述,我只解释算法

/***************************************/

#include <reg52.h>
#include <intrins.h> 
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
 uchar com,flag;
uchar n,m,y,x,v,u,a1,a2; //温湿度上下限的参数,其中,n m是温湿度超标与否的标准,值为0或者1。这代码的温湿度报警没有用LED或者蜂鸣器,只用了一个软件参数n、m存储报警信息。需要添加报警功能的可以自己写额外的功能代码,然后nm两个参数就是功能传递参数。也可以写多一个串口输出代码,用串口调试助手输出n、m的值验证温湿度是否超标判断正确。
void Delay1000ms()        //@11.0592MHz延时
{
    unsigned char i, j, k;

    _nop_();
    i = 8;
    j = 1;
    k = 243;
    do
    {
        do
        {
            while (--k);
        } while (--j);
    } while (--i);
}
void Delay500us()        //@11.0592MHz
{
    uchar b;

    _nop_();
    b = 227;
    while (--b);
}
void Delay10us()        //@11.0592MHz
{
    uchar a;

    a = 2;
    while (--a);
}
void delay(uint z)
{
 uchar i,j;
 for(i=z;i>0;i--)
  for(j=110;j>0;j--);                 //ÑÓʱº¯Êý
}
//************************引脚定义*************

/*******按键控制引脚定义*********/
sbit y_tem_inse=P1^0;        //

sbit y_tem_duce=P1^1;           //

sbit x_tem_inse=P1^2;         //

sbit x_tem_duce=P1^3;         //

sbit u_hum_inse=P1^4;           //

sbit u_hum_duce=P1^5;         //

sbit v_hum_inse=P1^6;           //

sbit v_hum_duce=P1^7;          //

/***********其他功能引脚*****/
sbit DQ=P2^1;    //DTH11

//****LCD的****
sbit RS=P2^7;
sbit RW=P2^6;
sbit EN=P2^5;
#define DataPort P0 //LCD的接线,我的是8线接发
//-----------------函数声明-------------
void delay_us(uchar t);               
void delay_ms(uchar t);
bit LCD_Check_Busy(void);
void LCD_Write_Com(uchar com);
void LCD_Write_Data(uchar Data);
void LCD_Clear(void);
void LCD_Write_String(uchar x,uchar y,uchar *s);
void LCD_Write_Char(uchar x,uchar y,uchar Data);
void LCD_Init(void);
void COMdata();
//*************************以下是函数定义***************************
//**************液晶屏显示原函数由此开始*************************
bit LCD_Check_Busy(void) //检忙

    DataPort= 0xFF; 
    RS = 0;
    RW = 1;
    EN = 0;
    _nop_(); 
    EN = 1;
    return (bit)(DataPort & 0x80);
}
void LCD_Write_Com(uchar com) //写指令原函数
{  
    while(LCD_Check_Busy());
    RS = 0;
    RW = 0;
    EN = 1;
    DataPort= com; 
    _nop_(); 
    EN = 0;
}
void LCD_Write_Data(uchar Data) //写数据原函数

    while(LCD_Check_Busy());
    RS = 1; 
    RW = 0;
    EN = 1;
    DataPort= Data; 
    _nop_();
    EN = 0;
}
void LCD_Clear(void)  //清屏

    LCD_Write_Com(0x01); 
    delay(1);
}
void LCD_Write_String(uchar x,uchar y,uchar *s)   //操作-显示LCD屏的哪个位置
{     
    if (y == 0)      
        LCD_Write_Com(0x80 + x);
    else     
        LCD_Write_Com(0xC0 + x); 
    while (*s) 
    {     
    LCD_Write_Data( *s);     
    s ++;     
    }
}
void LCD_Write_Char(uchar x,uchar y,uchar Data) //操作-显示的数据(字符类型,显示数字需找到该数字的ASCII码)
{     
    if(y == 0)   
        LCD_Write_Com(0x80 + x);  
    else   
        LCD_Write_Com(0xC0 + x);       
    LCD_Write_Data( Data);  
}
void LCD_Init(void) //LCD初始化(可以理解为唤醒)
{
    delay(15); 
    LCD_Write_Com(0x38); 
    delay(5); 
    LCD_Write_Com(0x38); 
    delay(5); 
    LCD_Write_Com(0x38); 
    delay(5); 
    LCD_Write_Com(0x38);  
    LCD_Write_Com(0x08); 
    LCD_Write_Com(0x01);  
    LCD_Write_Com(0x06); 
    delay(5); 
    LCD_Write_Com(0x0C);  
}
//****************LCD源码结束***********
//*********DHT11原函数以下开始*******
//***************************************************
uchar code ASCII[]="0123456789%c"; //普通数字需用该数组转成字符
uchar code table0[]="Hum:";
uchar code table1[]="Tem:";
uchar tem;
uchar hum;
display0[2]={0,0};
display1[2]={0,0};
//*************************初始化DTH11
     void  COMdata()   //读数据
      { uchar i,t;
       for(i=0;i<8;i++)       
       {
        flag=2;    
           while((!DQ)&&flag++);
        Delay10us();
         Delay10us();
        Delay10us();         //先看懂DHT11的工作时序图就知道我这个延时操作的含义了,读高电平多少秒可以对应数据0或1
          t=0;
         if(DQ) t=1;
            flag=2;
         while((DQ)&&flag++);          
            if(flag==1)break;            
           com<<=1;
              com|=t;        
         }
       
    }    
    void RH(void)     //该函数包括唤醒DHT11发送数据给单片机也包括单片机把数据提取
    {  DQ=0;
       delay(21);
       DQ=1;
    Delay10us();
     Delay10us();
           Delay10us();
               Delay10us();
       DQ=1;      
       if(!DQ)        
       {
       flag=2; 
       while((!DQ)&&flag++);
      flag=2;
       while((DQ)&&flag++);
       COMdata();
       hum=com;
       COMdata();
       COMdata();
       tem=com;
       COMdata();
       COMdata();   //小数位这里我不显示,所以不用读取tem或hum第二次的COMdata()函数获取的数据
                  DQ=1;
       }
    }

//*********************************LCD显示温湿度数据
void Display_DTH11()
{
uchar xh,xl,yh,yl,vh,vl,uh,ul;
xh=x/10%10; 
xl=x%10;
yh=y/10%10; 
yl=y%10;
uh=u/10%10; 
ul=u%10;
vh=v/10%10; 
vl=v%10;
LCD_Write_String(8,  0, "L");
LCD_Write_Char(9,  0, ASCII[uh] );
LCD_Write_Char (10,  0, ASCII[ul] );
LCD_Write_String(12,  0, "H");
LCD_Write_Char(13,  0, ASCII[vh] );
LCD_Write_Char (14,  0, ASCII[vl] );
LCD_Write_String(8,  1, "L");
LCD_Write_Char(9,  1, ASCII[xh] );
LCD_Write_Char (10,  1, ASCII[xl] );
LCD_Write_String(12,  1, "H");
LCD_Write_Char(13,  1, ASCII[yh] );
LCD_Write_Char (14,  1, ASCII[yl] );
display0[1]=hum/10%10;                               //读hum十位
display0[0]=hum%10;                                    //个位
LCD_Write_String(0,  0, table0);
LCD_Write_Char(4,  0, ASCII[ display0[1] ] ); 
LCD_Write_Char (5,  0, ASCII[ display0[0] ] );
LCD_Write_Char (6, 0, ASCII[10] );    //显示在LCD的第几行第几位(这一行是指在第0行,第6位开始显示 ASCII[10] 里面的字符数据,下同),运行结果是显示了“hum:”这四个字符
display1[1]=tem/10%10;            
display1[0]=tem%10;                                 
LCD_Write_String(0,  1, table1);
LCD_Write_Char (4,  1, ASCII[ display1[1] ] );
LCD_Write_Char (5,  1, ASCII[ display1[0] ] );
LCD_Write_Char (6, 1, 0xdf );
LCD_Write_Char (7, 1, ASCII[11] );     
}

//***************原函数结束*************
//
void keyscan()
{
if(y_tem_inse==0)
{    delay(10);
if(y_tem_inse==0)   //这里是消抖,下同
  { y=y+5;
  while(y==55)
   y=50;        
while(y_tem_inse==0);    
}
}
if(y_tem_duce==0)
 { delay(10);
if(y_tem_duce==0); 
{
y=y-5;     
while(y==5)         
y=10;
while(y_tem_duce==0);
}
}
if(x_tem_inse==0)
{    delay(10);
if(x_tem_inse==0)    
{ x=x+5;     
 while(x==55)
 x=50;
while(x_tem_inse==0);    

}
if(x_tem_duce==0)
 {
  delay(10);
if(x_tem_duce==0);
{x=x-5;     
while(x==5)
 x=10;    
while(x_tem_duce==0);
}
}
if(u_hum_inse==0)
{    delay(10);    
if(u_hum_inse==0)    

u=u+5;      
while(u==85)
 u=80;        
while(u_hum_inse==0);    

}
if(u_hum_duce==0)
{  delay(10);    
if(u_hum_duce==0);
{
u=u-5;     
while(u==25)
  u=30;     
while(u_hum_duce==0); 
}
}
if(v_hum_inse==0)
{    delay(10);
if(v_hum_inse==0)    

v=v+5;      
while(v==85)
 v=80;        
while(v_hum_inse==0);    
}
 }
 if(v_hum_duce==0)
{  delay(10);    
if(v_hum_duce==0);
{v=v-5;     
while(v==25)         
v=20;     
while(v_hum_duce==0);
}
}
}
//*******************************上面是按键扫描,以下开始是主函数
main()
{

LCD_Clear();
x=10,y=50,u=30,v=80;  //温湿度上下限初值,按键函数里可调
tem=0;   
hum=0;     //赋初值
LCD_Init();       
Delay1000ms();    //DTH11上电一秒后才工作正常
while(1)
{
EA=0;
keyscan();
RH();
if((tem>y)||(tem<x)) n=1;
else n=0;  //LED或蜂鸣器亮灭判断,下同
if((hum>v)||(hum<u)) m=1;
else m=0;
Display_DTH11();
Time0_Init();
Delay1000ms();
Delay1000ms();
Delay1000ms();
}
}

2019-11-28 22:36:11 weixin_44223883 阅读数 303
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

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

单片机音乐盒完整代码

该设计是使用C51单片机制作的音乐盒制作的一个音乐盒,可以实现进行歌曲的切换,暂停/播放。此外还增加了随机点歌,获取大气温湿度等功能。使用LCD1602显示器进行歌曲名称和大气温湿度的显示。将完整代码帖在下面,有需要的可以自己获取。完整代码可以在我的博客下面,我的资源下面进行下载使用。

由于我上传的资源需要积分,所以我重新更新了代码,现在以将完整代码贴出,有需要的可以自己看一下,如果遇到有什么问题的可以问一下我。如果觉得还行的请帮我点个赞,谢谢大家。

如果下面贴出的代码,大家不能看懂的,或者使用有麻烦的可以给我私信。

下面是一些实物图片

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

部分代码如下

main.c

#include "main.h"
#include "delay.h"
#include "beep.h"

uchar RH,RL,TH,TL;//定义变量用来存储温湿度变量的值

extern uchar timer1h, timer1l,time,K_Value,Singin_interface,Start,Stop;
extern char Number;



extern uchar code Player_Number1[9];


uchar KEY;//定义变量保存键值信息


//自定义1602显示心形字符
uchar code table1[]=
{   0x03,0x07,0x0f,0x1f,0x1f,0x1f,0x1f,0x1f,
    0x18,0x1E,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,
    0x07,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,
    0x10,0x18,0x1c,0x1E,0x1E,0x1E,0x1E,0x1E,
    0x0f,0x07,0x03,0x01,0x00,0x00,0x00,0x00,
    0x1f,0x1f,0x1f,0x1f,0x1f,0x0f,0x07,0x01,
    0x1f,0x1f,0x1f,0x1f,0x1f,0x1c,0x18,0x00,
    0x1c,0x18,0x10,0x00,0x00,0x00,0x00,0x00,//心图案
};

//定义流水灯断码
uchar code LED1[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40};
	


//定时器初始化函数
void  timer_init()
{
    TMOD=0x11;//定时器0和1都工作再方式一
	  TH0=(65536-30000)/256;
	  TL0=(65536-30000)%256;
	  EA=1;//开总中断
	  //开定时器中断
	  ET0=1;
    ET1=1;
    TR1=0;//首先关闭定时器T1
	  TR0=1;//开启定时器T0
	  PT1=1;
    PT0=0;

}


void  main()
{
    uchar i;
	  uchar flag1=0;
	  Player=1;
    Last_Song=1;
    Next_Song=1;
	  Choose_Song=1;//点歌按钮
    Confirmation=1;//确定按钮
   
	  P0=0xff;
    timer_init();
    lcd_init ();
    delay (50);
    
	
	  //向1602写入自定义字符
    Write_CGRAM(0x40,table1);
	
	  //再1602上显示自定义字符
	  //显示字符的前四位
    lcd_pos (0x0c);
    for(i=0; i<4; i++)
    {
        lcd_wdat(i);
    }
		//显示自定义字符的后四位
    lcd_pos (0x4c);
    for(i=4; i<8; i++)
    {
        lcd_wdat(i);
    }
		
		//在1602上显示自定义布局
		lcd_pos(0x00);
		lcd_word("T:");
		//温度
		lcd_pos(0x04);
		lcd_wdat(0xdF);
		lcd_wdat('C');
		//湿度
		lcd_pos(0x07);
		lcd_word("H:");
		lcd_pos(0x0b);
		lcd_wdat('%');
		
		
    lcd_pos (0x40);
    lcd_word("Sg:");

    lcd_word(Player_Number1);
    while(1)
    {	
					  Song(Number);  

		}			
        
}



void t0int() interrupt 1
{
	
	 static uchar Num0=0,Num1=0,i=0;
	
	 TH0=(65536-30000)/256;
	 TL0=(65536-30000)%256;
	 Num1++;	 
	//表示没有处于点个界面中,则进行数据刷新
	 if(Singin_interface==0)
	 {
	 Num0++;
	 if(Num0==90)//控制定时2.7秒钟,用来刷新数据
	 {		
	   receive();		 
		 //显示温湿度
     lcd_pos(0x02);
     lcd_wdat(TH/10+0x30);
		 lcd_wdat(TL%10+0X30);
		 
		 //显示湿度
		 lcd_pos(0x09);
     lcd_wdat(RH/10+0X30);
		 lcd_wdat(RL%10+0X30);
		 
		 Num0=0;
		
	 }
 }
	 
 
 //表示处于点歌界面中
 else if(Singin_interface==1)
 {
	     if(Start==1&&Stop==0)
			 {
        Number=rand_init();
        lcd_pos(0x48);
	      lcd_wdat(Number+0x30);
			 }
 
 }
	
 if(Num1==5)
	 {
	    P0=LED1[i];
	    i++;
		  if(i==7)
			{
			   i=0;
			}
			Num1=0;
	 }
 
 
}

void t1_int() interrupt 3     //T0中断程序,控制发音的音调         
 {                              
       TR1 = 0;                      //先关闭T0          s
       spaker =!spaker;           //输出方波, 发音                   
       TH1 = timer1h;               //下次的中断时间, 这个时间, 控制音调高低         
       TL1 = timer1l;          
       TR1 = 1;                     //启动T0        
 }  

main.h

#ifndef _main_h
#define _main_h

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

#define uchar unsigned char
#define uint unsigned int
	
typedef bit BOOL;




sbit spaker=P1^0;//定义音频输出管脚

sbit Player=P3^2;//播放按钮
sbit Last_Song=P3^3;//上一首按钮
sbit Next_Song=P3^5;//下一首

sbit Choose_Song=P3^6;//点歌按钮
sbit Confirmation=P3^7;//确定按钮


//1602相关函数
void lcd_wcmd (uchar cmd);
void lcd_pos (uchar pos);
void lcd_wdat (uchar dat);
void lcd_init ();
void lcd_word(uchar *word);
void delay (int m);
void Write_CGRAM(uchar *adder,uchar *p);


//DHT11相关函数
void start1();
uchar receive_byte();
void receive();


//音乐发声相关函数
void song();
void key_scan();
void Song(uchar j); 
	

#endif

1602.c

/*
该文件用来编写LCD1602方面的程序

*/
#include "main.h"
#include "delay.h"


#define Dat_1602  P2//1602数据口
sbit rs=P1^7;
sbit rw=P1^6;
sbit ep=P1^5;


void delay (int m)
{
 unsigned char i,j;
 for (i=0;i<m;i++)
 for (j=0;j<253;j++);
}

//判断LCD1602是否处于忙碌状态
BOOL lcd_bz()
{
  BOOL result;
  rs=0;           // 读忙信号
  rw=1;
  ep=1;
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  result = (BOOL)(Dat_1602&0x80);
  ep=0;
  return result;
}




//向LCD62写命令
void lcd_wcmd (uchar cmd)
{
  while (lcd_bz());
  rs=0;
  rw=0;
  ep=0;
  _nop_();
  _nop_();
  Dat_1602=cmd ;
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  ep=1;
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  ep=0;
}


//指定当前LCD1602要显示字符的位置
void lcd_pos (uchar pos)
{
  lcd_wcmd (pos|0x80);
}

void lcd_wdat (uchar dat)
{
   while (lcd_bz());
  rs=1;
  rw=0;
  ep=0;
  _nop_();
  _nop_();
  Dat_1602=dat ;
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  ep=1;
  _nop_();
  _nop_();
  _nop_();
  _nop_();
  ep=0;
}


//LCD1602初始化
void lcd_init ()
{
  lcd_wcmd (0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口
  delay (1);
  lcd_wcmd (0x0c); //显示模式设置:光标右移,字符不移  
  delay (1);
  lcd_wcmd (0x06); //显示模式设置:光标右移,字符不移  
  delay (1);
  lcd_wcmd (0x01); //清屏幕指令,将以前的显示内容清除 
  delay (1);


}
//向LCD1602发送字符串
void lcd_word(uchar *word)
{
   uchar i=0;
	 while(word[i]!='\0')
	 { 
	   lcd_wdat(word[i]);
		 i++;
	 }

}


//LCD1602自定义字符函数
void Write_CGRAM(uchar *adder,uchar*p)
{

    //uchar LOL=0x40;//操作CGRAM的命令码
    uchar i,j,V=0;
	  for(j=0;j<8;j++)
	{
	  for(i=0;i<8;i++)
	  {
	     lcd_wcmd(adder+i);
			 lcd_wdat(p[V]); 
       V++;			
	  }
		adder+=8;
	}

}


delay.h

#include "main.h"
#include "math.h"
#include "stdio.h"





void delay1(uchar t)
{
 uchar t1;
unsigned long t2;
for(t1=0;t1<t;t1++)
{
for(t2=0;t2<8000;t2++)
{
   ;
}
}
TR0=0;
}





void delay8us()//一个FOR循环大概需要8个机器周期,一个机器周期大约是1us也就是说12MHZ的晶振对此函数的延时
//是8US多 所以此延时函数更精确
{
    unsigned char i;
    for(i = 0; i < 1; i++);

}


//定义延时函数
void delay_WO(unsigned char ms)
{
    unsigned char i;
    while(ms--)
        for(i = 0; i < 100; i++);

}


void delay_player(unsigned char t)    //延时子函数,控制发音的时间长度
{   uchar t1;
    unsigned long t2;
    for(t1 = 0; t1 < t; t1++)          //嵌套循环, 共延时t个半拍
    for(t2 = 0; t2 < 8000; t2++); //延时期间, 可进入T0中断去发音   8
    TR1 = 0;                        //关闭T0, 停止发音

}


void Delay5ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 59;
	j = 90;
	do
	{
		while (--j);
	} while (--i);
}


void Delay100ms()		//@12.000MHz
{
	unsigned char i, j, k;

	_nop_();
	_nop_();
	i = 5;
	j = 144;
	k = 71;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}



//随机数产生函数
unsigned char rand_init()
{
    uchar i;
    i=rand()%8;
    return i;
}

dht11.c

#include "main.h"
#include "delay.h"

//DHT11的数据管脚
sbit io=P1^4;

uchar data_byte;

extern uchar RH,RL,TH,TL;




//单片机发送开始信号
void start1()
{
   io=1;
   delay8us();
   io=0;
   delay_WO(25);
   io=1;
   delay8us();
   delay8us();
   delay8us();



}

uchar receive_byte()
{
  unsigned char i,temp;
  for(i=0;i<8;i++)
  {
    while(!io);
	delay8us();
	delay8us();
	delay8us();
	temp=0;
	if(io==1)
	temp=1;
	while(io);
	data_byte<<=1;
	data_byte|=temp;
  }
  return data_byte;
}

void receive()
{
  uchar T_H,T_L,R_H,R_L,check,num_check,i;
	start1();
	io=1;
	if(!io)
	{
	   while(!io);
	   while(io);
	   R_H=receive_byte();
	   R_L=receive_byte();
	   T_H=receive_byte();
	   T_L=receive_byte();
	   check=receive_byte();
	   io=0;
	   for(i=0;i<7;i++)
	   delay8us();
	   io=1;		
	   num_check=R_H+R_L+T_H+T_L;
	   if(num_check==check)
	   {
	   	RH=R_H;
		  RL=R_L;
		  TH=T_H;
		  TL=T_L;
		  check=num_check;	   	   
	   }
	
	}

}

beep.c

#include "main.h"
#include "delay.h"
#include "beep.h"


// 频率-半周期数据表 高八位     本软件共保存了四个八度的28个频率数据
uchar code FREQH[] = {     0xF2, 0xF3, 0xF5, 0xF5, 0xF6, 0xF7, 0xF8,    //低音1234567
                           0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC,//1,2,3,4,5,6,7,i
                           0xFC, 0xFD, 0xFD, 0xFD, 0xFD, 0xFE,            //高音 234567
                           0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF
                     };   //超高音 1234567
// 频率-半周期数据表 低八位
uchar code  FREQL[] = {    0x42, 0xC1, 0x17, 0xB6, 0xD0, 0xD1, 0xB6,    //低音1234567
                           0x21, 0xE1, 0x8C, 0xD8, 0x68, 0xE9, 0x5B, 0x8F, //1,2,3,4,5,6,7,i
                           0xEE, 0x44, 0x6B, 0xB4, 0xF4, 0x2D,             //高音 234567
                           0x47, 0x77, 0xA2, 0xB6, 0xDA, 0xFA, 0x16
                      };   //超高音 1234567              //----------------------------------------------------------------------------------------------
// 要想演奏不同的乐曲, 只需要修改这个数据表
uchar code music[8][500] = {

    //乡间小路数据表
    {
        3,1,2, 3,1,1, 3,1,1, 6,0,1, 6,0,1, 1,1,2, 6,0,1, 5,0,1, 6,0,4, 6,0,2, 6,0,1 ,6,0,1, 6,0,2, 6,0,1,
        1,1,1, 2,1,2, 2,1,1, 3,1,1, 2,1,4, 3,1,1, 3,1,1, 3,1,1, 2,1,1, 4,1,2, 4,1,2, 3,1,2, 2,1,1, 1,1,1,
        2,1,4, 7,0,1, 7,0,1, 7,0,1, 6,0,1, 5,0,1, 5,0,1, 6,0,1, 7,0,1, 7,0,1, 6,0,1, 5,0,1, 6,0,4, 6,1,2,
        3,1,1, 6,1,1, 7,1,1, 6,1,1, 5,1,1, 5,1,2, 5,1,1, 2,1,1, 5,1,1, 6,1,1, 5,1,1, 4,1,1, 4,1,2, 4,1,1,
        3,1,1, 2,1,2, 1,1,1, 2,1,1, 3,1,1, 2,1,1, 1,1,1, 2,1,1, 3,1,4, 6,1,2, 3,1,1, 6,1,1, 7,1,1, 6,1,1,
        5,1,1, 5,1,2, 2,1,1, 5,1,1, 6,1,1, 5,1,1, 4,1,1, 4,1,2, 4,1,1, 5,1,1, 6,1,1, 4,1,1, 3,1,1, 2,1,2,
        2,1,2, 5,1,4, 0,0,0
    },

    // 送别数据表
    {   5,1,2, 3,1,3, 5,1,1, 1,2,3, 6,1,2, 1,2,2, 5,1,4,
        5,1,2, 1,1,1, 2,1,1, 3,1,2, 2,1,1, 1,1,1, 2,1,4,
        5,1,2, 3,1,1, 5,1,1, 1,2,2, 7,1,1, 6,1,2,
        1,2,2, 5,1,4, 5,1,2, 2,1,1, 3,1,1, 4,1,2, 7,0,1,
        1,1,4, 6,1,2, 1,2,2, 1,2,4, 7,1,2, 6,1,1, 7,1,1,
        1,2,4, 6,1,1, 7,1,1, 1,2,1, 6,1,1, 6,1,1, 5,1,1,
        3,1,1, 1,1,1, 2,1,8, 5,1,2, 3,1,1, 5,1,1, 1,2,2,
        7,1,1, 6,1,2, 1,2,2, 5,1,4, 5,1,2, 2,1,1, 3,1,1,
        4,1,2, 7,0,2, 1,1,4, 0,0,0
    },

    //一辈子的孤单数据表
    {   5,0,1, 5,0,1, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 3,1,1, 3,1,1, 2,1,1, 2,1,4,
        5,0,1, 5,0,1, 3,1,1, 2,1,1, 2,1,1, 2,1,1, 1,1,1,
        2,1,1, 3,1,1, 3,1,4, 5,0,1, 5,0,1, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 3,1,1, 3,1,1, 2,1,1, 2,1,4, 2,1,1, 1,1,1,
        -3,1,1, 2,1,1,
        1,1,1, 2,1,1, 1,1,1, 1,1,8, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 1,1,1, 2,1,1, 2,1,6, 3,1,1, 2,1,2, 1,1,1, 1,1,1,
        -5,0,1, 6,0,1,
        5,0,1, 5,0,6, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 1,1,1, 2,1,1, 2,1,6, 5,0,1, 3,1,1, 2,1,2, 1,1,1, 2,1,2, 3,1,1,
        -3,1,4,
        5,0,1, 3,1,1, 5,1,2, 6,1,1, 3,1,1, 2,1,1, 2,1,6, 5,0,1, 3,1,1, 2,1,2, 1,1,1, 2,1,2, 3,1,1, 3,1,4,
        5,0,1, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 3,1,1, 2,1,1, 2,1,4, 2,1,1, 1,1,1, 3,1,1, 2,1,1, 1,1,1, 2,1,1, 1,1,1,
        -1,1,1, 1,1,6,
        3,1,1, 2,1,1, 2,1,1, 1,1,1, 3,1,1, 2,1,1, 2,1,6, 5,0,1, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 2,1,1, 3,1,1, 3,1,6,
        5,0,1, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 3,1,1, 2,1,1, 2,1,6, 5,0,1, 3,1,1, 2,1,1, 2,1,1, 1,1,1, 2,1,1, 3,1,1,
        -3,1,6,0,0,0
    },


    //世上只有妈妈好数据表
    {   6,2,3,      5,2,1,      3,2,2, 5,2,2, 1,3,2, 6,2,1, 5,2,1,
        6,2,4,      3,2,2,      5,2,1, 6,2,1, 5,2,2, 3,2,2, 1,2,1,
        6,1,1,      5,2,1,      3,2,1, 2,2,4, 2,2,3, 3,2,1, 5,2,2,
        5,2,1,      6,2,1,      3,2,2, 2,2,2, 1,2,4, 5,2,3, 3,2,1,
        2,2,1,      1,2,1,      6,1,1, 1,2,1, 5,1,6, 0,0,0

    },


    {   5,1,1, 5,1,1, 6,1,2, 5,1,2, 1,2,2, 7,1,4,
        5,1,1, 5,1,1, 6,1,2, 5,1,2, 2,2,2, 1,2,4,
        5,1,1, 5,1,1, 5,2,2, 3,2,2, 1,2,2, 7,1,2, 6,1,2,
        4,2,1, 4,2,1, 3,2,2, 1,2,2, 2,2,2, 1,2,4
    },

    //发如雪
    {
        5,1,1, 2,2,1, 3,2,2, 2,2,1, 3,2,1, 5,2,1, 6,2,1, 5,2,3, 1,2,1, 2,2,1,
        3,2,1, 6,2,1, 5,2,1, 3,2,1, 5,2,3, 5,2,1, 6,2,1, 1,3,2, 6,2,1, 5,2,1,
        3,2,1, 5,2,1, 3,2,2, 1,2,1, 2,2,1, 3,2,1, 1,2,1, 6,1,1, 3,2,1, 2,2,1,
        5,1,1, 2,2,1, 3,2,2, 2,2,1, 3,2,1, 5,2,1, 6,2,1, 5,2,3, 1,2,1, 2,2,1,
        3,2,1, 6,2,1, 5,2,3, 5,2,1, 6,2,1, 1,3,2, 6,2,1,
        5,2,1, 3,2,1, 5,2,1, 3,2,2, 1,2,1, 6,1,1, 3,2,1, 2,2,1, 1,2,1, 6,1,1,
        1,2,1, 2,2,1, 2,2,1, 1,2,4, 0,0,0
    },

    //当你孤单会想起谁
    {
        3,2,2, 3,2,1, 4,2,1, 3,2,2, 2,2,1, 1,2,1,  2,2,2, 5,2,2, 2,2,2, 2,2,3,
        1,2,2, 1,2,1, 2,2,1, 1,2,2, 7,1,1, 6,1,1, 7,1,2, 3,2,2, 7,1,2, 7,1,3,
        6,1,2, 2,2,1, 3,2,1, 2,2,1, 1,2,1, 6,1,2, 5,1,2, 2,2,1, 3,2,1, 2,2,1,
        1,2,1, 6,1,2, 6,1,2, 2,2,1, 3,2,1, 2,2,1, 1,2,1, 6,1,1, 7,1,1, 1,2,6, 0,0,0
    },
		
		//简单爱
    {
     5,1,1, 1,2,1, 2,2,1, 3,2,1, 2,2,1, 3,2,1, 4,2,1, 5,2,1, 5,2,1, 5,2,1, 
         4,2,1, 3,2,1, 2,2,3, 5,1,1, 1,2,1, 2,2,1, 3,2,1, 4,2,1, 5,2,1, 5,2,1, 
         5,2,1, 6,2,1, 5,2,2, 2,2,1, 3,2,1, 1,2,2, 1,2,1, 6,1,1, 2,2,1, 2,2,1, 
         3,2,1, 3,2,1, 1,2,1, 5,2,1, 1,2,1, 5,2,1, 1,2,1, 7,1,1, 1,2,1, 1,2,1, 6,1,1, 
         2,2,1, 2,2,1, 3,2,1, 3,2,1, 5,2,1, 5,2,1, 
         5,2,1, 6,2,1, 5,2,2, 2,2,1, 3,2,1, 1,2,2,  
         5,1,1, 1,2,1, 2,1,2, 3,2,1, 2,2,1, 3,2,1, 4,2,1, 5,2,1, 5,2,1, 5,2,1, 
         4,2,1, 3,2,1, 2,2,3, 5,1,1, 1,2,1, 2,2,1, 3,2,1, 2,2,1, 3,2,1, 4,2,1, 
         5,2,1, 5,2,1, 5,2,2, 2,2,1, 3,2,1, 1,2,2, 1,2,1, 6,1,1, 2,2,1, 2,2,1, 
         3,2,1, 3,2,1, 1,2,2, 5,2,1, 1,2,1, 5,2,1, 5,2,1, 7,1,1, 1,2,1, 0,0,0 }
};


//定义歌曲名字
uchar code Player_Number1[10]="1.CyRoad ";
uchar code Player_Number2[10]="2.FeWell ";
uchar code Player_Number3[10]="3.LCover ";
uchar code Player_Number4[10]="4.Mother ";
uchar code Player_Number5[10]="5.Birhday";
uchar code Player_Number6[10]="6.SnHair ";
uchar code Player_Number7[10]="7.Althink";
uchar code Player_Number8[10]="8.SimLove";


//定义9各空格来进行下一首歌曲名字的显示
uchar code Tab[9]="         ";

//定义变量Singin_interface来判断是否处于点歌界面当变量等于一时表示处于点个界面中
//定义变量Start,Stop来判断点歌的开始与停止等于一时有效
uchar Singin_interface=0,Start=0,Stop=0;



/*定义变量timer1h, timer1l来存储定时器的初值,TIME用来控制延时时间,
K_Value用来存储键值Num用来记录
音乐播放到那一首*/


uchar timer1h, timer1l,time,K_Value;
char Number=0;


//发声控制函数
void song()
{
    TH1 = timer1h;               //控制音调
    TL1 = timer1l;
    TR1 = 1;                     //启动T0, 由T0输出方波去发音
    delay_player(time);                 //控制时间长度
}


void key_scan()
{

    //判断是否按下了播放按键
    if(Player==0)
    {
        Delay5ms();
        if(Player==0)
        {
            while(Player==0);
            K_Value=1;
        }


    }


    //判断是否按下了下一首按键
    else if(Next_Song==0)
    {
        Delay5ms();
        if(Next_Song==0)
        {
            while(Next_Song==0);
            K_Value=2;
        }

    }
    //判断是否按下了上一首的按键
    else if(Last_Song==0)
    {
        Delay5ms();
        if(Last_Song==0)
        {
            while(Last_Song==0);
            K_Value=3;
        }
    }

    //判断是否按下了点歌按钮
    else if(Choose_Song==0)
    {
        Delay5ms();
        if(Choose_Song==0)
        {
            while(Choose_Song==0);
            K_Value=4;
        }

    }
    //判断是否按下了确定按钮
    else if(Confirmation==0)
    {
        Delay5ms();
        if(Confirmation==0)
        {
            while(Confirmation==0);
            K_Value=5;
        }

    }
}

//音乐播放控制函数
void Song(uchar j) 	//j表示第n+1首曲   9
{
    uchar k, i,flag_play=0;
    uchar LCD_i=0;//用来显示从点歌界面切换回来时的自定义字符
    static char flag_next_song=0,K=0;//flag_next_song用来记录切换到了那一首歌曲,i用来记录按键5按下的次数
    i = 0;
    time = 1;
    while(time)
    {
        key_scan();
       if(Singin_interface==0)
			 {
        //说明播放按钮按下了,执行相应的操作
        if(K_Value==1)
        {
            TR1=0;
            ET1=0;
            flag_play++;
            K_Value=0;
            if( flag_play==2)
            {
                flag_play=0;
                TR1=1;
                ET1=1;
            }
        }

        //切换到下一首歌曲
        else if(K_Value==2)
        {

            K_Value=0;
            //开启定时器
            TR1=0;
            ET1=0;
            flag_next_song++;

            if(flag_next_song>7)//当到最后一首歌时循环到第一首
            {

                flag_next_song=0;
            }
            Number=flag_next_song;

            //在1602上显示歌曲名字
            switch(Number)
            {
            case 0:
                lcd_pos (0x43);
                lcd_word(Player_Number1);
                break;
            case 1:
                lcd_pos (0x43);
                lcd_word(Player_Number2);
                break;
            case 2:
                lcd_pos (0x43);
                lcd_word(Player_Number3);
                break;
            case 3:
                lcd_pos (0x43);
                lcd_word(Player_Number4);
                break;
            case 4:
                lcd_pos (0x43);
                lcd_word(Player_Number5);
                break;
            case 5:
                lcd_pos (0x43);
                lcd_word(Player_Number6);
                break;
            case 6:
                lcd_pos (0x43);
                lcd_word(Player_Number7);
                break;
						case 7:
							  lcd_pos (0x43);
                lcd_word(Player_Number8);
						    break;
            default:
                break;
            }

            TR1=1;
            ET1=1;

            break;
        }

        //切换到上一首歌
        else if(K_Value==3)
        {

            K_Value=0;
            //开启定时器
            TR1=0;
            ET1=0;
            flag_next_song--;
            if(flag_next_song<0)//当到最后一首歌时循环到第一首
            {
                flag_next_song=7;
            }
            Number=flag_next_song;

            //在1602上显示歌曲名字
            switch(Number)
            {
            case 0:
                lcd_pos (0x43);
                lcd_word(Player_Number1);
                break;
            case 1:
                lcd_pos (0x43);
                lcd_word(Player_Number2);
                break;
            case 2:
                lcd_pos (0x43);
                lcd_word(Player_Number3);
                break;
            case 3:
                lcd_pos (0x43);
                lcd_word(Player_Number4);
                break;
            case 4:
                lcd_pos (0x43);
                lcd_word(Player_Number5);
                break;
            case 5:
                lcd_pos (0x43);
                lcd_word(Player_Number6);
                break;
            case 6:
                lcd_pos (0x43);
                lcd_word(Player_Number7);
                break;
						case 7:
							  lcd_pos (0x43);
                lcd_word(Player_Number8);
						    break;
            default:
                break;
            }
            TR1=1;
            ET1=1;
            break;
        }

        //表示按下了点歌按键
        else if(K_Value==4)
        {

            Singin_interface=1;//将标志为置为一表示处于点歌界面中
            TR1=0;
            ET1=0;
            K_Value=0;
            lcd_wcmd (0x01);//刷新屏幕
            lcd_pos(0x00);
            lcd_word("Hello!  Welcome!");
            lcd_pos(0x41);
            lcd_word("Start      Stop");

        }
			}
        else if(Singin_interface==1)//表示在点歌界面中
        {
            //选择点歌的开始按钮
            if(K_Value==5)
            {

                K_Value=0;
                K++;
                if(K==1)
                {
                    ET1=0;
                    TR1=0;
                    Start=1;
                    Stop=0;
                    lcd_pos(0x40);
                    lcd_wdat('*');
                    lcd_pos(0x4b);
                    lcd_wdat(' ');
                }
                else if(K==2)
                {
                    Start=0;
                    Stop=1;
                    lcd_pos(0x40);
                    lcd_wdat(' ');
                    lcd_pos(0x4b);
                    lcd_wdat('*');
                    K=0;
                    Delay100ms();//100MS开始播放选中的歌曲
                    ET1=1;
                    TR1=1;
                    Song(Number);
                }
            }

            else if(K_Value==1)//当处于点个界面时按下上一首按键时退出点歌界面
            {
							
							  K_Value=0;
                Singin_interface=0;//点歌界面标志位清零
                Start=0;
                Stop=0;
                Number=0;
							  flag_next_song=0;
                //先关闭定时器
                ET1=0;
                TR1=0;
                //Number=0;
                //进行主界面显示
                lcd_wcmd(0x01);
							  Delay100ms();
                //再1602上显示自定义字符							
                //显示字符的前四位
                lcd_pos (0x0c);
                for( LCD_i=0; LCD_i<4; LCD_i++)
                {
                    lcd_wdat(LCD_i);
                }
								 
                //显示自定义字符的后四位
                lcd_pos (0x4c);
                for( LCD_i=4;  LCD_i<8;  LCD_i++)
                {
                    lcd_wdat( LCD_i);
                }

                //在1602上显示自定义布局
                lcd_pos(0x00);
                lcd_word("T:");
                //温度
                lcd_pos(0x04);
                lcd_wdat(0xdF);
                lcd_wdat('C');
                //湿度
                lcd_pos(0x07);
                lcd_word("H:");
                lcd_pos(0x0b);
                lcd_wdat('%');


                lcd_pos (0x40);
                lcd_word("Sg:");
                lcd_word(Player_Number1);
                ET1=1;
                TR1=1;
								Song(Number);
            }
        }

        k = music[j][i] + 7 * music[j][i + 1] - 1;                            //第i个是音符, 第i+1个是第几个八度
        timer1h = FREQH[k];      //从数据表中读出频率数值
        timer1l = FREQL[k];      //实际上, 是定时的时间长度
        time = music[j][i + 2];   //读出时间长度数值
        i += 3;
        song();                  //发出一个音符
    }
}

2018-05-07 01:33:58 honorwh 阅读数 8591
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

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

本实验回顾:是关于字符型LCD的显示原理的学习以及掌握字符型LCD显示字符的用法。

1.使用LCD显示两行字符,第一行显示“hello + 英文名字”,第二行显示时间(正确的年月日)

!注意,这里使用1602是无法显示汉字的,只能显示大小写和阿拉伯数字。

(万年历实验之后有空再更新)

-------------------------------------------------------------------------分割线


原理图附上:


这里有几个主要注意:

1.如果D0-D7要接在P0口的话,必须接上拉电阻,否则仿真时会出现灰色的电平,然而直接接P2口便不需要上拉电阻。51芯片一直要注意这个问题。

2.本实验用到的LM016L虽然只有14个引脚,而实物是16个,但是这没什么关系,就少了个背光电池的引脚,其他功能一样,也就是仿真用LM016L就是1602。

3.芯片上E(使能端)直接接P3.4,RS接P3.5,RW可以直接接地,因为是读写控制端,然而本实验不需要从液晶屏读取什么,所以直接低电平即可。VDD接电源,VSS接地,D0-D7接P2。


效果图如下:


代码如下:

#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int 
uchar code table[]="HELLO HONORWH";
uchar code table1[]="2018 5 6";
sbit dula=P2^6;
sbit wela=P2^7;
sbit lcden=P3^4;
sbit lcdrs=P3^5;
sbit rw=P3^6;
uchar num;
void delayms(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=0;y<110;y++);
}
void write_com(uchar com)
{
lcdrs=0;
P2=com;
delayms(5);
lcden=1;
delayms(5);
lcden=0;
}
void write_data(uchar date)
{
lcdrs=1;
P2=date;
delayms(5);
lcden=1;
delayms(5);
lcden=0;
}
void init()
{
dula=0;
wela=0;
lcden=0;
rw=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
}
void main()
{
init();
write_com(0x80);
for(num=0;num<13;num++)
{
write_data(table[num]);
delayms(5);
}
write_com(0x80+0x40);
for(num=0;num<8;num++)
{
write_data(table1[num]);
delayms(5);
}
while(1);

}

---------------------------------------------------------分割线

博主当做简单复习,不喜勿喷。

学习内容根据《51单片机C语言编程》。

2015-03-19 10:51:52 gogoky 阅读数 4619
  • 51单片机综合小项目-第2季第4部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第2季第4个课程,也是51单片机学完之后的一个综合小项目,该项目运用了开发板上大多数外设设备,并将之结合起来实现了一个时间、温度显示以及报警功能、时间调整功能等单片机控制常见的功能,有一定代码量,需要一定调试技巧和编程能力来完成,对大家是个很好的总结和锻炼,并且能拓展项目经验。

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

利用单片机数码管的数字显示:

#include<stc15f2k60s2.h>

unsigned char CS[]={0x7f,0xbf,0xdf,0xef};
unsigned char DM[]={0x77,0x41,0x3b,0x6b,0x4d,0x6e,0x7e,0x43,0x7f,0x6f};

void Delay500ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	i = 22;
	j = 3;
	k = 227;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Delay100us()		//@11.0592MHz
{
	unsigned char i, j;

	i = 2;
	j = 15;
	do
	{
		while (--j);
	} while (--i);
}

void Delay100ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	i = 5;
	j = 52;
	k = 195;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


int main()
{
	int i,j;
	P1M1 &= ~0xff;  //P1推挽输出
   P1M0 |=  0xff;
	P0=0xff;
	j=0;
	while(1)
	{
		for(i=0;i<4;i++)
		{
			P0=CS[i];
			
			P1=DM[j];
			Delay500ms();
			
		}
		j++;
		if(j>9)
		{
			j=0;
		}
	}
	return 0;
}


没有更多推荐了,返回首页