STM32CUBEMX_74HC165扩展芯片检测按键

实验1:点亮LED
实验2:按键控制LED
实验3:外部中断检测按键
实验4:扩展芯片检测按键
实验5:定时器实现LED闪烁
实验6:基于PWM的呼吸灯
实验7:检测输入的PWM频率和脉宽
实验8:串口的输入和输出
实验9:串口使用PRINTF函数
实验10:SPI接口操作片外FLASH
实验11:SPI接口操作TF卡
实验12:IIC接口操作OLED屏幕
实验13:ADC电压采样

实际应用过程中,经常会遇到按键过多,GPIO不够用的情况。这时我们需要通过外部芯片来对按键检测功能进行扩展。方式有很多,这里使用的是74HC165芯片,仅用3个IO即可检测8、16、32..甚至100多个按键。

74HC165检测按键的电路如下:

连接到单片机上的接口如下,分别是PB0、PB1、PB2:

接下来打开STM32CUBEMX,进行相应操作:

1、新建工程,进行基本配置。通过点击“ACCESS TO MCU SELECTOR”来创建一个新的工程:

参照实验1,芯片选择“STM32F103C8”。

打开外部时钟,点击“System Core”,选择RCC,在右侧弹出的菜单栏中选择“Crystal/Ceramic Resonator”。

选择调试接口,点击“System Core”,选择RCC。,在右侧弹出的菜单栏中选择“Serial Wire”。

2、LED的IO配置。依然使用PC15、PA1、PA2,参照实验1,依次对这三个管脚进行配置(输出模式),分别命名为D1、D2、D3。

3、74HC165的相关IO配置。该芯片的使用需要用到三个IO,这里用STM32的PB0PB1PB2来进行驱动。

PB0配置为输出模式,命名为:HC165_SH

PB1配置为输出模式,命名为:HC165_CLK

PB2配置为输入模式,命名为:HC165_DS

同时,在GPIO页面,确保PB0和PB1的初始值为低电平,PB2的上拉电阻打开。如下:

4、时钟配置。参照实验1.

5、生成工程。参照实验1的步骤7,进行相应配置,生成工程文件。

6、修改工程-添加74HC165驱动程序。驱动程序为网友在网上分享,这里演示下如何添加到工程中。

先把包含74HC165驱动程序的文件夹,复制、粘贴到指定位置。这里我们选择该路径:USB04KEYSER\Drivers\CMSIS\Device,如图:

然后打开工程,如图,点击“Option for Target”按钮,选择“C/C++”选项卡,点击“Include Paths”后面的按钮。

在弹出的页面中,点击位置1,为当前工程添加一个新的驱动程序路径;点击位置2,选择刚才我们粘贴的文件夹。注意是文件夹,不是文件,因为这里添加的是路径。

我这里已经添加好了,然后直接点击OK即可。

接下来,如下鼠标右键点击“Application/User/Core”,在弹出的对话框里选择“Add Existing Files to Group ‘Application/User/Core’..”

在弹出的对话框中,选择刚才粘贴的文件夹中的“hc165.c”文件,然后依次点击”Add”、“Close”即可。

这是,该文件会出现在左侧的工程栏里,如下:

7、修改工程-调用74HC165驱动程序。

先确保IO相关的宏定义,在hc165.h中:

#ifndef __HC165_H
#define __HC165_H
//#include "stm32f0xx.h"
//#include "systick_delay.h"
//#include "main.h"
#include "gpio.h"

#define CLK_L	HAL_GPIO_WritePin(HC165_CLK_GPIO_Port, HC165_CLK_Pin, GPIO_PIN_RESET)
#define CLK_H	HAL_GPIO_WritePin(HC165_CLK_GPIO_Port, HC165_CLK_Pin, GPIO_PIN_SET)
#define SL_L	HAL_GPIO_WritePin(HC165_SH_GPIO_Port, HC165_SH_Pin, GPIO_PIN_RESET)
#define SL_H	HAL_GPIO_WritePin(HC165_SH_GPIO_Port, HC165_SH_Pin, GPIO_PIN_SET)
#define DAT	HAL_GPIO_ReadPin(HC165_DS_GPIO_Port, HC165_DS_Pin)

void HC165_PIN_INIT(void);
uint8_t ReadByte_165(void);

#endif

然后在main.c中,定义一个变量,用来存储读取到的按键状态:

接下来,在main.c中添加一段代码,用来实现us级别的延时:

/* USER CODE BEGIN 0 */
typedef uint8_t u8;
typedef uint32_t u32;
u8 fac_us;

void delay_init(u8 SYSCLK)
{
    #if SYSTEM_SUPPORT_OS
        u32 reload;
    #endif
   
    HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
    //SysTick  HCLK
    fac_us=SYSCLK;              // OS,fac_us
   
    #if SYSTEM_SUPPORT_OS       // OS.
        reload=SYSCLK;
        reload*=1000000/delay_ostickspersec;    //delay_ostickspersec
        //reload 24Bit 16777216, 180M 0.745s
        fac_ms=1000/delay_ostickspersec;        // OS.
        SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;// SYSTICK
        SysTick->LOAD=reload;                   // 1/OS_TICKS_PER_SEC
        SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk; // SYSTICK
        #else
    #endif
}


void delay_us(u32 nus)
{
    u32 ticks;
    u32 told,tnow,tcnt=0;
    u32 reload=SysTick->LOAD;                   //LOAD
    ticks=nus*fac_us;
    told=SysTick->VAL;
    while(1)
    {
        tnow=SysTick->VAL;
        if(tnow!=told)
        {
            if(tnow<told)tcnt+=told-tnow;       // SYSTICK.
            else tcnt+=reload-tnow+told;
            told=tnow;
            if(tcnt>=ticks)break;
        }
    }
}

要使该延时生效,需要在初始化阶段调用延时初始化函数:

最后,在while(1)主循环里添加调用74HC165读取外部按键状态的函数,并做出处理:

		key_value = ReadByte_165();
		if(key_value != 0xff)
		{
			if(key_value == 0xfe)
			{
				HAL_GPIO_TogglePin(D1_GPIO_Port,D1_Pin);
			}
			else if(key_value == 0xfd)
			{
				HAL_GPIO_TogglePin(D2_GPIO_Port,D2_Pin);
			}
			else if(key_value == 0xfb)
			{
				HAL_GPIO_TogglePin(D3_GPIO_Port,D3_Pin);
			}
			HAL_Delay(10);
			while(0xff != ReadByte_165());
		}

位置如下:

修改后,保存,编译、下载,重新上电。KUP、KDOWN、K_LEFT这三个按键,每按一下按键,对应LED的状态翻转一次。

整个过程有PPT、数据手册、原理图、源码、相关软件,在公众号(单片机爱好者)回复关键词:002或者STM32CUBEMX教程,即可获取下载链接。

留下评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据