STM32的LCD1602顯示程序
以下為課設期間為1602顯示屏驅動寫的stm32的程序,其中參考了許多大佬的例子
程序設計:STM32入門之LCD1602驅動_TTOWFIVE-CSDN博客_stm32驅動lcd1602
硬件原理:lcd1602簡介,LCD1602中文資料 - 光電顯示 - 電子發燒友網 (elecfans.com)
D0-D7用的是PD0-PD7,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));