/* ************************************************************************************************** * 小浩电子科技 * 文件名: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 // 标准头文件 #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); }