|
@@ -0,0 +1,311 @@
|
|
|
+
|
|
|
+/*
|
|
|
+**************************************************************************************************
|
|
|
+* 小浩电子科技
|
|
|
+* 文件名:stm32驱动1602程序源文件
|
|
|
+* 描 述:
|
|
|
+* 版本号:V2.0
|
|
|
+* 备 注:
|
|
|
+* 程序员:电子极客迷
|
|
|
+* 日 期:2018-04-22
|
|
|
+***************************************************************************************************
|
|
|
+*/
|
|
|
+
|
|
|
+#include "drive_lcd1602.h"
|
|
|
+#include "delay.h"
|
|
|
+#include "stm32f10x.h"
|
|
|
+#include "stm32f10x_gpio.h"
|
|
|
+#include "stm32f10x_rcc.h"
|
|
|
+#include <stdarg.h> // 标准头文件
|
|
|
+#include "stdio.h"
|
|
|
+
|
|
|
+#ifdef LCD602_Bin //
|
|
|
+/*以下为并口驱动程序*/
|
|
|
+///********************************硬件接口定义*********************************/
|
|
|
+#define RS GPIO_Pin_7
|
|
|
+#define RW GPIO_Pin_6
|
|
|
+#define EN GPIO_Pin_5
|
|
|
+#define Control_GPIO GPIOA
|
|
|
+
|
|
|
+/********************************宏定义*********************************/
|
|
|
+#define LCD1602_RS(x) x ? GPIO_SetBits(Control_GPIO, RS): GPIO_ResetBits(Control_GPIO, RS)
|
|
|
+#define LCD1602_RW(x) x ? GPIO_SetBits(Control_GPIO, RW): GPIO_ResetBits(Control_GPIO, RW)
|
|
|
+#define LCD1602_EN(x) x ? GPIO_SetBits(Control_GPIO, EN): GPIO_ResetBits(Control_GPIO, EN)
|
|
|
+void LCDGPIO_Configuration(void);
|
|
|
+
|
|
|
+/*********************************************************************
|
|
|
+*名 称:LcdWaitReady()
|
|
|
+*描 述:等待液晶准备好
|
|
|
+*入口参数:无
|
|
|
+*出口参数:result
|
|
|
+*********************************************************************/
|
|
|
+u8 LcdWaitReady(void)
|
|
|
+{ // 测试LCD忙碌状态
|
|
|
+ u8 result;
|
|
|
+ LCD1602_RS(0); //0;
|
|
|
+ LCD1602_RW(1); //1;
|
|
|
+ LCD1602_EN(1); //1;
|
|
|
+ delay_us(50);
|
|
|
+ result = (GPIO_ReadInputData(GPIOB) & 0x8000)>>8;
|
|
|
+ LCD1602_EN(0); // 0;
|
|
|
+ return result;
|
|
|
+}
|
|
|
+/*********************************************************************
|
|
|
+*名 称: LcdWriteCmd(u8 cmd)
|
|
|
+*描 述:写指令到LCD1602,指令数据占一个字节
|
|
|
+*入口参数:cmd,待写入指令
|
|
|
+*出口参数:无
|
|
|
+*********************************************************************/
|
|
|
+void LCD1602_Write_Cmd(unsigned char cmd)
|
|
|
+{ // 写入指令数据到LCD
|
|
|
+ //while(LcdWaitReady());
|
|
|
+ delay_us(500);
|
|
|
+ LCD1602_RS(0); // 0;
|
|
|
+ LCD1602_RW(0); // 0;
|
|
|
+ LCD1602_EN(0); // 0;
|
|
|
+ delay_us(50);
|
|
|
+ GPIOB->BSRR = cmd<<8 & 0xff00; //将数据送到P0口
|
|
|
+ GPIOB->BRR = ((~cmd)<<8) & 0xff00;
|
|
|
+ delay_us(50);
|
|
|
+ LCD1602_EN(1); // 1;
|
|
|
+ delay_us(50);
|
|
|
+ LCD1602_EN(0); // 0;
|
|
|
+}
|
|
|
+
|
|
|
+/*********************************************************************
|
|
|
+*名 称: LcdWriteCmd(u8 cmd)
|
|
|
+*描 述:写数据到LCD1602,数据占一个字节
|
|
|
+*入口参数:dat,待写入数据
|
|
|
+*出口参数:无
|
|
|
+*********************************************************************/
|
|
|
+void LCD1602_Write_Dat(unsigned char dat)
|
|
|
+{ //写入字符显示数据到LCD
|
|
|
+ //while(LcdWaitReady());
|
|
|
+ delay_us(500);
|
|
|
+ LCD1602_RS(1); //= 1;
|
|
|
+ LCD1602_RW(0); //= 0;
|
|
|
+ LCD1602_EN(0); //= 0;
|
|
|
+ GPIOB->BSRR = dat<<8 & 0xff00; ////P0 = dat
|
|
|
+ GPIOB->BRR = ((~dat)<<8) & 0xff00;
|
|
|
+ delay_us(50);
|
|
|
+ LCD1602_EN(1);// = 1;
|
|
|
+ delay_us(50);
|
|
|
+ LCD1602_EN(0);// = 0;
|
|
|
+ delay_us(50);
|
|
|
+}
|
|
|
+/*********************************************************************
|
|
|
+*名 称:InitLcd1602()
|
|
|
+*描 述:初始化1602液晶
|
|
|
+*入口参数:无
|
|
|
+*出口参数:无
|
|
|
+*********************************************************************/
|
|
|
+void Init_Lcd1602(void)
|
|
|
+{
|
|
|
+ //LCD初始化设定
|
|
|
+ LCDGPIO_Configuration();
|
|
|
+ delay_ms(100);
|
|
|
+ LCD1602_Write_Cmd(0x38); //16*2显示,5*7点阵,8位数据
|
|
|
+ delay_ms(30);
|
|
|
+ LCD1602_Write_Cmd(0x0c); //显示开,关光标
|
|
|
+ delay_ms(30);
|
|
|
+ LCD1602_Write_Cmd(0x06); //移动光标
|
|
|
+ delay_ms(30);
|
|
|
+ LCD1602_Write_Cmd(0x01); //清除LCD的显示内容
|
|
|
+ delay_ms(30);
|
|
|
+}
|
|
|
+/*********************************************************************
|
|
|
+*名 称:LcdClearScreen()
|
|
|
+*描 述:清屏
|
|
|
+*入口参数:无
|
|
|
+*出口参数:无
|
|
|
+*********************************************************************/
|
|
|
+void LcdClearScreen(void)
|
|
|
+{
|
|
|
+ LCD1602_Write_Cmd(0x01);
|
|
|
+}
|
|
|
+
|
|
|
+/*********************************************************************
|
|
|
+*名 称:LcdOpenCursor()
|
|
|
+*描 述:打开光标的闪烁效果
|
|
|
+*入口参数:无
|
|
|
+*出口参数:无
|
|
|
+*********************************************************************/
|
|
|
+void LcdOpenCursor(void)
|
|
|
+{
|
|
|
+ LCD1602_Write_Cmd(0x0F);
|
|
|
+}
|
|
|
+
|
|
|
+/*********************************************************************
|
|
|
+*名 称:LcdCloseCursor()
|
|
|
+*描 述: 关闭光标显示
|
|
|
+*入口参数:无
|
|
|
+*出口参数:无
|
|
|
+*********************************************************************/
|
|
|
+void LcdCloseCursor(void)
|
|
|
+{
|
|
|
+ LCD1602_Write_Cmd(0x0C);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void LCDGPIO_Configuration(void)
|
|
|
+{
|
|
|
+ GPIO_InitTypeDef GPIO_InitStructure;
|
|
|
+
|
|
|
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
|
|
|
+
|
|
|
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//RS RW EN 控制脚 时钟
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
|
|
|
+ GPIO_Init(GPIOB,&GPIO_InitStructure);
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 |GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
|
|
|
+ //所有GPIO为同一类型端口
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //开漏输出
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //输出的最大频率为50HZ
|
|
|
+ GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB端口
|
|
|
+
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_6|GPIO_Pin_5;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
|
|
|
+ GPIO_Init(Control_GPIO,&GPIO_InitStructure);
|
|
|
+}
|
|
|
+#else
|
|
|
+
|
|
|
+//1602指令/数据 引脚 rs
|
|
|
+#define LCD_RS_Set() GPIO_SetBits(GPIOB, GPIO_Pin_7)
|
|
|
+#define LCD_RS_Clr() GPIO_ResetBits(GPIOB, GPIO_Pin_7)
|
|
|
+
|
|
|
+//1602读写引脚 rw可以不用 直接接地
|
|
|
+#define LCD_RW_Set() GPIO_SetBits(GPIOB, GPIO_Pin_6)
|
|
|
+#define LCD_RW_Clr() GPIO_ResetBits(GPIOB, GPIO_Pin_6)
|
|
|
+
|
|
|
+//1602使能引脚 en
|
|
|
+#define LCD_EN_Set() GPIO_SetBits(GPIOB, GPIO_Pin_6)
|
|
|
+#define LCD_EN_Clr() GPIO_ResetBits(GPIOB, GPIO_Pin_6)
|
|
|
+
|
|
|
+
|
|
|
+//1602数据端口 PD4~7 //采用操作一组io写方法使用 不建议用
|
|
|
+#define DATAOUT(x) GPIO_Write(LCD_DATA_PORT, x)
|
|
|
+#define LCD_DATA_PORT GPIOB
|
|
|
+
|
|
|
+
|
|
|
+void LCDGPIO_Configuration(void)
|
|
|
+{
|
|
|
+ GPIO_InitTypeDef GPIO_InitStructure;
|
|
|
+
|
|
|
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA,ENABLE);//打开时钟
|
|
|
+ //dataIO GPIOA4~7 初始化
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_Init(LCD_DATA_PORT, &GPIO_InitStructure);
|
|
|
+ // RS RW E IO初始化
|
|
|
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_6|GPIO_Pin_5; //rw rs en
|
|
|
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
|
|
|
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
+ GPIO_Init(GPIOB, &GPIO_InitStructure);
|
|
|
+}
|
|
|
+
|
|
|
+/* 检测液晶忙不忙 */
|
|
|
+void LCD1602_Wait_Ready(void)
|
|
|
+{
|
|
|
+ int8_t sta;
|
|
|
+ DATAOUT(0xff); //PA端口全部置1
|
|
|
+ LCD_RS_Clr(); //RS 0
|
|
|
+ LCD_RW_Set(); //RW 1
|
|
|
+ do
|
|
|
+ {
|
|
|
+ LCD_EN_Set(); //EN 1
|
|
|
+ delay_ms(5); //延时5MS
|
|
|
+ sta = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15);//读取状态字
|
|
|
+ LCD_EN_Clr(); //EN 0
|
|
|
+ }while(sta & 0x80);//bit7等于1表示忙,重复检测到其为0停止
|
|
|
+}
|
|
|
+/*
|
|
|
+向1602写入一字节命令,cmd-待写入命令
|
|
|
+//写入指令 RS-0 RW-0
|
|
|
+*/
|
|
|
+
|
|
|
+void LCD1602_Write_Cmd(unsigned char cmd)
|
|
|
+{
|
|
|
+ char ik=0;
|
|
|
+ delay_ms(10); //不判忙信号 必须加入延时
|
|
|
+ //LCD1602_Wait_Ready(); //判断忙不忙
|
|
|
+ LCD_RS_Clr();
|
|
|
+
|
|
|
+ for(ik=0;ik<2;ik++) //操作一位一位的写数据进去 建议用这种写法 不影响其他位
|
|
|
+ {
|
|
|
+ LCD_EN_Set();
|
|
|
+ GPIO_ResetBits(GPIOB,GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);//数据口全部写低
|
|
|
+ if(cmd&0x80) GPIO_SetBits(GPIOB,GPIO_Pin_15);
|
|
|
+ if(cmd&0x40) GPIO_SetBits(GPIOB,GPIO_Pin_14);
|
|
|
+ if(cmd&0x20) GPIO_SetBits(GPIOB,GPIO_Pin_13);
|
|
|
+ if(cmd&0x10) GPIO_SetBits(GPIOB,GPIO_Pin_12);
|
|
|
+ LCD_EN_Clr();
|
|
|
+ cmd=cmd<<4;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 向1602写入一字节数据*/
|
|
|
+void LCD1602_Write_Dat(unsigned char dat)
|
|
|
+{
|
|
|
+ char ik=0;
|
|
|
+ delay_ms(10); //不判忙信号 必须加入延时
|
|
|
+ LCD_RS_Set(); //1
|
|
|
+ for(ik=0;ik<2;ik++)
|
|
|
+ {
|
|
|
+ LCD_EN_Set();
|
|
|
+ GPIO_ResetBits(GPIOB,GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);
|
|
|
+ if(dat&0x80) GPIO_SetBits(GPIOB,GPIO_Pin_15);
|
|
|
+ if(dat&0x40) GPIO_SetBits(GPIOB,GPIO_Pin_14);
|
|
|
+ if(dat&0x20) GPIO_SetBits(GPIOB,GPIO_Pin_13);
|
|
|
+ if(dat&0x10) GPIO_SetBits(GPIOB,GPIO_Pin_12);
|
|
|
+ LCD_EN_Clr();
|
|
|
+ dat=dat<<4;
|
|
|
+ }
|
|
|
+}
|
|
|
+/* 初始化液晶*/
|
|
|
+void Init_Lcd1602(void)
|
|
|
+{
|
|
|
+ LCDGPIO_Configuration();//IO配置初始化
|
|
|
+ LCD1602_Write_Cmd(0x28); //16*2显示,5*7点阵,4位数据口
|
|
|
+ LCD1602_Write_Cmd(0x0C); //开显示,光标关闭
|
|
|
+ LCD1602_Write_Cmd(0x06); //文字不动,地址自动+1
|
|
|
+ LCD1602_Write_Cmd(0x01); //清屏
|
|
|
+}
|
|
|
+
|
|
|
+#endif
|
|
|
+
|
|
|
+/************ 写字符数据函数 *****************
|
|
|
+//功能:在lcd1602指定位置上显示字符;
|
|
|
+//参数
|
|
|
+//p: 指向待显示数据指针
|
|
|
+//x: X坐标
|
|
|
+//y: Y坐标
|
|
|
+*/
|
|
|
+void WriteLcd1602_String(char x,char y,char *p)
|
|
|
+{
|
|
|
+ if(y == 0)
|
|
|
+ {
|
|
|
+ LCD1602_Write_Cmd(0x80 + x);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ LCD1602_Write_Cmd(0xC0 + x);
|
|
|
+ }
|
|
|
+ while(*p != 0)
|
|
|
+ {
|
|
|
+ LCD1602_Write_Dat(*p);
|
|
|
+ p++;
|
|
|
+ }
|
|
|
+}
|
|
|
+void L1602_printf(char x,char y,char *p,...)
|
|
|
+{
|
|
|
+ char Lcdbuf[16];
|
|
|
+ va_list ap;
|
|
|
+ va_start(ap,p);
|
|
|
+ vsprintf(Lcdbuf,p,ap);
|
|
|
+ va_end(ap);
|
|
|
+ WriteLcd1602_String(x,y,Lcdbuf);
|
|
|
+}
|
|
|
+
|