紫荆小兵的个人空间 https://bbs.21ic.com/?1503458 [收藏] [复制] [RSS]

日志

LCD 1602 显示器操作 总结

已有 164 次阅读2019-3-17 17:31 |系统分类:兴趣爱好

.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 ");   //设置液晶第二行显示 当前系统测试到的距离
 }
 
 



路过

鸡蛋

鲜花

握手

雷人

全部作者的其他最新日志

评论 (0 个评论)