锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

51单片机详解

时间:2022-08-25 22:30:00 j小型中间继电器转换型tp1608j继电器模块继电器3e4l6574d013tr集成电路l010k静中间继电器

前言

这是我对近几个月学习51单片机的总结。我想谈谈我对51的看法。51大致是定时器、计算器、中断器和串口的一些操作。我先谈谈51的基本操作,然后再谈Sg-超声波,90舵机,LCD1602,DHT11温湿度传感器,IIC-OLED,HC-05蓝牙模块,esp8266-01sWI-FI模块,4G模块,4驱车进行一个详细的汇总,希望能对大家有所帮助。

文章目录

  • 前言
  • 一、单片机入门
  • 1.什么是单片机?
  • 2.单片机工作的基本时间顺序
  • 3.数字电路基础
  • 四、二进制逻辑操作
  • 6.89C52的引脚图
  • 二、单片机的一些项目
    • 1.点亮一个LED&按键点亮
    • 2.LED循环点亮
    • 3.介绍振动传感器
    • 4.振动传感器点亮Led&振动传感器触发继电器Led
    • 5.433接发模块&Relay做一个简单的报警器
    • 6.定时器详解
    • 7.中断详解
    • 8.利用舵机&中断超声波&定时器是一个自动垃圾桶
    • 9.UART串口详解
    • 10.用串口向上位机发送一个字符
    • 11.通过符发送到上位机
    • 12.通过串口使用HC-05蓝牙模块,手机连接蓝牙点亮LED
    • 13.通过esp8266WI-FI模块通过上位机点亮LED
    • 14.通过4GI模块通 过上位机点亮一个LED
    • 15.Lcd1602详解
    • 16.DTH11温湿度详解
    • 17.IIC_OLED详解
    • 18.四驱小车
  • 总结

一、单片机入门

1.什么是单片机

单片机是一种具有处理数据能力的集成电路芯片中央处理器CPU、随机存储器ROM、只读存储器RAM、定时器/计算器、中断系统和IO口等功能集成到一个由硅片组成的小型计算机,从当时的4到8发展到现在的300M高速单片机。

2.单片机工作的基本时间顺序

我们都知道,所有班级的上下课时间都是通过铃声控制的。我们都知道单片机执行指令的过程是从ROM取出一个指令来执行它在各个地方的作用,那么它什么时候取指令这个顺序呢??这里介绍一个时序周期,每访问一次ROM时间是机器周期的时间

1个机器周期 = 6个状态周期 = 12小时(振荡)周期

时钟周期的频率,时钟周期:即单片机的基本时间单元=12MHZ,那时钟周期 = 1/12MHZ,时钟周期 = 1/12MHZ = 1/12000 000每秒

机器周期:即12x1/12 000 000 =0.000001s = 1us,访问一次ROM取指令的时间是1us

3.数字电路基础

电平特性

数字电路只有两种电平:高电平和低电平

高电平:5v或者3.3v,取决于单片机电源

低电平:0V

RS232电平:计算机串口电平

高电平:-12v

低电平: 12v

当我们与计算机通信时,我们必须通过元件将单片机的电平转换为计算机可以识别的电平。

四、二进制逻辑操作

"与"运算

有0得0,全1才1

1&1 = 1,1&0 = 0; 0&0 = 0;

"或"运算

一得一,全0才0;

1|1 = 1;1|0 = 1;0|0 = 0;

"非"运算

~1 = 0;~0 = 1;

6.89C52的引脚

二、单片机的一些项目

1.点亮一个LED&按键点亮

通过sbit访问单片机P2^0口,给它一个低电平,让它点亮

#include   sbit led = P2^0;//sbit定义特殊功能寄存器的位变量的功能 此时变量led就保存了p2^0的地址  void main() {    led = 0.//通过看原理图,这个io口的led低电平触发   }

点亮单片机自带的按钮

#include   sbit led = P2^0;  sbit key_open  = P3^1; sbit key_close = P3^2;  void main() {    led = 1;//先默许led关    while(1)   {     if(key_open == 0)/当按key_open它会达到低电平     {      led = 0./按下按钮打开led     }          if(key_close == 0)//按下key_close,就关闭led     {      led = 1;     }   }     }

这是通过按键开关控制点亮的led的

2.LED循环点亮

#include  #include   void main() {    P2 = 0xfe;//因为led低电平点亮 0xfe = 1111 1110,让第0点亮    while(1)  {            Delay1000ms();     P2 = P2 << 1.//然后依次左移一位= 1111 1101,让第一个点亮,依次操作后面          //循环到第7位 = 是0111 1111 然而,在每个循环左移之前,都给出了低电平   if(P2 == 0x00)//所以当 = 0111 1111 重新赋值0xfe   {           P2 = 0xfe;   }   }   }  void Delay1000ms()  ///延迟函数 {  unsigned char i, j, k;   _nop_();  i = 8;  j = 154;  k = 122;  do  {   do   {    while (--k);   } while (--j);  } while (--i); } 

3.介绍振动传感器

振动点亮led

#include  #include   sbit shake = P0^0; sbit led   = P2^0;  void main() {  led = 1;    while(1)  {   if(shake == 0)//当振动发生时 就点亮led   {    led = 0;   }     }     } 

4.振动传感器点亮Led&振动传感器触发继电器Led

继电器通过振动照亮连接在继电器上的灯

#include  #include   sbit shake = P0^0; sbit relay = P0^1;  void main() {    while(1)  {   if(shake == 0)//当发生震动打开继电器   {    relay = 0;       }     }   }

5.433接发模块&Relay做一个简单的报警器

按下433收发模块,打开继电器,让报警器响。按下后,让它停止响。当然,您也可以配备振动传感器。如果振动响,按下后停止响。

#include  #include   sbit d0 = P0^0; sbit d1 = P0^1; sbit relay = P0^7;  void main() {    while(1)  {   if(d0 == 1)   {    relay = 0;   }      if(d1 == 1)   {    relay = 1;   }  }    }

6.定时器详解

51单片机有两组定时器,一组是T0,一组是T1.因为几个定时/计数,所以叫定时器。定时的本质就是每过一个机器周期加1

定时器一共有4个模式

GATE =1,要用软件使TR0/TR1置1,才能开始工作,同时外部中断INT0/1为高电平,才能启动定时器 

C/T = 0是定时模式,=1是计数模式

#include 
#include 

sbit led = P2^0;


void Delay1000ms()		//延迟函数
{
	unsigned char i, j, k;

	_nop_();
	i = 8;
	j = 154;
	k = 122;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


void Time_Init()
{
	TMOD = 0x01;
	TL0 = 0x20;		//设置定时初值1ms,定时器初值=(2的16次方(因为我选的模式1)—x)x12/你单片机晶振的频率 = 你要设的初值(us)求出的x转换成16 进制就行了
	TH0 = 0xD1;
	TR0  = 1;
	TF0  = 0; 


}


void main()
{
	int num = 0;
	Time_Init();

	
	led = 1;//默认led为关的状态
	
	while(1)
	{
	   if(TF0 == 1)//定时好了溢出
  	{
       
	  	  ++num;//每溢出一次加1
		
				TL0 = 0x20;		//设置定时初值
				TH0 = 0xD1; 		
	 }
	 
	 if(num == 1000)//加到1000 也就是1s 打开led
			{
				led = !led;
				
			}
	 

}
	
	

}

7.中断详解

比如:你正在喝奶茶,此时发生了一个紧急事情,你就会先暂停喝奶茶,转而取处理这个紧急事情,等紧急事情处理完了,你就可以继续和奶茶了。我们把这种紧急事情叫做中断。但是如果你喝奶茶期间发生了许多事情,那就要按照紧急事情的优先级来处理。

#include 

sbit led = P2^0;

int cnt = 0;

void Time_Init()
{
	TMOD = 0x10;
	TL1 = 0x18;		//设置定时初值
	TH1 = 0xFC;
	TR1 = 1;
	TF1 = 0;//现在还没有溢出,先让他=0
	ET1 = 1;//用的T1就必须用T1中断通道
	EA = 1;
	


}



void main()
{
	Time_Init();
	led = 1;
	
	while(1);
	
}

void zd() interrupt 3
{
	TL1 = 0x18;		
	TH1 = 0xFC;
	
	cnt++;
	
	if(cnt == 500)
	{
		cnt = 0;
		led =!led;
	}
}

8.利用舵机&超声波通过中断&定时器做一个自动垃圾桶

超声波测距

#include 

sbit trig = P0^1;//发送超声波,要发送超声波,必须给trig一个10us以上的高电平
sbit echo = P0^0;//判断超声波什么时候发送和什么时候接收
sbit led  = P2^0; 

void Delay10us()		//@11.0592MHz
{
	unsigned char i;

	i = 2;
	while (--i);
}


void trig10us()
{
	trig = 0;
	trig = 1;
	Delay10us();
	trig = 0;
	
}

void Time1_Init()
{
    TMOD = 0x10;//choose 16bit 计数
    TL1 = 0;
    TH1 = 0;
}


void main()
{
    double time;
    double dis;
    Time1_Init();

    while(1)
    {

        trig10us();
        while(echo == 0);//判断超声波说明时候发送
        TR1 = 1;//开始定时
        while(echo == 1);//判断超声波什么时候返回
        TR1 = 0;//停止计时
        time = (TH1 *256 + TL1)*1;//TL1和TH1是所计的数,1是机器周期1us,time就是超声波去的时间和返回的时间
        dis = (time/2)*0.034;//因为time存放的是去和返回的时间,所以要除以2,超声波测距是340m/s换算成 34000cm/s = 34cm/ms = 0.034cm/us
        if(dis < 10)
        {
            led = 0;//open led
        }        
        else
        {
            led = 1;
        }

        TH1 = 0;
        TL1 = 0;
    }    

}

舵机 

/*
    控制舵机是通过占空比来控制的,也就是在单位时间内,你控制让它得到多少高电平
    sg90舵机最高频率是50Mhz 周期就是0.02s = 20ms,我们字舵机20ms这个周期内给它高电平控制舵机角度

     0° = 0.5ms
    45° = 1ms
    90° = 1.5ms
    135°= 2ms
    180°= 2.5ms 	

*/
#include 
#include 

sbit sg90 = P0^7;

int jd;//用于控制舵机角度
int cnt;//用于计数来判断定时器中断溢出

void Time0_Init()
{
    TMOD = 0x01;
  	TL0 = 0x33;	//定时器第八位初始化
	  TH0 = 0xFE;//定时器高八位初始化 设置定时0,5ms
    TR0 = 1;
    TF0 = 0;
    ET0 = 1;
    EA  = 1;
    
}

void Delay1000ms()		//延迟函数
{
	unsigned char i, j, k;

	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


void main()
{
    Time0_Init();
    jd = 1;
		cnt = 0;
    
    while(1)
    {
        jd = 5;
				cnt = 0;
        Delay1000ms();
        jd = 1;
				cnt = 0;
        Delay1000ms();

    }

}

void zd() interrupt 1
{
	  TL0 = 0x33;	
	  TH0 = 0xFE;
    cnt++;

    if(cnt <= jd)
    {
        sg90 = 1;
    }
    
    else
    {
        sg90 = 0;
    }

    if(cnt == 40)
    {
        cnt = 0;
    }
}

垃圾桶

#include 
#include 

sbit led = P2^0;
sbit trig = P0^1; //超声波发送 给trig至少10us高电平
sbit echo = P0^0;//怎么知道他开始发和接受的返回波
sbit dj = P0^7;
sbit key = P3^1;
int cnt = 0;
int jd;

void Time0_Init()
{
	TMOD &= 0xF0;                                    
  TMOD |= 0x01;                                            
	TL0 = 0x33;	//定时器第八位初始化
	TH0 = 0xFE;//定时器高八位初始化 设置定时0,5ms
	TR0 = 1;//开始定时
	TF0 = 0;//定时器溢出标志位
	EA = 1;//中断允许总开关
	ET0 = 1;//T0中断允许开关



}

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

	_nop_();
	i = 18;
	j = 131;
	k = 103;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


void Delay10us()		//给trig一个10us延时
{
	unsigned char i;

	i = 2;
	while (--i);
}

void Time1_Init()//初始化定时器
{
	TMOD = 0x10;
	TH1 = 0;//从0开始定时
	TL1 = 0;

}

void trig10()//给trig一个10us高电平
{
	trig = 0;
	trig = 1;//向外发送
	Delay10us();
	trig = 0;//恢复
	
}

double Read_Csb()
{
	double dis;
	double time;
	
		TH1 = 0;//从0开始定时
	  TL1 = 0;
		
		trig10();//发送一个信号
		while(echo == 0);//通过echo从高电平跳转到低电平知道已经开始发送信号了
		TR1 = 1;//信号发送开始定时
		while(echo == 1);//通过从低电平跳转到高电平知道波回来了
		TR1 = 0;//波回来了结束定时
		time=(TH1 * 256 + TL1)*1;//us为单位  计算中间进过的时间 记得数TH0和TL0相加 就是TH0左移8位 移1位 = 2;8位 = 256 ;*1.085一个机器周期
		dis = time / 2* 0.034;//距离 = 340m/s = 34000cm/s = 34cm/ms = 0.034cm/us 时间来回两次 / 2
		
	
	return dis;

}

void main()
{
	double dis;
	Time1_Init();//初始化定时器
  Time0_Init();
	jd  = 1;
	cnt = 0;
	led = 1;
	
	while(1)
	{
		dis = Read_Csb();
		
		if(dis < 10 || key == 0)
		{
			led = 0;
			jd = 5;
			Delay2500ms();
			
			
			
		}
		else
		{
			led = 1;
			jd = 1;
		}

	
	
	}
	
}	

void zd() interrupt 1 //控制脉冲
{
	cnt++;
	
	TL0 = 0x33;		
	TH0 = 0xFE;
	
	if(cnt <= jd)
	{
		dj = 1;
	}
	else
	{
		dj = 0;
	}
	if(cnt == 40)
	{
		cnt = 0;
		
	}
	


}

9.UART串口详解

串口通信

1.单工   只有一根线,只能单向传输
2.半双工 有两根线Tx、Rx,交叉连接,但是任何时候只有一个方向传输和接收
3.全双工 有两根线可以在两个方向上传输

同步和异步通信

1.同步通信 发送数据和,等待接收方回应了,才能继续发送下个数据
同步通信 必须保持双方在同一个时钟
2.异步通信 发送数据后,不等待接收方的回应,继续发送下个数据
异步通信 因为发送效率低,所以每发送一个字符,要加开始位和停止位,还要配置波特率

10.发送一个字符到上位机

#include 
#include 

void UART_Init()
{
    PCON = 0x00;//波特率不翻倍
	SCON = 0x50;//sm0 sm1 sm2 ren rb8 tb8 ti ri 每发送一个数据ti必须复位 每接收一个数据ri必须复位 ren = 1允许接收
	TMOD = 0x20;//波特率配置 方式1 9600 =(2smod/32)*t1的溢出率
	TH1  = 0XFD;//t1溢出率 = (频率/32)*(256 -TH1)
	TL1  = 0xFD;
	TR1 = 1;//打开定时器1
	
}

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

	_nop_();
	i = 71;
	j = 10;
	k = 171;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


void main()
{

	UART_Init();
	
	while(1)
	{
		Delay10000ms();
		SBUF = 'a';//每个一秒发送一个字符
	}
}

11.发送一个字符串到上位机

#include 
#include 

void UART_Init()
{
	SCON = 0x50;
	TMOD = 0x20;
	TH1  = 0XFD;
	TL1  = 0xFD;
	TR1= 1;

	
}


void Send_Bit(char Data)
{
	SBUF = Data;
	while(!TI);
	TI = 0;

}

void Send_String(char * p)
{
	
	while(*p != '\0')
	{
		
		Send_Bit(*p);
		p++;
	}

}

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 main()
{
	UART_Init();

	while(1)
	{
		Delay1000ms();
		Send_String("iverson");
	}

	
}

12.通过串口用HC-05蓝牙模块,手机连接蓝牙点亮一个LED 

#include 
#include 

sbit led =P2^0;

void UART_Init()
{
	SCON = 0x50;
	TMOD = 0x20;
	TH1  = 0XFD;
	TL1  = 0xFD;
	TR1  = 1;
	ES   = 1;
  EA	 = 1;
	
}

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 main()
{


	UART_Init();
	
	while(1)
	{
		Delay1000ms();
		SBUF = 'a';
	}
}


void zd() interrupt 4//串口中断
{

	
	if(RI == 1)
	{
		RI = 0;
		
		if(SBUF == 'o')
		{
			led = 0;
		}
		if(SBUF == 'c')
		{
			led = 1;
		}
	}
		

}

 13.通过esp8266WI-FI模块通过上位机点亮一个LED

/*
				就是在同一个局域网 服务器先连接WiFi 获得WiFiIP esp826601s在通过WIFIIP连接服务器  
				单片机通过串口发送数据给esp826601s esp826601s接受该AT数据连接 WIFI 和 服务器等
				就开始实现数据传输 

				AT+CWMODE=3 //1. 是station(设备)模式 2.是AP(路由)模式 3.是双模
				OK

				AT+CWJAP="TP-LINK_3E30","18650711783" //指令
				WIFI CONNECTED //结果
				WIFI GOT IP //结果
				
				AT+CIFSR //指令
				+CIFSR:APIP,"192.168.4.1"         当esp826601s做路由的IP
				+CIFSR:APMAC,"4e:75:25:0d:ae:2f"
				+CIFSR:STAIP,"192.168.0.148"
				+CIFSR:STAMAC,"4c:75:25:0d:ae:2f"
				OK
				
				AT+CIPSTART="TCP","192.168.0.113",8888 //指令,注意双引号逗号都要半角(英文)输入
				CONNECT //结果:成功
				OK //结果:成功

				AT+CIPSEND=4 // 设置即将发送数据的长度 (这里是4个字节)
				>CLCA // 看到大于号后,输入消息,CLCA,不要带回车
				Response :SEND OK //结果:成功
				//注意,这种情况下,每次发送前都要先发送AT+CIPSEND=长度 的指令,再发数据!

				AT+CIPMODE=1 //开启透传模式
				Response :OK
				+++退出透传模式

				AT+CIPSEND //带回车
				Response: > //这个时候随意发送接收数据咯


*/

#include 
#include 
#include 
#define SIZE 12

sbit Led = P2^0;
sbit Led1= P2^7; 

code char LJWL []="AT+CWJAP=\"iPhone\",\"00000000\"\r\n";
code char LJFWQ[]="AT+CIPSTART=\"TCP\",\"169.254.165.190\",8880\r\n";
char TC  []="AT+CIPMODE=1\r\n";
char SJFS[]="AT+CIPSEND\r\n";

char buffer[SIZE];

void Delay7000ms()		
{
	unsigned char i, j, k;

	_nop_();
	i = 50;
	j = 7;
	k = 195;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Delay1000ms()		
{
	unsigned char i, j, k;

	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


void Uart()
{
	PCON = 0x00;
	SCON = 0x50;
	TMOD = 0x20;
	TH1  = 0xFD;
	TL1  = 0xFD;
	TR1  = 1;
	ES   = 1;
	EA   = 1;
}

void SendByt(char Js)
{
	SBUF = Js;
	while(! TI );
	TI = 0;
}

void SendString(char * p)
{
	while(*p != '\0')
	{
		SendByt(*p);
		p++;
	}
}

void main()
{
	Led = 1;
	
	Uart();
	Delay1000ms();
	
	SendString(LJWL);
	Delay7000ms();
	
	SendString(LJFWQ);
	Delay7000ms();
	
	SendString(TC);
	Delay1000ms();

	SendString(SJFS);
	Delay1000ms();	
	
	Led = 0;
	
	while(1)
	{
		SendString("666\r\n");
	}
	
}

void Zd() interrupt 4
{
	unsigned char cmd; 
	static int i = 0;
	if(RI == 1)
	{
		RI = 0;
		cmd = SBUF;
		
		if(cmd == 'o' ||cmd == 'c')
		{
			i = 0;
		}
		buffer[i++] = cmd;
		if(buffer[0] == 'o'&&buffer[3]=='n')
		{
			Led1 = 0;
			memset(buffer, '\0', SIZE);

		}
		
		if(buffer[0] == 'c'&& buffer[4]=='e')
		{
			Led1 = 1;
			memset(buffer, '\0', SIZE);

		}
		
		if(i == 12)i = 0;
	}
}

14.通过4GI模块通 过上位机点亮一个LED

/*
	
	4G是公网通信不认识:‘局域网’;
	我们可以将内网IP穿透 就是利用花生壳 把内网ip弄成外网可以访问的一个地址端口
	
	我建立个服务器 通过花生壳把IP打造成外网可以访问的IP  通过AT指令先配置好(4G模块是先配置 重启才能使用)
	单片机接受4G发来的数据 如果检索到跟我设置一样的数据就可以进行点灯操作等。。。
	跟蓝牙一样 优点是突破了地域限制
	
	
	1. 打开串口连接4G模块,串口出产默认波特率是115200,可以自行根据用户手册修改
  	2. 进入AT指令模式,在串口助手内发送+++(不要勾选发送新行),必须在发送+++指令 3s 内发送其
     	他任意 AT 指令,比如AT+CPIN 1 检测到sim卡 0 没有检测到
  	3. 观察SIM卡灯是否亮起,AT+ICCID获得SIM卡信息,确认SIM卡安装完好 返回数据:
   	  +OK=89860116838013413419
     	检查信号是否正常,通过AT+CSQ指令检查信号值,建议插入信号天线,返回数据:+OK=31
	4. AT+SOCK=TCPC,103.46.128.21,52541 连接socket服务器,
     	103.46.128.21是公网IP地址,通过花生壳获得,26532是端口号,参数之间逗号隔开
	5.AT+REBT 重启模块。
	6.AT+UART=9600,NONE  none表示没有奇偶校验位 4g默认uart=115200;
	7.AT+LINKSTA 查询 TCP 链接是否已建立链接 返回Connect(TCP 连接)/ Disconnect(TCP 断开)

	
*/

#include 
#include 


sbit Led = P2^7;



void Uart()
{
	PCON = 0x00;
	SCON = 0x50;
	TMOD = 0x20;
	TH1  = 0xFD;
	TL1  = 0xFD;
	TR1  = 1;
	ES   = 1;
  EA   = 1;	
}

void main()
{
	Led = 1;
	
	Uart();
	while(1);
	
}

void Zd() interrupt 4
{
	 char cmd;

	
	if(RI == 1)
	{
		RI = 0;
		cmd = SBUF;
		
		if(cmd == 'o')
		{
			Led = 0;
		}
		if(cmd == 'c')
		{
			Led = 1;
		}
	}
}

 15.Lcd1602详解

RS 为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器
R/W 为读写信号线,高电平时进行读操作,低电平时进行写操作,当 RS 为低电平 R/W 为高电平时可以读忙信号。

#include 
#include 
#define buffer P0

sbit RS = P2^6;
sbit RW = P2^5;
sbit EN = P2^7;



void Read_Busy()
{
	char flag = 0x80;
	buffer = 0x80;
	
	while(flag & 0x80)
	{
		RS = 0;
		RW = 1;
		EN = 0;
		_nop_();
		
		EN = 1;
		_nop_();
		_nop_();
		
		flag = buffer;
		
		EN = 0;
		_nop_();
		
	}


}

void Write_Cmd(char cmd)
{
	Read_Busy();
	
	RS = 0;
	RW = 0;
	
	EN = 0;
	_nop_();
	
	buffer = cmd;
	_nop_();
	
	EN = 1;
	_nop_();
	_nop_();
	
	EN = 0;
	_nop_();
	


}

void Write_Data(char Data)
{
	Read_Busy();

	
	RW = 0;
	RS = 1;
	EN = 0;
	_nop_();
	
	buffer = Data;
	_nop_();
	
	EN = 1;
	_nop_();
	_nop_();
	
	EN = 0;
	_nop_();
	

}

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

	i = 10;
	j = 183;
	do
	{
		while (--j);
	} while (--i);
}

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

	i = 30;
	j = 43;
	do
	{
		while (--j);
	} while (--i);
}



void LCD1602_Init()
{
		//(1)延时 15ms
	Delay15ms();
	//(2)写指令 38H(不检测忙信号)
	Write_Cmd(0x38);
	//(3)延时 5ms
	Delay5ms();
	//(4)以后每次写指令,读/写数据操作均需要检测忙信号
	//(5)写指令 38H:显示模式设置
	Write_Cmd(0x38);
	//(6)写指令 08H:显示关闭
	Write_Cmd(0x08);
	//(7)写指令 01H:显示清屏
	Write_Cmd(0x01);
	//(8)写指令 06H:显示光标移动设置
  Write_Cmd(0x06);
	//(9)写指令 0CH:显示开及光标设置}
	Write_Cmd(0x0c);


}


void Data_Show(char hang,char lie,char *p)
{
	switch(hang)
	{
		case 1:
			
		  Write_Cmd(0x80 + lie);
			
		  while(*p != '\0')
			{
					Write_Data(*p);
				  p++;
			}
		case 2:
			
		 Write_Cmd(0x80 + 0x40 + lie);
			
			while(*p != '\0')
			{
			     Write_Data(*p);
						p++;
			}
	}

}

void main()
{
	LCD1602_Init();
	
	while(1)
	{
		
		Data_Show(1,6,"NO.1");
		Data_Show(2,4,"iverson!");
		
	}
	//Write_Cmd(0x80);
	//Write_Data('a');
	

}

 16.DTH11温湿度详解

 

#include 
#include 

sbit Led = P2^0;
sbit Dht = P0^0;
char Data[5];

void Uart()
{
	PCON = 0x00;
	SCON = 0x50;
	TMOD = 0x20;
	TH1  = 0xFD;
	TL1  = 0xFD;
	TR1  = 1;
}

void SendByte(char Js)
{
	SBUF = Js;
	while(!TI);
	TI  =  0;
}

void SendString(char *p)
{
	while(*p != '\0')
	{
		SendByte(*p);
		p++;
	}
}

void Delay30us()		
{
	unsigned char i;

	i = 11;
	while (--i);
}

void Delay40us()		
{
	unsigned char i;

	_nop_();
	i = 15;
	while (--i);
}


void Dht_Start()
{
	Dht = 1;
	Dht = 0;
	Delay30us();
	Dht = 1;
	
	while(Dht);
	while(!Dht);
	while(Dht);
	
	
}

void Read_Dht()
{
	int i;
	int j;
	char tmp;
	char flag;
	
	Dht_Start();
	
	for(i = 0;i < 5;++i)
	{
		for(j = 0;j < 8;++j)
		{
			
			
			while(!Dht);
			Delay40us();
			
			if(Dht == 1)
			{
				flag = 1;
				while(Dht);
			}
			else
			{
				flag = 0;
			}
			tmp = tmp << 1;
			tmp = flag | tmp;
			
		}
		Data[i] = tmp;
	}
}


void Delay500ms()		
{
	unsigned char i, j, k;

	_nop_();
	i = 4;
	j = 129;
	k = 119;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}


void main()
{
	
	Uart();
	
	while( 1 )
	{
		Delay500ms();
		Read_Dht();
		
		SendString("H:");
		
	  SendByte(Data[0] / 10 +0x30); //0x30 - 0x39 是0 - 9的ascll码 
		SendByte(Data[0] % 10 + 0x30);//这样就可以把对应的字符变成ascll输出
		SendByte('.');
		SendByte(Data[1] / 10 +0x30);
		SendByte(Data[1] % 10 + 0x30);
		SendString("\r\n");
		
		SendString("T:");
		
		SendByte(Data[2] / 10 +0x30);
		SendByte(Data[2] % 10 + 0x30);
		SendByte('.');
		SendByte(Data[3] / 10 +0x30);
		SendByte(Data[3] % 10 + 0x30);
		SendString("\r\n");
	
		
		
	}

	
	

	
}

让dht温湿度数据显示在Lcd1602上面

#include 
#include 
#define buffer P0


/*---------定义LCD1602 & DHT 引脚-----------*/

sbit dht = P0^0;
sbit RS = P2^6;
sbit RW = P2^5;
sbit EN = P2^7;

/*----------wd&sd用于存放温湿度数据---------*/
char Data[5];
char sd[9];
char wd[9];

/*----------读第7位是不是高电平-------------*/
void Read_Busy()
{
	char flag = 0x80;
	buffer = 0x80;
	
	while(flag & 0x80)
	{
		RS = 0;
		RW = 1;
		EN = 0;
		_nop_();
		
		EN = 1;
		_nop_();
		_nop_();
		
		flag = buffer;
		
		EN = 0;
		_nop_();
		
	}


}

void Write_Cmd(char cmd)
{
	Read_Busy();
	
	RS = 0;
	RW = 0;
	
	EN = 0;
	_nop_();
	
	buffer = cmd;
	_nop_();
	
	EN = 1;
	_nop_();
	_nop_();
	
	EN = 0;
	_nop_();
	


}

void Write_Data(char Data)
{
	Read_Busy();

	
	RW = 0;
	RS = 1;
	EN = 0;
	_nop_();
	
	buffer = Data;
	_nop_();
	
	EN = 1;
	_nop_();
	_nop_();
	
	EN = 0;
	_nop_();
	

}

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

	i = 10;
	j = 183;
	do
	{
		while (--j);
	} while (--i);
}

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

	i = 30;
	j = 43;
	do
	{
		while (--j);
	} while (--i);
}



void LCD1602_Init()
{
		//(1)延时 15ms
	Delay15ms();
	//(2)写指令 38H(不检测忙信号)
	Write_Cmd(0x38);
	//(3)延时 5ms
	Delay5ms();
	//(4)以后每次写指令,读/写数据操作均需要检测忙信号
	//(5)写指令 38H:显示模式设置
	Write_Cmd(0x38);
	//(6)写指令 08H:显示关闭
	Write_Cmd(0x08);
	//(7)写指令 01H:显示清屏
	Write_Cmd(0x01);
	//(8)写指令 06H:显示光标移动设置
  Write_Cmd(0x06);
	//(9)写指令 0CH:显示开及光标设置}
	Write_Cmd(0x0c);


}


void Data_Show(char hang,char lie,char *p)
{
	switch(hang)
	{
		case 1:
			
		  Write_Cmd(0x80 + lie);
			
		  while(*p != '\0')
			{
					Write_Data(*p);
				  p++;
			}
		case 2:
			
		 Write_Cmd(0x80 + 0x40 + lie);
			
			while(*p != '\0')
			{
			     Write_Data(*p);
						p++;
			}
	}

}

void Uart()
{
	PCON = 0x00;
	SCON = 0x50;
	TMOD = 0x20;
	TH1  = 0xFD;
	TL1  = 0xFD;
	TR1  = 1;
}

void SendByte(char Js)
{
	SBUF = Js;
	while(!TI);
	TI  =  0;
}

void SendString(char *p)
{
	while(*p != '\0')
	{
		SendByte(*p);
		p++;
	}
}


void Delay30us()		
{
	unsigned char i;

	i = 11;
	while (--i);
}

void Delay40us()		
{
	unsigned char i;

	_nop_();
	i = 15;
	while (--i);
}


void Dht_Start()
{
	dht = 1;
	dht = 0;
	Delay30us();
	dht = 1;
	
	while(dht);
	while(!dht);
	while(dht);
	
	
}

void Read_Dht()
{
	int i;
	int j;
	char tmp;
	char flag;
	
	Dht_Start();
	
	for(i = 0;i < 5;++i)
	{
		for(j = 0;j < 8;++j)
		{
			
			
			while(!dht);
			Delay40us();
			
			if(dht == 1)
			{
				flag = 1;
				while(dht);
			}
			else
			{
				flag = 0;
			}
			tmp = tmp << 1;
			tmp = flag | tmp;
			
		}
		Data[i] = tmp;
	}
}


void Put_Data()
{
	sd[0] = 's';
	sd[1] = 'd';
	sd[2] = ':';
	sd[3] = Data[0] /10 + 0x30;
	sd[4] = Data[0] %10 + 0x30;
	sd[5] = '.';
	sd[6] = Data[1] /10 + 0x30;
	sd[7] = Data[1] %10 + 0x30;
	sd[8] = '\0';

  wd[0] = 'w';
	wd[1] = 'd';
	wd[2] = ':';
	wd[3] = Data[2] /10 + 0x30;
	wd[4] = Data[2] %10 + 0x30;
	wd[5] = '.';
	wd[6] = Data[3] /10 + 0x30;
	wd[7] = Data[3] %10 + 0x30;
	wd[8] = '\0';
}


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 main()
{
	Uart();
	Delay1000ms();
	
	LCD1602_Init();
	
	

	while(1)
	{
		Delay1000ms();
		Read_Dht();
		Put_Data();
		
		Delay1000ms();
		Delay1000ms();

		SendString(wd);
		SendString("\r\n");
		SendString(sd);
		SendString("\r\n");
		
		Data_Show(1,0,wd);
		Data_Show(2,0,sd);

		
		
	}
}

 17.IIC_OLED详解

/*
    代码太多,需要的可以加我qq:2652408527
*/
#include 
#include 
#include "oled.h"
#include "oled_ziku.h"
#include "dht.h"

sbit SDA = P0^0;
sbit SCL = P0^1;
sbit dht = P0^2;

extern char Data[5];
extern char sd[9];
extern char wd[9];



void main()
{
	
	
	Oled_INIT();
	
	Oled_Write_Cmd(0x20);
	Oled_Write_Cmd(0x02);//选择页寻址
	
	Oled_Clear();//清屏
	
	while(1)
	{
	
		Oled_Show_Str(1,0,"Li zhen");
		Oled_Show_Str(2,0,"I LOVE YOU");
		Oled_Show_Str(2,80,"!");
		
		
	}
	
	
}
	

/*
	部分代码,需要的可以加我QQ:2652408527
*/

#include 
#include 
#include "oled.h"
#include "oled_ziku.h"
#include "dht.h"

sbit SDA = P0^0;
sbit SCL = P0^1;
sbit dht = P0^2;

extern char Data[5];
extern char sd[9];
extern char wd[9];
	char command[5];


void UART_Init()
{
	PCON = 0x00;
	SCON = 0x50;
	TMOD = 0x20;
	TH1  = 0xFD;
	TL1  = 0xFD;
	TR1  = 1;
	ES   = 1;
  EA   = 1;	
}


void main()
{
	UART_Init();
	 Delay1000ms();
	Oled_INIT();
	
	Oled_Write_Cmd(0x20);
	Oled_Write_Cmd(0x02);//选择页寻址
	
	Oled_Clear();//清屏
	

	while(1)
	{
		
		
		Read_Dht();
	
	  Put_Data();
		

		
		Oled_Show_Str(4,40,"Li jian hua");
		
		Delay1000ms();
		
	}
	
	
}
	

void zd() interrupt 4
{
	static i = 0;
	

	
	if(RI == 1)
	{
		RI = 0;
		command[i] = SBUF;
		i++;
		
		if(command[0]=='o'&&command[1]=='p'&&command[2]=='e'&&command[3]=='n')
		{
					Oled_Show_Str(1,0,wd);
		      Oled_Show_Str(2,0,sd); 
		}
		
	if(command[0]=='c'&&command[1]=='l'&&command[2]=='o'&&command[3]=='s')
	{
					Oled_Show_Str(1,0,"                                                                 ");
		      Oled_Show_Str(2,0,"                                                                  "); 
		}
		
	}

}

 

 18.四驱小车

由于没有循迹模块,我直接写了一个可以上下左右的小车代码

#include 
#include "dianji.h"

void UART_Init()
{
	PCON = 0x00;
	SCON = 0x50;
	TMOD = 0x20;
	TH1  = 0xFD;
  TL1  = 0xFD;
  TR1  = 1;
  ES   = 1;
  EA   = 1; 	
}

void zd() interrupt 4
{
	if(RI == 1)
	{
			RI = 0;
			
		 if(SBUF == 'a')
		 {
			 		 Dianji_Left1Ward_Init();
					 Dianji_Left2Ward_Init();
					 Dianji_Right1Ward_Init();
					 Dianji_Right2Ward_Init();
			 
			}
			
			if(SBUF == 'b')
			{
					   Dianji_Left1Back_Init();
						 Dianji_Left2Back_Init();
						 Dianji_Right1Back_Init();
						 Dianji_Right2Back_Init();
			}
			
			if(SBUF == 'e')
			{
				7 Stop();
			}
	}


}

 

 总结

感谢各位的观看,需要其中代码的兄弟可以私聊我。

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章