.H /*======================*/
#ifndef __lcd1602_H
#define __lcd1602_H
#include "sys.h"
//1602液晶指令/数据选择引脚
#define LCD_RS_Set() GPIO_SetBits(GPIOB, GPIO_Pin_3)
#define LCD_RS_Clr() GPIO_ResetBits(GPIOB, GPIO_Pin_3)
//1602液晶读写引脚
#define LCD_RW_Set() GPIO_SetBits(GPIOB, GPIO_Pin_1)
#define LCD_RW_Clr() GPIO_ResetBits(GPIOB, GPIO_Pin_1)
//1602液晶使能引脚
#define LCD_EN_Set() GPIO_SetBits(GPIOB, GPIO_Pin_2)
#define LCD_EN_Clr() GPIO_ResetBits(GPIOB, GPIO_Pin_2)
void display_gpio_init(void);// 初始化 端口
void LCD1602_Write_Cmd(u8 cmd); //写命令
void LCD1602_Write_Dat(u8 dat); //写数据
void LCD1602_ClearScreen(void); //清屏
void LCD1602_Set_Cursor(u8 x, u8 y); /* 设置显示RAM起始地址,亦即光标位置,(x,y)-对应屏幕上的字符坐标 */
void LCD1602_Show_Str(u8 x, u8 y, u8 *str);
void LCD1602_Init(void); //初始化显示器 16*2显示,5*7点阵,8位数据口
void DATAOUT(u8 data);
void display(void); //液晶显示函数
void display_moving_data(u16 vbat,u16 Icircuit,u16 distance);// 显示实时监测数据
#endif
*C /*===========================*/
#include "lcd1602.h"
#include "stm32f10x.h"
#include "delay.h"
// lcd 显示屏程序
/*
程序运行逻辑
1、初始化 所有使用之端口 为推挽输出 50Mhz
2、开机初始化屏幕 屏幕清零 光标置于左上角 屏幕显示开启
3、设置固定显示项
4、书写动态显示函数
*/
/*
RS---> PB3 命令/数据
RW---> PB1 读/写
EN---> PB2 使能
D0---> PB10 数据端口0
D1---> PB11 数据端口1
D2---> PB12 数据端口2
D3---> PB13 数据端口3
D4---> PB14 数据端口4
D5---> PB15 数据端口5
D6---> PA8 数据端口6
D7---> PA9 数据端口7
*/
void lcd1_init(void) // 通用推挽输出 50Mhz
{
GPIO_InitTypeDef GPIO_InitStructure;//GPIO_InitStructure; 定义初始化名称
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //使能初始化端口时钟
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD; //定义初始化输出模式 开漏输出
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15; //定义初始化输出组,具体引脚
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //定义初始化引脚工作频率
GPIO_Init(GPIOB,&GPIO_InitStructure); //初始化所需使用引脚
}
void lcd2_init(void) // 通用推挽输出 50Mhz
{
GPIO_InitTypeDef GPIO_InitStructure;//GPIO_InitStructure; 定义初始化名称
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能初始化端口时钟
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD; //定义初始化输出模式 开漏输出
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8|GPIO_Pin_9; //定义初始化输出组,具体引脚
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //定义初始化引脚工作频率
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化所需使用引脚
}
// 初始化 端口
void display_gpio_init(void)
{
lcd1_init();
lcd2_init();
}
//LCD1602 数据位输出函数*/
void DATAOUT(u8 data)
{
//分别操作与液晶连接的IO口,顺序是由高位到低位
static u8 d7;
static u8 d6;
static u8 d5;
static u8 d4;
static u8 d3;
static u8 d2;
static u8 d1;
static u8 d0;
// static u8 data1;
// data1=data;
// d7=0;
d7=(data & 0x80) >> 7;
d6=(data & 0x40) >> 6;
d5=(data & 0x20) >> 5;
d4=(data & 0x10) >> 4;
d3=(data & 0x08) >> 3;
d2=(data & 0x04) >> 2;
d1=(data & 0x02) >> 1;
d0=data & 0x01;
GPIO_WriteBit(GPIOA, GPIO_Pin_9 ,(BitAction)d7 );
GPIO_WriteBit(GPIOA, GPIO_Pin_8 ,(BitAction)d6 );
GPIO_WriteBit(GPIOB, GPIO_Pin_15,(BitAction)d5 );
GPIO_WriteBit(GPIOB, GPIO_Pin_14,(BitAction)d4 );
GPIO_WriteBit(GPIOB, GPIO_Pin_13,(BitAction)d3 );
GPIO_WriteBit(GPIOB, GPIO_Pin_12,(BitAction)d2 );
GPIO_WriteBit(GPIOB, GPIO_Pin_11,(BitAction)d1 );
GPIO_WriteBit(GPIOB, GPIO_Pin_10,(BitAction)d0 );
}
//液晶命令执行等待时间
void lcd1602_init(void)
{
DATAOUT(0xff);
LCD_RS_Clr(); //液晶操作方式 命令输入 RS=0
LCD_RW_Set(); //液晶数据方向 写入数据 RW=0
LCD_EN_Set();
delay_ms(5); //延时5ms,非常重要
LCD_EN_Clr();
delay_ms(50); //延时 等待液晶完全准备好
}
/* 向LCD1602液晶写入一字节命令,cmd-待写入命令值 */
void LCD1602_Write_Cmd(u8 cmd)
{
delay_ms(50);
//lcd1602_init(); //初始化液晶
LCD_RS_Clr(); //液晶操作方式 命令输入 RS=0
LCD_RW_Clr(); //液晶数据方向 写入数据 RW=0
DATAOUT(cmd); //写入数据
LCD_EN_Set(); //使能液晶
LCD_EN_Clr(); //关闭液晶
}
/* 向LCD1602液晶写入一字节数据,dat-待写入数据值 */
void LCD1602_Write_Dat(u8 dat)
{
delay_ms(10);
// lcd1602_init(); //初始化液晶
LCD_RS_Set(); //液晶操作方式 数据输入 RS=1
LCD_RW_Clr(); //液晶数据方向 写入数据 RW=0
DATAOUT(dat); //写入数据
LCD_EN_Set(); //使能液晶
LCD_EN_Clr(); //关闭液晶
}
/* 清屏 */
void LCD1602_ClearScreen(void)
{
LCD1602_Write_Cmd(0x01);
}
/* 设置显示RAM起始地址,亦即光标位置,(x,y)-对应屏幕上的字符坐标 */
void LCD1602_Set_Cursor(u8 x, u8 y) //y第几行 0行或者1行,x0-15列
{
u8 addr;
if (y == 0)
addr = 0x00 + x;
else
addr = 0x40 + x;
addr= addr|0x80 ;
LCD1602_Write_Cmd(addr );
}
/* 在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,str-字符串指针 */
void LCD1602_Show_Str(u8 x, u8 y, u8 *str)
{
LCD1602_Set_Cursor(x, y);
while(*str != '\0')
{
LCD1602_Write_Dat(*str++);
}
}
/* 初始化1602液晶 */
void LCD1602_Init(void)
{
LCD1602_Write_Cmd(0x01); //清屏
LCD1602_Write_Cmd(0x38); //16*2显示,5*7点阵,8位数据口
LCD1602_Write_Cmd(0x0c); //开显示,光标关闭
LCD1602_Write_Cmd(0x06); //文字不动,地址自动+1
}
/*单独显示某一行字体*/
void display_uit(u8 x,u8 y,u8 d) //在x列 y行 显示d 单独显示某一字符方式
{
LCD1602_Set_Cursor(x, y);
LCD1602_Write_Dat(d+0x30);
}
void display_moving_data(u16 vbat,u16 Icircuit,u16 distance) //液晶显示函数 // 显示实时监测数据
{
u8 vbat1,vbat2,vbat3,vbat4;
u8 Icircuit1,Icircuit2,Icircuit3,Icircuit4;
u8 distance1,distance2,distance3,distance4;
//电池电压实时更新
vbat1=vbat / 1000 % 10;
vbat2=vbat/ 100 % 10;
vbat3=vbat/ 10 % 10;
vbat4=vbat/ 1 % 10;
display_uit(5,0,vbat1);
display_uit(6,0,vbat2);
display_uit(7,0,vbat3);
display_uit(8,0,vbat4);
//系统电流实时更新
Icircuit1=Icircuit / 1000 % 10;
Icircuit2=Icircuit / 100 % 10;
Icircuit3=Icircuit / 10 % 10;
Icircuit4=Icircuit / 1 % 10;
display_uit(12,0,Icircuit1);
display_uit(13,0,Icircuit2);
display_uit(14,0,Icircuit3);
display_uit(15,0,Icircuit4);
//探测距离实时更新
distance1=distance / 1000 % 10;
distance2=distance/ 100 % 10;
distance3=distance/ 10 % 10;
distance4=distance/ 1 % 10;
display_uit(9,1,distance1);
display_uit(10,1,distance2);
display_uit(11,1,distance3);
display_uit(12,1,distance4);
}
void display(void) //液晶显示函数
{
LCD1602_Show_Str(0,0, "Yang Engineer "); //设置液晶第一行显示 当前系统电压值 电流值
LCD1602_Show_Str(0,1, "Hardware first "); //设置液晶第二行显示 当前系统测试到的距离
delay_ms(500);
LCD1602_Show_Str(0,0, "Vbat:0000 I:0000 "); //设置液晶第一行显示 当前系统电压值 电流值
LCD1602_Show_Str(0,1, "Distance:0000 mm "); //设置液晶第二行显示 当前系统测试到的距离
}