一:液晶模块LCD1602只能显示字符不能显示图片和汉字;引脚相对应的功能如下:
E管脚对应的单片机的管脚为P1^2;R/W对应的管脚为P2^1;RS对应的管脚为P2^0;VL是接接旁边的电位器RB1的,通过RB1可以控制液晶的显示暗和亮情况;
二:液晶的写命令和写数据的方法:dat 要写入的数;当RS=0;的时候写入的是命令当RS=1;的时候写入的是数据
void LCD_COM(uchar dat) //写命令
{
SE = 0;
RW = 0; // =0 是写入 =1 是读;
RS = 0; // =0 是写入命令 =1是写入数据
add=dat;SE=1;
delayms(5); //让数据保持然后一个下降沿将数据传到端口
SE=0;
}void LCD_Write(uchar dat) //写数据
{
SE = 0;
RW = 0; // =0 是写入LCD1602 =1是从LCD1602里面读
RS = 1; // =0 是写入命令 =1是写入数据
add=dat;
SE=1;
delayms(5); //让数据保持然后一个下降沿将数据传到端口
SE=0;
}
三:LCD1602一些对应的指令及初始化;
DL
功能:设定数据总线位数、显示的行数及字型。参数设定的情况如下:
位名 设置
DL 0=数据接口为 4 位 1=数据接口为 8 位
N 0=显示 1 行 1=显示 2 行
F 0=5×7 点阵/每字符 1=5×10 点阵/每字符 X为任意值
0x32是四位数据接口设置;0x38是八位数据接口设置;且显示两行;
0x0c 开显示不显示光标 0x0e 显示光标但不闪烁,0x0f开光标并且闪烁
0x06 写一个光标右移,0x04光标左移,
0x01;清屏指令;所有显示清零;指针指向左上第一个;
初始化代码:
void LCD_init()
{
LCD_COM(0x3c); // 0x38 是开的5*7方阵 0x3c 是开的5*10方阵
LCD_COM(0x0c); // 开显示不显示光标 0x0e 显示光标但不闪烁,0x0f开光标并且闪烁
LCD_COM(0x06); // 0x06 写一个光标后移,0x04光标左移,0x07 屏幕右移且光标后移
LCD_COM(0x01); // 清屏
LCD_COM(0x00+0x80); //设置数据指针起点为什么加0x80看下面;这条指令可以不写在这里可以在显示的时候再写
}
四:初始化之后要确定显示位置;
LCD1602的DDROM里面有80字节的空间用来寄存待显示的字符代码上表就是对应的关系;
要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,例如第二行第一个字符的地址是 40H, 那么是否直接写入 40H 就可以将光标定位在第二行第一个字符的位置呢?这样不行,因为写入显示地址时要求最高位 D7恒定为高电平 1 所以实际写入的数据应该是 01000000B(40H)+10000000B(80H)=11000000B(C0H)。就是在写入地址的时候要加上0x80;
五:LCD显示时间温度;
代码如下:
#include <STC15F2K60S2.H>
#include<intrins.h>
#include<ds1302.h>
#include<onewire.h>
#define uchar unsigned char
#define uint unsigned int
#define add P0 //LCD数据端口
sbit SE=P1^2; // LCD使能端口
sbit RW=P2^1; // LCD读写端口
sbit RS=P2^0; // LCD写数据或写命令端口
uchar time[]={55,59,23,27,3,3,19}; //初始时间 2019-3-28 23:59:55 星期三
//秒,分,时,日,月,星期,年
uchar du1[16]; // 第一行
uchar du2[16]; // 第二行
void LCD_COM(uchar dat); // LCD写命令
void LCD_write(uchar dat); //LCD写数据
void LCD_init(); //LCD初始化
void ds1302_init(); //时钟初始化
void ds1302_read(); //读取时钟
void display1(); //LCD第一行显示
void display2(); //LCD第二行显示
uint ds18b20();
void delayms(uint ms)
{
uint i,j;
for(i=0;i<ms;i++)
for(j=0;j<855;j++);
}
void allinit()
{
P2=0xa0;P0=0x00;
P2=0x80;P0=0xff;
P2=0xc0;P0=0xff;P2=0x00;
P2=0xff;P0=0xff;P2=0x00;
}
void main()
{ uchar i;
LCD_init();
allinit();
ds1302_init();
while(1)
{
ds1302_read();
display1();
display2();
LCD_COM(0x80); //显示第一行
for(i=0;i<16;i++)
LCD_write(du1[i]);
LCD_COM(0x40+0x80); //显示第二行
for(i=0;i<16;i++)
LCD_write(du2[i]);
}
}
void display1() //第一行显示
{
du1[0]='T';
du1[1]=' ';
du1[2]=time[4]/10+0x30; //+0x30的原因是数字在LCD不能显示要转化成字符就是AIISC码
du1[3]=time[4]%10+0x30;
du1[4]='-';
du1[5]=time[3]/10+0x30;
du1[6]=time[3]%10+0x30;
du1[7]=' ';
du1[8]=time[2]/10+0x30;
du1[9]=time[2]%10+0x30;
du1[10]=':';
du1[11]=time[1]/10+0x30;
du1[12]=time[1]%10+0x30;
du1[13]=':';
du1[14]=time[0]/10+0x30;
du1[15]=time[0]%10+0x30;
}
void display2() //第二行显示
{ uint num;
num=ds18b20();
du2[15]=num%10+0x30;
du2[14]=num/10%10+0x30;
du2[13]='.';
du2[12]=num/100%10+0x30;
du2[11]=num/1000%10+0x30;
du2[10]='m';
du2[9]='e';
du2[8]='l';
du2[7]='e';
du2[6]=' ';
du2[0]='2';
du2[1]='0';
du2[2]=time[6]/10+0x30;
du2[3]=time[6]%10+0x30;
du2[4]='-';
du2[5]=time[5]%10+0x30;
}
/******LCD*************/
void LCD_COM(uchar dat)
{
SE=0;
RW=0;//写数据
RS=0;//0写命令 1写数据
SE=1;
add=dat;
delayms(5); //保持数据
SE=0; //下降沿传输数据
}
void LCD_write(uchar dat)
{
SE=0;
RW=0;//写数据
RS=1;//0写数据 1写命令
SE=1;
add=dat;
delayms(5); //保持数据
SE=0; //下降沿传输数据
}
void LCD_init()
{
LCD_COM(0x38); //8位总线,显示两行,5*7点阵
LCD_COM(0x0c); //B2位显示开,无光标,不闪烁
LCD_COM(0x06); //光标后移,显示屏不右移
LCD_COM(0x01); //清屏
}
/**********温度****************/
uint ds18b20()
{
uint temp;
uchar L,H;
init_ds18b20();
Write_DS18B20(0xcc); //跳过选择ROM
Write_DS18B20(0x44); //启动转换命令
init_ds18b20(); //再次初始化
Write_DS18B20(0xcc);
Write_DS18B20(0xbe); //读取数据命令
L=Read_DS18B20();
H=Read_DS18B20();
temp=(H<<8)|L; //精确到小数
return temp*100*0.0625+0.05; //小数后两位
}
/*******时钟*****************/
uchar BCD_DAT(uchar dat) //BCD码转十进制
{
uchar dat1,dat2;
dat1=dat/16;
dat2=dat%16;
return dat1*10+dat2;
}
uchar DAT_BCD(uchar dat)//十进制转BCD码
{
uchar dat1,dat2;
dat1=dat/10;
dat2=dat%10;
return dat1*16+dat2;
}
void ds1302_init() //时钟初始化
{
Write_Ds1302_Byte(0x8e,0x00);
Write_Ds1302_Byte(0x80,DAT_BCD(time[0]));
Write_Ds1302_Byte(0x82,DAT_BCD(time[1]));
Write_Ds1302_Byte(0x84,DAT_BCD(time[2]));
Write_Ds1302_Byte(0x86,DAT_BCD(time[3]));
Write_Ds1302_Byte(0x88,DAT_BCD(time[4]));
Write_Ds1302_Byte(0x8a,DAT_BCD(time[5]));
Write_Ds1302_Byte(0x8c,DAT_BCD(time[6]));
Write_Ds1302_Byte(0x8e,0x80);
}
void ds1302_read() //读取时钟
{
Write_Ds1302_Byte(0x8e,0x00);
time[0]=BCD_DAT(Read_Ds1302_Byte(0x81));
time[1]=BCD_DAT(Read_Ds1302_Byte(0x83));
time[2]=BCD_DAT(Read_Ds1302_Byte(0x85));
time[3]=BCD_DAT(Read_Ds1302_Byte(0x87));
time[4]=BCD_DAT(Read_Ds1302_Byte(0x89));
time[5]=BCD_DAT(Read_Ds1302_Byte(0x8b));
time[6]=BCD_DAT(Read_Ds1302_Byte(0x8d));
Write_Ds1302_Byte(0x8e,0x80);
}
温度驱动
/*
程序说明: 单总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
日 期: 2011-8-9
*/
#include <STC15F2K60S2.H>
sbit DQ = P1^4; //单总线接口
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{ t=t*8;
while(t--);
}
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//DS18B20设备初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
时钟驱动
/*
程序说明: DS1302驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include <STC15F2K60S2.H>
#include <intrins.h>
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3; // DS1302复位
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK=0;
SDA=temp&0x01;
temp>>=1;
SCK=1;
}
}
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return (temp);
}