先介绍硬件环境:
MCU:STM32F030F4,主频16Mhz
显示器:LCD1602A,黄绿屏
软件环境:STM32CUBE_MX
编译器:keil MDK;
不多说了,直接上代码:
/**
硬件连接:
DB4–PA0
DB5–PA1
DB6–PA3
DB7–PA4
RW—PA9
RS—PA10
E----PB1
/
/
读状态。输入RS=0,RW=1,E=高脉冲。输出:D0—D7为状态字。
读数据。输入RS=1,RW=1,E=高脉冲。输出:D0—D7为数据。
写命令。输入RS=0,RW=0,E=高脉冲。输出:无。
写数据。输入RS=1,RW=0,E=高脉冲。输出:无。
**/
#ifndef __LCD_1602_H
#define __LCD_1602_H
#include “main.h”
#define COM 0
#define DAT 1
#define LCD_RS_H() HAL_GPIO_WritePin(LCD_RS_GPIO_Port,LCD_RS_Pin,GPIO_PIN_SET)
#define LCD_RS_L() HAL_GPIO_WritePin(LCD_RS_GPIO_Port,LCD_RS_Pin,GPIO_PIN_RESET)
#define LCD_RW_H() HAL_GPIO_WritePin(LCD_RW_GPIO_Port,LCD_RW_Pin,GPIO_PIN_SET)
#define LCD_RW_L() HAL_GPIO_WritePin(LCD_RW_GPIO_Port,LCD_RW_Pin,GPIO_PIN_RESET)
#define LCD_E_H() HAL_GPIO_WritePin(LCD_E_GPIO_Port,LCD_E_Pin,GPIO_PIN_SET)
#define LCD_E_L() HAL_GPIO_WritePin(LCD_E_GPIO_Port,LCD_E_Pin,GPIO_PIN_RESET)
#define LCD_BusySta() HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_3)
void LCD1602_Init(void);
void LCD1602_ClearScreen(void);
void LCD1602_Show_Str(uint8_t x, uint8_t y, uint8_t *str);
#endif
//
#include “lcd1602.h”
void LCD1602_Set_Cursor(uint8_t x, uint8_t y);
///4线LCD1602
//函数名: delay
//函数功能:LCD1602延时
//注释:
void delay(unsigned char z)
{
unsigned char x,y,j;
for(j=0;j<4;j++)
for(x=z;x>0;x–)
for(y=110;y>0;y–);
}
//
void Send2Lcd(uint8_t data,uint8_t rs)
{
uint8_t i;
if(rs) LCD_RS_H();
else LCD_RS_L();
LCD_RW_L();
for(i=0;i<2;i++)
{
GPIOA->ODR = (GPIOA->ODR & 0xfff0) | ((data>>4) & 0x0f);
LCD_E_H();
delay(50);
LCD_E_L();
data <<= 4;
}
}
//void LCD_CheckBusy(void)
//{
//
// uint16_t portValue;
// portValue = GPIOA->ODR;
// GPIOA->ODR= portValue | 0X000F;
//
// LCD_RS_L();
// LCD_RW_H();
// LCD_E_H();
//
// while(LCD_BusySta());
// LCD_E_L();
//}
/*向1602写入一字节命令,cmd-待写入命令 */
//写入指令PA4-7 RS-0 RW-0
void LCD1602_Write_Cmd(uint8_t cmd)
{
// LCD_CheckBusy();
Send2Lcd(cmd,COM);
}
/* 向1602写入一字节数据*/
void LCD1602_Write_Dat(uint8_t dat)
{
// LCD_CheckBusy();
Send2Lcd(dat,DAT);
}
/清屏/
void LCD1602_ClearScreen(void)
{
LCD1602_Write_Cmd(0x01);
HAL_Delay(2);
}
/* 设置RAM其实地址,即光标位置,(X,Y)对应屏幕上的字符坐标 */
void LCD1602_Set_Cursor(uint8_t x, uint8_t y)
{
// uint8_t addr;
//
// if (y == 0)
// addr = 0x00 + x;
// else
// addr = 0x40 + x;
// LCD1602_Write_Cmd(addr | 0x80);
switch(x)
{
case 0:
y|=0x80;
break;
case 1:
y|=0xc0;
break;
}
LCD1602_Write_Cmd(y);
}
/* 在液晶上显示字符串,(X,Y)-对应屏幕上的其实坐标,str-字符串指针 */
void LCD1602_Show_Str(uint8_t x, uint8_t y, uint8_t *str)
{
LCD1602_Set_Cursor(x, y);
while(*str != ‘\0’)
{
LCD1602_Write_Dat(*str++);
}
}
/* 初始化液晶 */
void LCD1602_Init(void)
{
HAL_Delay(50);
LCD1602_Write_Cmd(0x33);
HAL_Delay(5);
LCD1602_Write_Cmd(0x32);
HAL_Delay(1);
LCD1602_Write_Cmd(0x28); //16*2显示,5*7点阵,4位数据口
HAL_Delay(1);
LCD1602_Write_Cmd(0x01); //清屏
HAL_Delay(1);
LCD1602_Write_Cmd(0x06); //文字不动,地址自动+1
HAL_Delay(1);
LCD1602_Write_Cmd(0x0c);
}
//
//
1、在发送数据的时候,因为硬件是直接在PA低四位,所以采用了寄存器直接输出,如果不是,请调整数据发送。
2、初始化命令要按上面程序的来,我之前用其他初始化程序,在debug完成后,能正常显示,但是直接上电就总是显示不正常。