非标协议外设
4.1 LCD1602显示
4.1.1 概述
LCD1602(Liquid Crystal Display)是一种工业字符型液晶,能够同时显示 16×02 即 32 字符(16列两行
4.1.2引脚说明、
第 1 脚: VSS 为电源地
第 2 脚: VDD 接 5V 正电源
第 3 脚: VL 为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度 过高时会产生“鬼影”,使用时可以通过一个 10K 的电位器调整对比度。
第 4 脚:RS 为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
第 5 脚:R/W 为读写信号线,高电平时进行读操作,低电平时进行写操作。当 RS 和 R/W 共 同为低电平时可以写入指令或者显示地址,当 RS 为低电平 R/W 为高电平时可以读忙信号, 当 RS 为高电平 R/W 为低电平时可以写入数据。
第 6 脚:E 端为使能端,当 E 端由高电平跳变成低电平时,液晶模块执行命令。
第 7-14 脚:D0~D7 为 8 位双向数据线。
第 15 脚:背光源正极。
第 16 脚:背光源负极
//和上官一号的接线
//电源
VSS -- GND
VDD -- 5V
//对比度
VO -- GND
//控制线
RS -- P1.0
RW -- P1.1
E -- P1.4
//背光灯
A -- 5V
K -- GDN
//数据
D0到D7 -- P0.到P0.7
4.1.3 开发逻辑
- 在哪里显示
例如第二行第一个字符的地址是 40H,那么是否直接写入 40H 就可以将光标定位在第二行第 一个字符的位置呢?这样不行,因为写入显示地址时要求最高位 D7 恒定为高电平 1 所以实 际写入的数据应该是 01000000B(40H) +10000000B(80H)=11000000B(C0H)
- 显示什么
4.1.4 读写操作时序
读操作时序
写操作
RS=1时,发送的为内容 RS=0时,发送的为地址 。
RW中间必须为低电平,将全程配置为低电平。
E 0 1 0
第一个0的时候延迟TR=25ns
1持续tpw=150ns 下降过程TF=25ns
数序参数
三个关键节点:
- 开始
- 结束
- 转折
代码
#include "reg52.h"
#include "intrins.h"
#define databuffer P0//定义8位数据线,P0端口组
sbit RS=P1^0;
sbit RW=P1^1;
sbit EN=P1^4;
void Delay15ms(void) //@11.0592MHz
{
unsigned char data i, j;
i = 27;
j = 226;
do
{
while (--j);
} while (--i);
}
void Delay5ms(void) //@11.0592MHz
{
unsigned char data i, j;
i = 9;
j = 244;
do
{
while (--j);
} while (--i);
}
void check_busy()
{
char tmp=0x80;
databuffer=0x80;
while(tmp&0x80)//1
{
RS=0;
RW=1;
EN=0;
_nop_();
EN=1;
_nop_();
_nop_();
tmp=databuffer;
EN=0;
_nop_();
}
}
void write_cmd_fun(char cmd)
{
check_busy();
RS=0;
RW=0;
EN=0;
_nop_();
databuffer=cmd;
_nop_();
EN=1;
_nop_();
_nop_();
EN=0;
_nop_();
}
void write_Data_fun(char cmd)
{
check_busy();
RS=1;
RW=0;
EN=0;
_nop_();
databuffer=cmd;
_nop_();
EN=1;
_nop_();
_nop_();
EN=0;
_nop_();
}
void LCE1602_Init()
{
//(1)延时 15ms
Delay15ms();
//(2)写指令 38H(不检测忙信号)
write_cmd_fun(0x38);
//(3)延时 5ms
Delay5ms();
//(4)以后每次写指令,读/写数据操作均需要检测忙信号
//(5)写指令 38H:显示模式设置
write_cmd_fun(0x38);
//(6)写指令 08H:显示关闭
write_cmd_fun(0x08);
//(7)写指令 01H:显示清屏
write_cmd_fun(0x01);
//(8)写指令 06H:显示光标移动设置
write_cmd_fun(0x06);
//(9)写指令 0CH:显示开及光标设置
write_cmd_fun(0x0c);
}
void main()
{
char position=0x80+0x05;
char data_show= 'C';
LCE1602_Init();
write_cmd_fun(position);//选择要显示的地址
write_Data_fun(data_show);//发送要显示的字符
}
4.1.5显示一行字符
代码
#include "reg52.h"
#include "intrins.h"
#define databuffer P0//定义8位数据线,P0端口组
sbit RS=P1^0;
sbit RW=P1^1;
sbit EN=P1^4;
void Delay15ms(void) //@11.0592MHz
{
unsigned char data i, j;
i = 27;
j = 226;
do
{
while (--j);
} while (--i);
}
void Delay5ms(void) //@11.0592MHz
{
unsigned char data i, j;
i = 9;
j = 244;
do
{
while (--j);
} while (--i);
}
void check_busy()
{
char tmp=0x80;
databuffer=0x80;
while(tmp&0x80)//1
{
RS=0;
RW=1;
EN=0;
_nop_();
EN=1;
_nop_();
_nop_();
tmp=databuffer;
EN=0;
_nop_();
}
}
void write_cmd_fun(char cmd)
{
check_busy();
RS=0;
RW=0;
EN=0;
_nop_();
databuffer=cmd;
_nop_();
EN=1;
_nop_();
_nop_();
EN=0;
_nop_();
}
void write_Data_fun(char cmd)
{
check_busy();
RS=1;
RW=0;
EN=0;
_nop_();
databuffer=cmd;
_nop_();
EN=1;
_nop_();
_nop_();
EN=0;
_nop_();
}
void lcd1602_showline(char row,char col,char *string)
{
switch(row)
{
case 1:
write_cmd_fun(0x80+col);
while(*string)
{
write_Data_fun(*string);
string++;
}
break;
case 2:
write_cmd_fun(0x80+0x40+col);
while(*string)
{
write_Data_fun(*string);
string++;
}
break;
}
}
void LCE1602_Init()
{
//(1)延时 15ms
Delay15ms();
//(2)写指令 38H(不检测忙信号)
write_cmd_fun(0x38);
//(3)延时 5ms
Delay5ms();
//(4)以后每次写指令,读/写数据操作均需要检测忙信号
//(5)写指令 38H:显示模式设置
write_cmd_fun(0x38);
//(6)写指令 08H:显示关闭
write_cmd_fun(0x08);
//(7)写指令 01H:显示清屏
write_cmd_fun(0x01);
//(8)写指令 06H:显示光标移动设置
write_cmd_fun(0x06);
//(9)写指令 0CH:显示开及光标设置
write_cmd_fun(0x0c);
}
void main()
{
char position=0x80+0x05;
char data_show= 'C';
LCE1602_Init();
//write_cmd_fun(position);//选择要显示的地址
//write_Data_fun(data_show);//发送要显示的字符
lcd1602_showline(1,5,"no.1");
lcd1602_showline(2,0,"hwq handsome");
}
4.2 DHT11 温湿度传感器
4.2.1 产品概述
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,应用领域:暖通 空调;汽车;消费品;气象站;湿度调节器;除湿器;家电;医疗;自动控制
4.2.2特点
相对湿度和温度测量 全部校准,数字输出 长期稳定性 超长的信号传输距离:20米 超低能耗:休眠 4 引脚安装:可以买封装好的 完全互换 : 直接出结果,不用转化
4.2.3接线
4.2.4数据传送逻辑
只有一根数据线DATA,上官一号发送序列指令给DHT11模块,模块一次完整的数据传输为40bit,高位先出
4.2.5数据格式
8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据+8bit校验和
4.2.6通讯过程时序图
通讯过程时序图
4.2.7 检测模块是否存在
根据如下时序图,做通信初始化,并检测模块是否存在,功能是否正常
a=1 b=0
b=0,c=0,至少拉低18ms
c=d=1拉高20-40ms
d=e=0持续80us 读dht=0 读40-100us之间
a : dht = 1
b :dht = 0
延时30ms
c: dht = 1
在60us后读d点,如果d点是低电平(被模块拉低),说明模块存在!
void check_DHT()
{
//a : dht = 1
DHT = 1;
//b :dht = 0
DHT = 0;
//延时30ms
Delay30ms();
//c: dht = 1
DHT = 1;
//在60us后读d点,如果d点是低电平(被模块拉低),说明模块存在!
Delay60us();
if(DHT==0)
{
led1=0;//亮灯则模块存在
}
}
4.2.8DHT11工作原理
a : dht = 1
b :dht = 0
延时30ms
c: dht = 1
卡d点;while(dht1); 卡e点 while(!dht) 卡f点:while(dht)
卡g点:while(!dht) 有效数据都是高电 平,持续时间不一样,50us读,低电平0 高电平
DHT11传输0的时序分析
50us读,低电平0 高电平1
DHT11传输1的时序分析
读数据读5轮,每轮读8次
#include "reg52.h"
#include "intrins.h"
sbit DHT=P3^3;
sbit led1=P3^7;
char datas[5];
sfr AUXR = 0x8E;
void Delay30ms(void) //@11.0592MHz
{
unsigned char data i, j;
i = 54;
j = 199;
do
{
while (--j);
} while (--i);
}
void Uart1_Init(void) //9600bps@11.0592MHz
{
AUXR = 0x01;
//scon配0101 0000
SCON=0X40;//配置串口工作方式1,REN不使能接收
TMOD &=0XF0;
TMOD |=0x20;//定时器8位重载
TH1=0XFD;
TL1=0XFD;//9600波特率初值
TR1=1;
}
void sendbyte(char data_message)
{
SBUF=data_message;
while(!TI);
TI=0;
}
void send_string(char* str)
{
while(*str !='\0')
{
sendbyte(*str);
str++;
}
}
void Delay60us(void) //@11.0592MHz
{
unsigned char data i;
i = 25;
while (--i);
}
void Delay1000ms(void) //@11.0592MHz
{
unsigned char data i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay50us(void) //@11.0592MHz
{
unsigned char data i;
_nop_();
i = 20;
while (--i);
}
void check_DHT()
{
//a : dht = 1
DHT = 1;
//b :dht = 0
DHT = 0;
//延时30ms
Delay30ms();
//c: dht = 1
DHT = 1;
//在60us后读d点,如果d点是低电平(被模块拉低),说明模块存在!
Delay60us();
if(DHT==0)
{
led1=0;//亮灯则模块存在
}
}
void DHT11_start()
{
//a : dht = 1
DHT = 1;
//b :dht = 0
DHT = 0;
//延时30ms
Delay30ms();
//c: dht = 1
DHT = 1;
//卡d点;while(dht1); 卡e点 while(!dht) 卡f点:while(dht) 卡g点:while(!dht)
while(DHT);
while(!DHT);
while(DHT);
}
void read_data()
{
int i;//轮数
int j;//次数
char tmp;
char flag;
DHT11_start();
for(i=0;i<5;i++)
{
for(j=0;j<8;j++)
{
while(!DHT);//等待卡g点
Delay50us();
if(DHT==1)
{
flag=1;
while(DHT);
}else
{
flag=0;
}
tmp=tmp<<1;
tmp|=flag;
}
datas[i]=tmp;
}
}
void main()
{
led1=1;
check_DHT();
Uart1_Init();
Delay1000ms();
while(1)
{
Delay1000ms();
Delay1000ms();
read_data();
send_string("H:");
sendbyte(datas[0]/10+0x30);
sendbyte(datas[0]%10+0x30);
send_string(".");
sendbyte(datas[1]/10+0x30);
sendbyte(datas[1]%10+0x30);
send_string("\r\n");
send_string("T:");
sendbyte(datas[2]/10+0x30);
sendbyte(datas[2]%10+0x30);
send_string(".");
sendbyte(datas[3]/10+0x30);
sendbyte(datas[3]%10+0x30);
send_string("\r\n");
}
}