STM32
直播中

刘洋

10年用户 1075经验值
擅长:可编程逻辑 嵌入式技术
私信 关注
[问答]

使用74HC595芯片真的能节省STM32的IO口吗


使用74HC595芯片真的能节省STM32的IO口吗?为什么要使用74HC595芯片呢?

回帖(1)

杨波

2021-11-25 14:35:19
使用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 != '')
        {
                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)
  {
   
  }
  
}
举报

更多回帖

发帖
×
20
完善资料,
赚取积分