STM32的LCD1602显示程序
以下为课设期间为1602显示屏驱动写的stm32的程序,其中参考了许多大佬的例子
程序设计:STM32入门之LCD1602驱动_TTOWFIVE-CSDN博客_stm32驱动lcd1602
硬件原理:lcd1602简介,LCD1602中文资料 - 光电显示 - 电子发烧友网 (elecfans.com)
D7D0用的是PD0PD7,RS为PB10,E为PB11,RW为PB12,使用的板子是STM32F103VET6
下面是我的程序,只完成了基础功能,并没有自定义字模部分的代码
lcd.h
#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
lcd.c
#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]);
}
}
}
main.c
#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));