【STM32學習】(16)STM32實現LCD1602顯示(74HC595驅動)- 4位總線

使用74HC595芯片的目的其實很簡單,就是爲節省STM32的IO口。

如果不使用74HC595模塊,我們將要使用D0-D7八個數據腳,還有RS,RW,EN控制引腳,也就是說要很多IO腳,這樣就不便於STM32的其他功能或模塊的擴展,是不可取的。而使用595模塊就能很好的解決這個問題。

使用的單片機型號:STM32L052K8*

液晶顯示的模塊:RG1602A,其實和LCD1602是一樣的。

接線,如下圖(很重要):

你會發現只需要將74HC595的三個引腳接在STM32 上就可以了,但要提示一下,不是要求必須接PB1、PA5、PA7,其實是隨便你怎麼接,需要代碼進行修改就行。

1.LCD1602的實現

 

       ||*可以發現只使用了4位控制線實現數據傳輸

                  如何實現傳輸的呢?   ——假如要傳輸一個字節的數據,需要先傳輸該字節的高四位,然後再傳輸該字節的低四位

根據配置RS和EN來進行寫數據寫命令

     關於LCD1602的管腳及功能信息在之前的博客也有涉及,大家可以看看我之前的博客。

  2.74HC595實現串行並出

       ||*數據的發送

                 這個在之前的博客也講到過,可以查看之前的博客。一定要注意時序的關係。

關於IO口的初始化配置,如下:

static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, SCLK_Pin|DATA_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(RCLK_GPIO_Port, RCLK_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pins : SCLK_Pin DATA_Pin */
  GPIO_InitStruct.Pin = SCLK_Pin|DATA_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pin : RCLK_Pin */
  GPIO_InitStruct.Pin = RCLK_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(RCLK_GPIO_Port, &GPIO_InitStruct);

}

lcd1602.c

#include "lcd1602.h"   
#include "stdio.h" 
#include "main.h"

/**********************************/
/** 函數名稱:void LCD1602_Send595OneByte(unsigned char dis_data) **/
/** 輸入參數:unsigned char dis_data 需要輸入的數據  */
/** 函數功能:將數據寫進74HC595中*/
/** ****************************** **/
void LCD1602_Send595OneByte(unsigned char dis_data)
{
	unsigned char i;
	unsigned char temp;
	temp = dis_data;
	for(i=0;i<8;i++)
	{
		HAL_GPIO_WritePin(SCLK_GPIO_Port,SCLK_Pin,GPIO_PIN_RESET);	
		if(temp & 0X80)
		{
			HAL_GPIO_WritePin(DATA_GPIO_Port,DATA_Pin,GPIO_PIN_SET);
		}
		else
		{
			HAL_GPIO_WritePin(DATA_GPIO_Port,DATA_Pin,GPIO_PIN_RESET);
		}
		temp = temp<<1;
		HAL_GPIO_WritePin(SCLK_GPIO_Port,SCLK_Pin,GPIO_PIN_RESET);		//	0
		HAL_GPIO_WritePin(SCLK_GPIO_Port,SCLK_Pin,GPIO_PIN_SET);			//	1
		HAL_GPIO_WritePin(SCLK_GPIO_Port,SCLK_Pin,GPIO_PIN_RESET);		//	0
	}
}

/****************************************/
/**函數名稱:void LCD1602_OUT(void)			*/
/**函數參數:無參							*/
/**函數功能:寄存器數據輸出顯示			*/
void LCD1602_OUT(void)
{
	HAL_GPIO_WritePin(RCLK_GPIO_Port,RCLK_Pin,GPIO_PIN_RESET);
	HAL_GPIO_WritePin(RCLK_GPIO_Port,RCLK_Pin,GPIO_PIN_SET);
	HAL_GPIO_WritePin(RCLK_GPIO_Port,RCLK_Pin,GPIO_PIN_RESET);
}


/* 向LCD1602液晶寫入一字節命令,cmd-待寫入命令值 */
//液晶寫指令
void LCD1602_Write_Command(uint8_t command)
{
	LCD1602_Send595OneByte(0x02);								//LCD1602_EN=1,LCD1602_RS=0,清高4位
	LCD1602_OUT();
	LCD1602_Send595OneByte(0x02|(((command & 0xf0)>>4)<<2));	//LCD1602_EN=1,LCD1602_RS=0,寫高4位
	LCD1602_OUT();
	LCD1602_Send595OneByte(0x00|(((command & 0xf0)>>4)<<2));	//LCD1602_EN=0,LCD1602_RS=0,寫高4位
	LCD1602_OUT();
	
	command = command << 4;										//低4位移到高4位
	LCD1602_Send595OneByte(0x02);								//LCD1602_EN=1,LCD1602_RS=0,清高4位
	LCD1602_OUT();
	LCD1602_Send595OneByte(0x02|(((command & 0xf0)>>4)<<2));	//LCD1602_EN=1,LCD1602_RS=0,寫低4位
	LCD1602_OUT();
	LCD1602_Send595OneByte(0x00|(((command & 0xf0)>>4)<<2));	//LCD1602_EN=0,LCD1602_RS=0,寫低4位
	LCD1602_OUT();
}

//液晶寫數據
void LCD1602_Write_Data(uint8_t RecData)
{

	LCD1602_Send595OneByte(0x03);								//LCD1602_EN=1,LCD1602_RS=1,清高4位
	LCD1602_OUT();
	LCD1602_Send595OneByte(0x03|(((RecData & 0xf0)>>4)<<2));	//LCD1602_EN=1,LCD1602_RS=1,寫高4位
	LCD1602_OUT();
	LCD1602_Send595OneByte(0x01|(((RecData & 0xf0)>>4)<<2));	//LCD1602_EN=0,LCD1602_RS=1,寫高4位
	LCD1602_OUT();
	
	RecData = RecData << 4;										//低4位移到高4位
	LCD1602_Send595OneByte(0x03);								//LCD1602_EN=1,LCD1602_RS=1,清高4位
	LCD1602_OUT();
	LCD1602_Send595OneByte(0x03|(((RecData & 0xf0)>>4)<<2));	//LCD1602_EN=1,LCD1602_RS=1,寫低4位
	LCD1602_OUT();
	LCD1602_Send595OneByte(0x01|(((RecData & 0xf0)>>4)<<2));	//LCD1602_EN=0,LCD1602_RS=1,寫低4位
	LCD1602_OUT();
}

/* 清屏 */
void LCD1602_ClearScreen(void)
{
	LCD1602_Write_Command(0x01);
}

/* 設置顯示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_Command(addr | 0x80);
}

/* 在液晶上顯示字符串,(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_Data(*str++);
	}
}

/* 初始化1602液晶 */
void LCD1602_Init(void)
{
	LCD1602_Write_Command(0x33);	//原來1602初始化成4位數據線之前必需先初始化成8位(此時命令發送方式是8位格式,但數據線只需接4位)
	LCD1602_Write_Command(0x32);	//然後再改到4位線寬,這樣初始化才穩定
	LCD1602_Write_Command(0x28);	//四線模式設置
	LCD1602_Write_Command(0x0c);	//顯示開  
	LCD1602_Write_Command(0x01);	//清屏
	HAL_Delay(10);    
  
}

lcd1602.h

#include "main.h"
#ifndef __LCD1602_H
#define __LCD1602_H	 


void LCD1602_Send595OneByte(unsigned char dis_data);
void LCD1602_OUT(void);

void LCD1602_Wait_Ready(void);
void LCD1602_Write_Command(uint8_t cmd);
void LCD1602_Write_Data(uint8_t dat);
void LCD1602_ClearScreen(void);
void LCD1602_Set_Cursor(uint8_t x, uint8_t y);
void LCD1602_Show_Str(uint8_t x, uint8_t y, uint8_t *str);
void LCD1602_Init(void);

#endif

main.c

int main(void)
{
  
  uint8_t str[] = "   WANGTING";
  SystemClock_Config(); 
  MX_GPIO_Init();

  LCD1602_Init();
  LCD1602_Show_Str(1, 0, str);
  LCD1602_Show_Str(2, 1, "I LOVE STM32");
 
  while (1)
  {
   
  }
  
}

實現效果如下:

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章