📄 lcm1602.c
字号:
#include <reg52.h>
/*
定义Lcm1602的接线方式
RS: P2.0
RW: P2.1
E: P2.2
D0: P0.0
D1: P0.1
D2: P0.2
D3: P0.3
D4: P0.4
D5: P0.5
D6: P0.6
D7: P0.7
*/
sbit LCM1602RS = P2^0;
sbit LCM1602RW = P2^1;
sbit LCM1602E = P2^2;
/*定义1602的数据模式*/
#define LCM1602_8BIT_MODE
/*在lpc2106下移植成功*/
/*1602 IO定义*/
//1602 RS脚 PA12
#define LCM1602_PIN_RS (0)
//1602 RW脚 PA13
#define LCM1602_PIN_RW (1)
//1602 E脚 PA14
#define LCM1602_PIN_E (2)
//1602 D0
#define LCM1602_PIN_D0 (0)
//1602 D1
#define LCM1602_PIN_D1 (1)
//1602 D2
#define LCM1602_PIN_D2 (2)
//1602 D3
#define LCM1602_PIN_D3 (3)
//1602 D4
#define LCM1602_PIN_D4 (4)
//1602 D5
#define LCM1602_PIN_D5 (5)
//1602 D6
#define LCM1602_PIN_D6 (6)
//1602 D7
#define LCM1602_PIN_D7 (7)
/*设置RS为输出*/
#define LCM1602_RS_OUT
/*设置RS低*/
#define LCM1602_RS_LOW (LCM1602RS = 0)
/*设置RS高*/
#define LCM1602_RS_HIGH (LCM1602RS = 1)
/*设置RW为输出*/
#define LCM1602_RW_OUT
/*设置RW低*/
#define LCM1602_RW_LOW (LCM1602RW = 0)
/*设置RW高*/
#define LCM1602_RW_HIGH (LCM1602RW = 1)
/*设置E为输出*/
#define LCM1602_E_OUT
/*设置E低*/
#define LCM1602_E_LOW (LCM1602E = 0)
/*设置E高*/
#define LCM1602_E_HIGH (LCM1602E = 1)
//8Bit模式操作
#ifdef LCM1602_8BIT_MODE
//设置DATA为输出
#define LCM1602_DATA_OUT
//设置DATA为输入
#define LCM1602_DATA_IN
//获得DATA
#define LCM1602_GET_DATA (P1)
//清除数据
#define LCM1602_CLEAR_DATA (LCM1602_GET_DATA = 0x00)
//设置DATA
#define LCM1602_SET_DATA(x) (LCM1602_GET_DATA = (x))
#endif
//4Bit模式操作
#ifdef LCM1602_4BIT_MODE
#endif
/***********************LCD1602地址相关******************************/
// 第一行DDRAM起始地址
#define LCM1602_LINE1_ADDR (0x80 + 0x00)
// 第二行DDRAM起始地址
#define LCM1602_LINE2_ADDR (0x80 + 0x40)
// 第一行
#define LCM1602_LINE1 (0)
// 第二行
#define LCM1602_LINE2 (1)
// 每行的最大字符长度
#define LCM1602_LINE_LENGTH (16)
//用于检测LCM状态字中的Busy标识
#define LCM1602_BUSY (1 << 7)
//显示清屏。数据指针清零;所有显示清零
//#define LCM1602_ (0x01)
//显示回车。数据指针清零
//#define LCM1602_ (0x02)
/*设置Lcm1602 RS脚状态,0设置低电平;非0设置高电平*/
static void Lcm1602Rs(unsigned char uchStatus);
/*设置Lcm1602 RW脚状态,0设置低电平;非0设置高电平*/
static void Lcm1602Rw(unsigned char uchStatus);
/*设置Lcm1602 E脚状态,0设置低电平;非0设置高电平*/
static void Lcm1602E(unsigned char uchStatus);
/*获得Lcm1602返回的数据*/
static unsigned int Lcm1602GetData(void);
/*向Lcm1602发送数据*/
static void Lcm1602SetData(unsigned char uchData);
/*检查Lcm1602是否读写使能*/
static unsigned char Lcm1602CheckBusy(void);
/*向Lcm1602发送指令*/
static void Lcm1602Command(unsigned char uchInstruction, unsigned char uchBusy);
/*向Lcm1602发送数据*/
static void Lcm1602Data(unsigned char uchData);
extern void delay_ms(unsigned int uiTime);
/*设置1602 RS脚状态*/
void Lcm1602Rs(unsigned char uchStatus)
{
if (0 == uchStatus)
{
LCM1602_RS_LOW;
}
else
{
LCM1602_RS_HIGH;
}
}
/*设置1602 RW脚状态*/
void Lcm1602Rw(unsigned char uchStatus)
{
if (0 == uchStatus)
{
LCM1602_RW_LOW;
}
else
{
LCM1602_RW_HIGH;
}
}
/*设置1602 E脚状态*/
void Lcm1602E(unsigned char uchStatus)
{
if (0 == uchStatus)
{
LCM1602_E_LOW;
}
else
{
LCM1602_E_HIGH;
}
}
/*获得1602数据*/
unsigned int Lcm1602GetData(void)
{
unsigned int uiData;
LCM1602_DATA_IN;
uiData = LCM1602_GET_DATA;
return uiData;
}
/*将数据写到1602*/
void Lcm1602SetData(unsigned char uchData)
{
/*将IO设置为输出*/
LCM1602_DATA_OUT;
LCM1602_CLEAR_DATA;
LCM1602_SET_DATA(uchData);
}
/*检查1602读写操作使能*/
unsigned char Lcm1602CheckBusy(void)
{
unsigned int uiData;
while (1)
{
Lcm1602Rs(0);
Lcm1602Rw(1);
Lcm1602E(1);
/*判断STA7是否为0*/
uiData = Lcm1602GetData();
if (0 == (uiData & LCM1602_BUSY))
{
break;
}
Lcm1602E(0);
}
return uiData;
}
/*写1602指令*/
void Lcm1602Command(unsigned char uchInstruction, unsigned char uchBusy)
{
if (0 != uchBusy)
{
Lcm1602CheckBusy();
}
Lcm1602Rs(0);
Lcm1602Rw(0);
Lcm1602SetData(uchInstruction);
Lcm1602E(1);
delay_ms(1);
Lcm1602E(0);
}
/*写1602数据*/
void Lcm1602Data(unsigned char uchData)
{
Lcm1602CheckBusy();
Lcm1602Rs(1);
Lcm1602Rw(0);
Lcm1602SetData(uchData);
Lcm1602E(1);
delay_ms(1);
Lcm1602E(0);
}
/*初始化1602*/
void Lcm1602Init(void)
{
LCM1602_RS_OUT;
LCM1602_RW_OUT;
LCM1602_E_OUT;
delay_ms(15);
//三次显示模式设置,不检测忙信号
Lcm1602Command(0x38, 0);
delay_ms(5);
Lcm1602Command(0x38, 0);
delay_ms(5);
Lcm1602Command(0x38, 0);
delay_ms(5);
//显示模式设置,开始要求每次检测忙信号
Lcm1602Command(0x38, 1);
//关闭显示
Lcm1602Command(0x08, 1);
//显示清屏
Lcm1602Command(0x01, 1);
//显示光标移动设置
Lcm1602Command(0x06, 1);
//显示开及光标设置
Lcm1602Command(0x0c, 1);
}
#if 0
void Lcm1602Clear(void)
{
Lcm1602Command(0x01, 1);
}
/*****************************************************
函 数 名:void DisplayChar(unsigned char x, unsigned char y, unsigned char uchData)
功 能:按指定坐标中写入数据
说 明:X-横坐标,Y-纵坐标,DData为ASCII值
入口参数:x, y, uchData
返 回 值:无
*****************************************************/
void DisplayChar(unsigned char x, unsigned char y, unsigned char uchData)
{
y &= 0x01;
x &= 0x0F; // 限制X不能大于15,Y不能大于1
if (y)
{
x |=LCM1602_LINE2_ADDR; // 当要显示第二行时地址码:0xc0
}
x |= LCM1602_LINE1_ADDR; // 第一行的地址码:0x80
Lcm1602Command(x, 1);
Lcm1602Data(uchData);
}
#endif
/*****************************************************
函 数 名:void DisplayString(unsigned char x,unsigned char y,unsigned char *puszData)
功 能:向指定坐标中写入字符串(在LCD1602中使用此函数)
说 明:X-横坐标,Y-纵坐标
入口参数:x, y, *puszData
返 回 值:无
*****************************************************/
void DisplayString(unsigned char x,unsigned char y,unsigned char *puszData)
{
if (LCM1602_LINE1 == y) // 判断是否写入第1行
{
if (x < LCM1602_LINE_LENGTH) // 写入位数
{
Lcm1602Command(LCM1602_LINE1_ADDR + x, 1); // 写入第1行地址
for (; x < LCM1602_LINE_LENGTH && *puszData != '\0'; x++)
{
Lcm1602Data(*(puszData++)); // 写入数据
}
if(*puszData!='\0') // 判断数据是否写完
{
x=0; // 没写完写入第2行
y=LCM1602_LINE2;
}
}
}
if (LCM1602_LINE2 == y) // 判断是否写入第2行
{
Lcm1602Command(LCM1602_LINE2_ADDR + x, 1); // 写入第2行地址
for (; x < LCM1602_LINE_LENGTH && *puszData != '\0'; x++) // 判断数据是否写完
{
Lcm1602Data(*(puszData++)); // 写入数据
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -