void delay(uint z);//延时,1微妙时间有点短
你看看下面我做的程序,在2051+12M晶振通过你可以套用这个程序,不行的话就改长延时
/AT89S51使用12M晶振/
//LCD脚接法,根据实际接法定义
#define LCM_D4_RS P3_2//第4脚数据/命令
#define LCM_D5_RW P3_5//第5脚读/写
#define LCM_D6_E P3_7//第6脚使能
#define LCM_D16_BLK P3_0//背光负极
#define LCM_D7_Data P1//第7-14脚数据
//LCD脚接法,根据实际接法定义
#define Busy 0x80 //用于检测LCM状态字中的Busy标识
#define _LCD_BIT_IS 4 //CPU与LCD1602间使用DB7-DB4这4根数据线进行传输
#include <at89x51h> //头文件
#include <stringh> //strlen()函数头文件
void LCMInit(void); //LCM初始化化
void WriteDataLCM(unsigned char WDLCM); //写数据
void WriteCommandLCM(unsigned char WCLCM,int BuysC); //写指令
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData); //按指定位置显示一个字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code DData);//按指定位置显示一串字符
void Delay5Ms(void); //5ms延时
unsigned char ReadStatusLCM(void); //读状态
unsigned char code Greetings_Line1[] = {"Welcome Control"};
unsigned char code Greetings_Line2[] = {" ChuLong Make "};
data unsigned char cou = 0; // 定义软计数器,放在程序最前面的寄存器定义部分
void main(void)
{
LCMInit(); //LCM初始化
LCM_D16_BLK = 0; //开背光灯
TMOD = 0x11; // 定时/计数器0,1工作于方式1 16位定时
TH0 = 0x3c; // 预置产生50ms时基信号
TL0 = 0xb0;
EA = 1; // 开总中断
ET0 = 1; // 定时/计数器0允许中断
TR0 = 1; // 开定时/计数器0
DisplayListChar(0, 0, Greetings_Line1);
DisplayListChar(0, 1, Greetings_Line2);
// while(1);
}
//
void LCMInit(void) //LCM初始化
{
WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
Delay5Ms();
WriteCommandLCM(0x38,0);
Delay5Ms();
WriteCommandLCM(0x38,0);
#if(_LCD_BIT_IS == 8) //CPU与LCD1602间使用DB0-DB8这8根数据线进行传输
WriteCommandLCM(0x38,1); //显示8位模式设置,开始要求每次检测忙信号
#else //CPU与LCD1602间使用DB0-DB4这4根数据线进行传输
WriteCommandLCM(0x28,1); //显示4位模式设置,开始要求每次检测忙信号
#endif
WriteCommandLCM(0x08,1); //关闭显示
WriteCommandLCM(0x01,1); //显示清屏
WriteCommandLCM(0x06,1); // 显示光标移动设置
WriteCommandLCM(0x0C,1); // 显示开及光标设置
}
//写数据
void WriteDataLCM(unsigned char WDLCM)
{
ReadStatusLCM(); //检测忙
LCM_D4_RS = 1;
LCM_D5_RW = 0;
#if(_LCD_BIT_IS == 8) //CPU与LCD1602间使用DB0-DB8这8根数据线进行传输
{
LCM_D7_Data = WDLCM;
}
#else //CPU与LCD1602间使用DB0-DB4这4根数据线进行传输
{
LCM_D7_Data &= 0x0f; //清高四位
LCM_D7_Data |= WDLCM & 0xf0; //写高四位
LCM_D6_E = 0;
LCM_D6_E = 1;
WDLCM = WDLCM << 4; //低四位移到高四位
LCM_D7_Data &= 0x0f; //清高四位
LCM_D7_Data |= WDLCM & 0xf0; //写低四位
}
#endif
LCM_D6_E = 0;
LCM_D6_E = 1;
}
//写指令
void WriteCommandLCM(unsigned char WCLCM,int BuysC) //BuysC为0时忽略忙检测
{
if(BuysC)
ReadStatusLCM(); //根据需要检测忙
LCM_D4_RS = 0;
LCM_D5_RW = 0;
#if(_LCD_BIT_IS == 8) //CPU与LCD1602间使用DB7-DB4这4根数据线进行传输
{
LCM_D7_Data = WCLCM;
}
#else
{
LCM_D7_Data &= 0x0f; //清高四位
LCM_D7_Data |= WCLCM & 0xf0; //写高四位
LCM_D6_E = 0;
LCM_D6_E = 1;
WCLCM = WCLCM << 4; //低四位移到高四位
LCM_D7_Data &= 0x0f; //清高四位
LCM_D7_Data |= WCLCM & 0xf0; //写低四位
}
#endif
LCM_D6_E = 0;
LCM_D6_E = 1;
}
//读状态
unsigned char ReadStatusLCM(void)
{
LCM_D7_Data = 0xff;
LCM_D4_RS = 0;
LCM_D5_RW = 1;
LCM_D6_E = 1;
while (LCM_D7_Data & Busy); //检测忙信号
return(LCM_D7_Data);
}
//按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
X |= 0x80; //算出指令码
WriteCommandLCM(X, 0); //这里不检测忙信号,发送地址码
WriteDataLCM(DData);
}
//按指定位置显示一串字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code DData)
{
int ListLength;
Y &= 0x1;
X &= 0xF; //限制X不能大于15,Y不能大于1
for(ListLength = 0;ListLength < strlen(DData);ListLength++) //若到达字串尾则退出
{
if (X <= 0xF) //X坐标应小于0xF
{
DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
X++;
}
}
}
//5ms延时
void Delay5Ms(void)
{
unsigned int TempCyc = 5552;
while(TempCyc--);
}
//10s延时
void tiem0(void) interrupt 1
{ // T/C0中断服务程序(产生50ms时基信号)
if(cou < 60)
{ // 计数值到1000(1s) (时间为倒计时)
cou = 0; // 软计数器清零
}
cou++; // 软计数器加1
TH0 = 0x3c; // 重置定时常数
TL0 = 0xb0;
}
单片机是典型的嵌入式微控制器(Microcontroller Unit),由运算器,控制器,存储器,输入输出设备等构成,相当于一个微型的计算机。与应用在个人电脑中的通用型微处理器相比,它更强调自供应(不用外接硬件)和节约成本。它的最大优点是体积小,可放在仪表内部,但存储量小,输入输出接口简单,功能较低。由于其发展非常迅速,旧的单片机的定义已不能满足,所以在很多应用场合被称为范围更广的微控制器;已经从上世纪80年代的4位、8位单片机,发展到现在的32位甚至64位的高速单片机。[1]
中文名
单片机
外文名
Microcontroller Unit
性质
嵌入式微控制器
优点
体积小、质量轻、价格便宜
组成
运算器、控制器、存储器、输入输出设备
种类
3种
类别
电路芯片
相关概述
单片微型计算机简称单片机,是典型的嵌入式微控制器(Microcontroller Unit), 常用英文字母的缩写MCU表示单片机。单片机又称单片微控制器,它不是完成某一个逻辑功能的芯片,而是把一个计算机系统集成到一个芯片上。单片机由运算器,控制器,存储器,输入输出设备构成,相当于一个微型的计算机(最小系统),和计算机相比,单片机缺少了外围设备等。概括的讲:一块芯片就成了一台计算机。它的体积小、质量轻、价格便宜、为学习、应用和开发提供了便利条件。同时,学习使用单片机是了解计算机原理与结构的最佳选择。它最早是被用在工业控制领域。

单片机
由于单片机在工业控制领域的广泛应用,单片机由仅有CPU的专用处理器芯片发展而来。最早的设计理念是通过将大量外围设备和CPU集成在一个芯片中,使计算机系统更小,更容易集成进复杂的而对体积要求严格的控制设备当中。
INTEL的8080是最早按照这种思想设计出的处理器,当时的单片机都是8位或4位的。其中最成功的是INTEL的8051,此后在8051上发展出了MCS51系列单片机系统。因为简单可靠而性能不错获得了很大的好评。尽管2000年以后ARM已经发展出了32位的主频超过300M的高端单片机,直到现在基于8051的单片机还在广泛的使用。在很多方面单片机比专用处理器更适合应用于嵌入式系统,因此它得到了广泛的应用。事实上单片机是世界上数量最多处理器,随着单片机家族的发展壮大,单片机和专用处理器的发展便分道扬镳。
现代人类生活中所用的几乎每件有电子器件的产品中都会集成有单片机。手机、电话、计算器、家用电器、电子玩具、掌上电脑以及鼠标等电子产品中都含有单片机。 汽车上一般配备40多片单片机,复杂的工业控制系统上甚至可能有数百片单片机在同时工作。
应用分类
单片机作为计算机发展的一个重要分支领域,根据发展情况,从不同角度单片机大致可以分为通用型/专用型、总线型/非总线型及工控型/家电型。
通用/专用型
这是按单片机适用范围来区分的。例如,80C51是通用型单片机,它不是为某种专用途设计的;专用型单片机是针对一类产品甚至某一个产品设计生产的,例如为了满足电子体温计的要求,在片内集成ADC接口等功能的温度测量控制电路。
总线型/非总线型
这是按单片机是否提供并行总线来区分的。总线型单片机普遍设置有并行地址总线、数据总线、控制总线,这些引脚用以扩展并行外围器件都可通过串行口与单片机连接,另外,许多单片机已把所需要的外围器件及外设接口集成一片内,因此在许多情况下可以不要并行扩展总线,大大减省封装成本和芯片体积,这类单片机称为非总线型单片机。
工控型/家用型
这是按照单片机大致应用的领域进行区分的。一般而言,工控型寻址范围大,运算能力强;用于家电的单片机多为专用型,通常是小封装、低价格,外围器件和外设接口集成度高。 显然,上述分类并不是惟一的和严格的。例如,80C51类单片机既是通用型又是总线型,还可以作工控用。
相关历史
单片机诞生于20世纪70年代末,经历了SCM、MCU、SoC三大阶段。
起初模型

单片机
SCM即单片微型计算机(Single Chip Microcomputer)阶段,主要是寻求最佳的单片形态嵌入式系统的最佳体系结构。“创新模式”获得成功,奠定了SCM与通用计算机完全不同的发展道路。在开创嵌入式系统独立发展道路上,Intel公司功不可没。
MCU即微控制器(Micro Controller Unit)阶段,主要的技术发展方向是:不断扩展满足嵌入式应用时,对象系统要求的各种外围电路与接口电路,突显其对象的智能化控制能力。它所涉及的领域都与对象系统相关,因此,发展MCU的重任不可避免地落在电气、电子技术厂家。从这一角度来看,Intel逐渐淡出MCU的发展也有其客观因素。在发展MCU方面,最著名的厂家当数Philips公司。
Philips公司以其在嵌入式应用方面的巨大优势,将MCS-51从单片微型计算机迅速发展到微控制器。因此,当我们回顾嵌入式系统发展道路时,不要忘记Intel和Philips的历史功绩。
SoC即嵌入式系统(System on Chip)寻求应用系统在芯片上的最大化解决使得专用单片机的发展自然形成了SoC化趋势。随着微电子技术、IC设计、EDA工具的发展,基于SoC的单片机应用系统设计会有越来越大的发展。因此,对单片机的理解可以从单片微型计算机、单片微控制器延伸到单片应用系统。
单片机发展史
1971年intel公司研制出世界上第一个4位的微处理器;Intel公司的霍夫研制成功世界上第一块4位微处理器芯片Intel 4004,标志着第一代微处理器问世,微处理器和微机时代从此开始。因发明微处理器,霍夫被英国《经济学家》杂志列为“二战以来最有影响力的7位科学家”之一 。
1971年11月,Intel推出MCS-4微型计算机系统(包括4001 ROM芯片、4002 RAM芯片、4003移位寄存器芯片和4004微处理器 )其中4004包含2300个晶体管,尺寸规格为3mm×4mm,计算性能远远超过当年的ENIAC,最初售价为200美元。
1972年4月,霍夫等人开发出第一个8位微处理器Intel 8008。由于8008采用的是P沟道MOS微处理器,因此仍属第一代微处理器。
1973年intel公司研制出8位的微处理器8080;1973年8月,霍夫等人研制出8位微处理器Intel 8080,以N沟道MOS电路取代了P沟道,第二代微处理器就此诞生。
主频2MHz的8080芯片运算速度比8008快10倍,可存取64KB存储器,使用了基于6微米技术的6000个晶体管,处理速度为064MIPS(Million Instructions Per Second )。
1975年4月,MITS发布第一个通用型Altair 8800,售价375美元,带有1KB存储器。这是世界上第一台微型计算机。
1976年intel公司研制出MCS-48系列8位的单片机,这也是单片机的问世。Zilog公司于1976年开发的Z80微处理器,广泛用于微型计算机和工业自动控制设备。当时,Zilog、Motorola和Intel在微处理器领域三足鼎立。
20世纪80年代初,Intel公司在MCS-48系列单片机的基础上,推出了MCS-51系列8位高档单片机。MCS-51系列单片机无论是片内RAM容量,I/O口功能,系统扩展方面都有了很大的提高。
你把跟lcd数据连接的一些外设都去掉 程序的话
#include<reg52h>
#include<intrinsh>
#define uchar unsigned char
#define uint unsigned int
//这三个引脚参考资料
sbit LCD1602_EN=P2^7; //1602使能引脚
sbit LCD1602_RW=P2^6; //1602读写引脚
sbit LCD1602_RS=P2^5; //1602数据/命令选择引脚
/
名称 : LCD1602_delay()
功能 : 延时,延时时间大概为5US。
输入 : 无
输出 : 无
/
void LCD1602_delay()
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
void LCD1602_Delay(uint i)
{
uint x,j;
for(j=0;j<i;j++)
for(x=0;x<=148;x++);
}
/
名称 : bit Busy(void)
功能 : 这个是一个读状态函数,读出函数是否处在忙状态
输入 : 输入的命令值
输出 : 无
/
bit Busy(void)
{
bit busy_flag = 0;
LCD1602_RS = 0;
LCD1602_RW = 1;
LCD1602_EN = 1;
LCD1602_delay();
busy_flag = (bit)(P0 & 0x80);
LCD1602_EN = 0;
return busy_flag;
}
/
名称 : LCD1602_wcmd(uchar del)
功能 : 1602命令函数
输入 : 输入的命令值
输出 : 无
/
void LCD1602_wcmd(uchar del)
{
while(Busy());
LCD1602_RS = 0;
LCD1602_RW = 0;
LCD1602_EN = 0;
LCD1602_delay();
P0 = del;
LCD1602_delay();
LCD1602_EN = 1;
LCD1602_delay();
LCD1602_EN = 0;
}
/
名称 : LCD1602_wdata(uchar del)
功能 : 1602写数据函数
输入 : 需要写入1602的数据
输出 : 无
/
void LCD1602_wdata(uchar del)
{
while(Busy());
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_EN = 0;
LCD1602_delay();
P0 = del;
LCD1602_delay();
LCD1602_EN = 1;
LCD1602_delay();
LCD1602_EN = 0;
}
/
名称 : L1602_init()
功能 : 1602初始化,请参考1602的资料
输入 : 无
输出 : 无
/
void LCD1602_init(void)
{
LCD1602_wcmd(0x38);//设置16X2显示
LCD1602_wcmd(0x08);//关显示
LCD1602_wcmd(0x0c);//开显示
LCD1602_wcmd(0x0e);//开显示显示光标
LCD1602_wcmd(0x0f);//开显示显示光标光标闪烁
LCD1602_wcmd(0x06);//写入指针加一
LCD1602_wcmd(0x04);//写入指针减一
// LCD1602_wcmd(0x07);//写入整屏左移
// LCD1602_wcmd(0x05);//写入整屏右移
LCD1602_wcmd(0x01);//清屏
//LCD1602_wcmd(0x80+0X10);
}
/
名称 : LCD1602_char(uchar hang,uchar lie,char sign)
功能 : 改变液晶中某位的值,如果要让第一行,第五个字符显示"b" ,调用该函数如下
L1602_char(1,5,'b')
输入 : 行,列,需要输入1602的数据
输出 : 无
/
void LCD1602_char(uchar hang,uchar lie,char sign)
{
uchar a;
if(hang == 1) a = 0x80;
if(hang == 2) a = 0xc0;
a = a + lie - 1;
LCD1602_wcmd(a);
LCD1602_wdata(sign);
}
/
名称 : LCD1602_string(uchar hang,uchar lie,uchar p)
功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
L1602_string(1,5,"ab cd ef;")
输入 : 行,列,需要输入1602的数据
输出 : 无
/
void LCD1602_string(uchar hang,uchar lie,uchar p)
{
uchar a,b=0;
if(hang == 1) a = 0x80;
if(hang == 2) a = 0xc0;
a = a + lie - 1;
while(1)
{
LCD1602_wcmd(a++);
if((p == '\0')||(b==16)) break;
b++;
LCD1602_wdata(p);
p++;
}
}
/
名称 : main()
功能 : 主函数
输入 : 无
输出 : 无
/
void main()
{
LCD1602_Delay(30);
LCD1602_init();
LCD1602_string(1,1," Welcome To ");
LCD1602_string(2,1," The MCU World ");
LCD1602_char(1,1,'');
LCD1602_char(1,16,'');
while(1);
}
试试这个 有用请给好评
LCD1602是一种常见的字符型液晶显示屏,通常与单片机一起使用。下面是LCD1602程序流程的一般描述:
初始化:设置数据总线和控制总线的方向及初始状态,将LCD1602的控制寄存器和数据寄存器初始化,设置显示模式、光标位置等。
发送指令:将需要执行的指令通过数据总线发送到LCD1602的指令寄存器中。
发送数据:将需要显示的数据通过数据总线发送到LCD1602的数据寄存器中。
延时:在发送指令和数据的过程中,需要适当的延时等待LCD1602完成 *** 作。
循环显示:根据需要不断发送指令和数据,以显示所需的内容。
清屏 *** 作:当需要清空显示内容时,通过发送清屏指令实现。
光标控制:根据需要移动光标的位置或改变光标显示状态。
显示控制:根据需要控制显示内容的开关、显示光标等。
结束程序:完成所需的显示后,关闭LCD1602的电源或将其重置为初始状态。
以上是LCD1602程序流程的一般描述,实际编程时还需要根据具体需求进行具体的指令和数据的发送 *** 作。
本程序已通过实际电路检测
#include<reg52h>
#define uchar unsigned char
sbit rs=P2^0; //lcd1602 rs端
sbit rw=P2^1; //lcd1602 rw端
sbit en=P2^2; //lcd1602 e端
uchar code table[]="wang yun";
uchar code tt1[]={0x1F,0x1F,0x04,0x0E,0x0E,0x04,0x1F,0x1F}; //王
uchar code tt2[]={0x0E,0x0E,0x00,0x1F,0x1F,0x0C,0x19,0x1F}; //云
///////////////////////////////////////
void delay(uchar H,uchar L) //定时器延时程序段
{ TF0=0;TH0=H;TL0=L;
while(!TF0);
}
////////////////////////////////////// 写指令程序段
void w_comd(uchar lcd1602_code)
{ en=1;rs=0;rw=0;
P0=lcd1602_code;
delay(0xff,0xd8);
en=0; //en端下降沿触发数据发送
delay(0xff,0xd8); //本程序没有 忙检测程序,所以此处必须给足够长的延时,保证数据发送完全
}
///////////////////////////////////////写数据程序段
void w_data(uchar lcd1602_data)
{ en=1;rs=1;rw=0;
P0=lcd1602_data;
delay(0xff,0xd8);
en=0; //en端下降沿触发数据发送
delay(0xec,0x78);
}
//////////////////////////////////// 初始化lcd1602
void set_lcd1602()
{ w_comd(0x01); //清屏
delay(0xf9,0x98);
w_comd(0x02); //地址指针归位
delay(0xf9,0x98);
w_comd(0x06); //
w_comd(0x0c); //开显示屏
w_comd(0x38); //8位传送数据 2行显示
}
/////////////////////////////////// 显示程序段
void view_lcd1602(uchar addr,uchar i) //i为所传字符串指针
{ int j;
w_comd(addr); //写入地址
while(i>0)
{ w_data(i); //写入数据
i++;
for(j=0;j<=100;j++)
delay(0x15,0xa0);
w_comd(0x18); //左移指令
}
}
/////////////////////////////////////// cgram写入程序段
void cgram_set_lcd1602(uchar addr,uchari)
{ int j;
w_comd(addr); //地址写入
for(j=0;j<8;j++)
{ w_data(i); //自定义数据写入
i++;
}
}
////////////////////////////////////// 主程序
void main()
{
TMOD=0x00; //设定定时器
TR0=1; //定时器0开
set_lcd1602(); //初始化LCD1602
view_lcd1602(0x8f,table);
cgram_set_lcd1602(0x40,tt1);
cgram_set_lcd1602(0x48,tt2);
w_comd(0xca); w_data(0x00); w_data(0x01); //自定义字符显示
while(1);
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)