STM32入门之LCD1602驱动

LCD1602驱动要点:1. STM32的GPIO不是51单片机一样的准双向IO,读忙时需要设置。
平台:STM32F103RCT6
使用的GPIO:PB5,PB6,PB7 ;PA0~PA7,具体的配置程序中有详情
例程下载:点我去下载

贴代码:

main.c

#include "stm32f10x.h"
#include "LCD1602.h"

unsigned char tem[] = {
    
    0x1C,0x14,0x1F,0x09,0x08,0x08,0x09,0x0F};	//摄氏度符号“℃”的字模

int main(){
    
    
	
	LCD_INIT();		//LCD1602初始化
	
	LCD_WRITE_StrDATA( "HELLO",0,5 );		//向屏幕第一行第五列输出HELLO
	LCD_WRITE_StrDATA( "W O R L D !",1,3 ); //向屏幕第一行第三列输出W O R L D !
	
	WUserImg( 0, tem );	//写入用户自定义字符到第一个用户自定义字符位
	LCD_WRITE_CMD( 0x80 );				//指定屏幕第一行第一列输出
	LCD_WRITE_ByteDATA( 0x00 );			//输出第一个用户自定义字符
	
}

LCD.c
#include "LCD1602.h"
#include "stm32f10x_rcc.h"

void delay_us(unsigned int us){
    
    
	unsigned int  i;
	
	do{
    
    
		i = 10;
		while(i--) __nop();
	} while (--us);

}
/***********************************GPIO初始化********************************************/
void GPIO_INIT(void){
    
    		//GPIO初始化
	GPIO_InitTypeDef PB;
	GPIO_InitTypeDef PA;
	
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);	//禁用jtag,不然写入程序和程序执行都会受影响
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );		//打开GPIOA~B
	//RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );
	
	PB.GPIO_Pin = EN|RW|RS;
	PB.GPIO_Mode = GPIO_Mode_Out_PP;
	PB.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &PB);
	
	PA.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;
	PA.GPIO_Mode = GPIO_Mode_Out_PP;
	PA.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &PA);
	
}
/***********************************GPIO初始化********************************************/

/***********************************LCD初始化********************************************/
void LCD_INIT(void){
    
    	//初始化
	GPIO_INIT();	//GPIO的初始化,在LCD_INIT被调用时自动调用
	
	GPIO_Write( GPIOA, 0x0000 );		//初始化GPIOA和GOIOB的值为0x0000,可以不用,个人习惯
	GPIO_Write( GPIOB, 0x0000 );
	
	delay_us(500);
	
	LCD_WRITE_CMD( 0x38 );
	LCD_WRITE_CMD( 0x0d );	//开启光标和闪烁
	LCD_WRITE_CMD( 0x06 );
	LCD_WRITE_CMD( 0x01 );
}
/***********************************LCD初始化********************************************/

/***********************************写入命令函数********************************************/
void LCD_WRITE_CMD( unsigned char CMD ){
    
    		//写入命令函数
	ReadBusy();
	GPIO_ResetBits( GPIOB, RS );
	GPIO_ResetBits( GPIOB, RW );
	GPIO_ResetBits( GPIOB, EN );
	GPIO_Write( GPIOA, CMD );		//
	GPIO_SetBits( GPIOB, EN );
	GPIO_ResetBits( GPIOB, EN );
}
/***********************************写入命令函数********************************************/

/***********************************写入单个Byte函数********************************************/
void LCD_WRITE_ByteDATA( unsigned char ByteData ){
    
    	//写入单个Byte函数
	ReadBusy();
	GPIO_SetBits( GPIOB, RS );
	GPIO_ResetBits( GPIOB, RW );
	GPIO_ResetBits( GPIOB, EN );
	GPIO_Write( GPIOA, ByteData );
	GPIO_SetBits( GPIOB, EN );
	GPIO_ResetBits( GPIOB, EN );
}

/***********************************写入单个Byte函数********************************************/

/***********************************写入字符串函数********************************************/

void LCD_WRITE_StrDATA( unsigned char *StrData, unsigned char row, unsigned char col ){
    
    //写入字符串
	unsigned char baseAddr = 0x00;			//定义8位地址
	if ( row ){
    
    
		baseAddr = 0xc0;
	}else{
    
    
		baseAddr = 0x80;																				   
	} 	//row为1用户选择第二行
		//row为0用户选择第一行
	baseAddr += col;

	while ( *StrData != '\0' ){
    
    

		LCD_WRITE_CMD( baseAddr );
		LCD_WRITE_ByteDATA( *StrData );
	
		baseAddr++;			   //每次循环地址加一,数据指针加一
		StrData++;
	}
}
/***********************************写入字符串函数********************************************/

/***********************************读忙函数********************************************/
void ReadBusy(void){
    
    		//读忙函数,读忙之前记得更改引脚的工作方式!!!因为STM32的IO不是准双向IO
	GPIO_Write( GPIOA, 0x00ff );	
	
	GPIO_InitTypeDef p;
	p.GPIO_Pin = GPIO_Pin_7;		//选定GPIOA的第七Pin
	p.GPIO_Mode = GPIO_Mode_IN_FLOATING;	//第七Pin的工作方式为浮空输入模式,用于检测LCD1602的忙状态
	p.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init( GPIOA, &p );
	
	GPIO_ResetBits( GPIOB, RS );//RS拉低
	GPIO_SetBits( GPIOB, RW );//RW拉高
	
	GPIO_SetBits( GPIOB, EN );	//使能开
	while( GPIO_ReadInputDataBit( GPIOA, GPIO_Pin_7 ) );	//读第七Pin状态,如果一直为1则循环等待
	GPIO_ResetBits( GPIOB, EN );//使能关
		
	p.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;		//使GPIOA的状态还原成推挽模式
	p.GPIO_Mode = GPIO_Mode_Out_PP;
	p.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init( GPIOA, &p  );
}
/***********************************读忙函数********************************************/

/***********************************写入用户自定义图像********************************************/
void WUserImg(unsigned char pos,unsigned char *ImgInfo){
    
     //写入用户自定义图像
	unsigned char cgramAddr;			//CGRAM的用户自定义字符位
	
	if( pos <= 1 ) cgramAddr = 0x40;		// 
	if( pos > 1 && pos <= 3 ) cgramAddr = 0x50;
	if( pos > 3 && pos <= 5 ) cgramAddr = 0x60;
	if( pos > 5 && pos <= 7 ) cgramAddr = 0x70;

	LCD_WRITE_CMD( (cgramAddr + (pos%2) * 8) );	//指定字模写入的地址,一般从0x40开始,0x78结束
	
	while( *ImgInfo != '\0' ){
    
    		//循环写入tem数据,即用户取模的数据
		LCD_WRITE_ByteDATA( *ImgInfo );
		ImgInfo++;
	}
}
/***********************************写入用户自定义图像********************************************/


LCD1602.h
#ifndef LCD1602_H
#define LCD1602_H

#include "stm32f10x_gpio.h"

/***********************************引脚定义********************************************/
#define BUSY 0x80		//忙标志
#define RS GPIO_Pin_5	//设置PB5为RS
#define RW GPIO_Pin_6	//PB6为RW
#define EN GPIO_Pin_7	//PB7为EN使能
//PA0 ~ PA7对应D0 ~D7
/***********************************引脚定义********************************************/

/***********************************函数定义********************************************/
void ReadBusy(void);
void LCD_WRITE_CMD( unsigned char CMD );
void LCD_WRITE_StrDATA( unsigned char *StrData, unsigned char row, unsigned char col );
void LCD_WRITE_ByteDATA( unsigned char ByteData );
void LCD_INIT(void);
void GPIO_INIT(void);
void WUserImg(unsigned char pos,unsigned char *ImgInfo);
/***********************************函数定义********************************************/
#endif

效果图:
在这里插入图片描述
提醒:
图片中

VSS代表 地
VDD代表电源
V0代表灰度显示,一般接电位器,或直接接STM的PWM输出引脚调节灰度显示,不接的话就没有显示!
A一般代表背光电源正极,可以用电位器或PWM调控
K代表背光电源负极

可以参考下图:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_26106317/article/details/99691503