以下为课设期间为1602显示屏驱动写的stm32的程序,其中参考了许多大佬的例子
程序设计:STM32入门之LCD1602驱动_TTOWFIVE-CSDN博客_stm32驱动lcd1602
硬件原理:lcd1602简介,LCD1602中文资料 - 光电显示 - 电子发烧友网 (elecfans.com)
D7D0用的是PD0PD7,RS为PB10,E为PB11,RW为PB12,使用的板子是STM32F103VET6
下面是我的程序,只完成了基础功能,并没有自定义字模部分的代码
#ifndef __LCD_H #define __LCD_H #include "stm32f10x.h" ///////////////////////////////////////////////////////// #define D0_1 GPIO_SetBits(GPIOD,GPIO_Pin_0) #define D0_0 GPIO_ResetBits(GPIOD,GPIO_Pin_0) #define D1_1 GPIO_SetBits(GPIOD,GPIO_Pin_1) #define D1_0 GPIO_ResetBits(GPIOD,GPIO_Pin_1) #define D2_1 GPIO_SetBits(GPIOD,GPIO_Pin_2) #define D2_0 GPIO_ResetBits(GPIOD,GPIO_Pin_2) #define D3_1 GPIO_SetBits(GPIOD,GPIO_Pin_3) #define D3_0 GPIO_ResetBits(GPIOD,GPIO_Pin_3) #define D4_1 GPIO_SetBits(GPIOD,GPIO_Pin_4) #define D4_0 GPIO_ResetBits(GPIOD,GPIO_Pin_4) #define D5_1 GPIO_SetBits(GPIOD,GPIO_Pin_5) #define D5_0 GPIO_ResetBits(GPIOD,GPIO_Pin_5) #define D6_1 GPIO_SetBits(GPIOD,GPIO_Pin_6) #define D6_0 GPIO_ResetBits(GPIOD,GPIO_Pin_6) #define D7_1 GPIO_SetBits(GPIOD,GPIO_Pin_7) #define D7_0 GPIO_ResetBits(GPIOD,GPIO_Pin_7) #define RS_1 GPIO_SetBits(GPIOB,GPIO_Pin_10) #define RS_0 GPIO_ResetBits(GPIOB,GPIO_Pin_10) #define RW_1 GPIO_SetBits(GPIOB,GPIO_Pin_12) #define RW_0 GPIO_ResetBits(GPIOB,GPIO_Pin_12) #define E_1 GPIO_SetBits(GPIOB,GPIO_Pin_11) #define E_0 GPIO_ResetBits(GPIOB,GPIO_Pin_11) ///////////////////////////////////////////////////////// void LCD_Init(void);//初始化 void LCD_Clear(void);//清除显示 void LCD_CursorReset(void);//光标返回 void LCD_SetInput(u16,u16);//置输入模式 void LCD_Display(u16,u16,u16);//显示开关控制 void LCD_COD(u16,u16);//光标或显示移动指令 void LCD_Mode(u16,u16,u16);//工作方式设置 void LCD_CGRAM_Addr(u8);//设置CGRAN地址,除置位位以外共六位 void LCD_DDRAM_Addr(u8);//设置DDRAM地址,除置位位以外共七位 void LCD_RB(void);//当1602处于忙状态时,不接受指令,当不忙时,接受指令 void LCD_Write(u8);//写入数据 void LCD_Read(void);//读取数据 void LCD_WriteStr(u8*,int);//写入字符串 #endif
#include "lcd.h" #include "stm32f10x_gpio.h" void LCD_Init(void) { GPIO_InitTypeDef GPIO_LCDStr; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_LCDStr.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_LCDStr.GPIO_Speed=GPIO_Speed_50MHz; GPIO_LCDStr.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7; GPIO_Init(GPIOD,&GPIO_LCDStr); GPIO_LCDStr.GPIO_Pin=GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_10; GPIO_Init(GPIOB,&GPIO_LCDStr); } /////////////////////////////////////// /////////////////////////////////////// void LCD_Clear(void) { E_0; LCD_RB(); RS_0;RW_0; GPIO_Write(GPIOD,0x01); E_1; E_0; } ///////////////////////////////////////// ///////////////////////////////////////// void LCD_CursorReset(void) { E_0; LCD_RB(); RS_0;RW_0; GPIO_Write(GPIOD,0x02); E_1; E_0; } /////////////////////////////////////////// /////////////////////////////////////////// void LCD_SetInput(u16 ID,u16 S) { E_0; LCD_RB(); RS_0;RW_0;D7_0;D6_0;D5_0;D4_0;D3_0;D2_1; if(ID==1)/*高电平光标右移,低电平左移*/ D1_1; else if(ID==0) D1_0; if(S==1)/*屏幕上所有的文字是否左移或右移,高电平有效,低电平无效*/ D0_1; else if(S==0) D0_0; E_1; E_0; } ///////////////////////////////////////////// ///////////////////////////////////////////// void LCD_Display(u16 D,u16 C,u16 B) { E_0; LCD_RB(); RS_0;RW_0;D7_0;D6_0;D5_0;D4_0;D3_1; if(D==1)//高电平开,低电平关 D2_1; else if(D==0) D2_0; if(C==1)//高电平有光标,低电平无光标 D1_1; else if(C==0) D1_0; if(B==1)//光标是否闪烁,高电平闪烁,低电平无 D0_1; else if(B==0) D0_0; E_1; E_0; } ////////////////////////////////////////////// ////////////////////////////////////////////// void LCD_COD(u16 SC,u16 RL) { E_0; LCD_RB(); RS_0;RW_0;D7_0;D6_0;D5_0;D4_1;D1_1;D0_1; if(SC==1)//高电平显示移动的文字,低电平移动坐标 D3_1; else if(SC==0) D3_0; if(RL==1)//高电平右移,低电平左移 D2_1; else if(RL==0) D2_0; E_1; E_0; } ////////////////////////////////////////////// ////////////////////////////////////////////// void LCD_Mode(u16 DL,u16 N,u16 F) { E_0; LCD_RB(); E_1; RS_0;RW_0;D7_0;D6_0;D5_1;D1_1;D0_1; if(DL==1)//高电平八位数据接口,低电平四位数据接口 D4_1; else if(DL==0) D4_0; if(N==1)//高电平两行显示,低电平一行显示 D3_1; else if(N==0) D3_0; if(F==1)//高电平5x10点阵,低电平5x8点阵 D2_1; else if(F==0) D2_0; E_0; } //////////////////////////////////////////// //////////////////////////////////////////// void LCD_CGRAM_Addr(u8 addr)// { E_0; LCD_RB(); RS_0; RW_0; D6_1; E_1; E_0; } /////////////////////////////////////// /////////////////////////////////////// void LCD_DDRAM_Addr(u8 addr)// { E_0; LCD_RB(); RS_0;RW_0; GPIO_Write(GPIOD,0x0000);//清空地址 GPIO_Write(GPIOD,addr); E_1; E_0; } ///////////////////////////////////////// ///////////////////////////////////////// void LCD_RB(void)// { GPIO_InitTypeDef pp; RS_0;RW_1; pp.GPIO_Mode=GPIO_Mode_IN_FLOATING; pp.GPIO_Speed=GPIO_Speed_50MHz; pp.GPIO_Pin=GPIO_Pin_7; GPIO_Init(GPIOD,&pp);//将端口设为输入 E_1; while(GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_7));//若忙信号存在,则一直循环,直至忙信号结束 E_0; pp.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7; pp.GPIO_Mode=GPIO_Mode_Out_PP; pp.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOD,&pp);//将端口重新设为输出 } ///////////////////////////////////////////// ///////////////////////////////////////////// void LCD_Write(u8 data)// { LCD_RB(); RS_1; RW_0; E_1; GPIO_Write(GPIOD,data); E_0; } ////////////////////////////////////// ////////////////////////////////////// void LCD_Read(void)// { LCD_RB(); RS_1;RW_1;E_1; E_0; } ////////////////////////////////////// ////////////////////////////////////// void LCD_WriteStr(u8 *str,int length)// { int i=0; for(i=0;i<length;i++) {if(i<=15) { LCD_DDRAM_Addr(0x80+i); LCD_Write(str[i]); } else { LCD_DDRAM_Addr(0xc0+i-16); LCD_Write(str[i]); } } }
#include "lcd.h" #include "string.h" int main() { u8 strMCU[]=" **** YOU 1602! TEST TEST "; LCD_Init(); LCD_Clear(); LCD_SetInput(1,0); LCD_Display(1,0,0); LCD_Mode(1,1,0); LCD_WriteStr(strMCU,strlen(strMCU));