STM32F407基于沁恒CH455芯片的矩阵键盘扫描程序设计

目录

一、前言

二、硬件设计

(1)CH455H

(2)矩阵键盘

(3)STM32F407VET6单片机

(4)原理图和PCB

三、程序设计

(1)CH455.h

(2)CH455.c

(3) main.c


一、前言

       使用STM32F407VET6单片机,沁恒CH455H数码管控制及键盘控制芯片,通过外部中断的方式上报键值信息,并通过串口打印。

二、硬件设计

(1)CH455H

       CH455 是数码管显示驱动和键盘扫描控制芯片。CH455 内置时钟振荡电路,可以动态驱动 4 位数码管或者 32 只 LED;同时还可以进行 28 键的键盘扫描;CH455 通过 SCL 和 SDA 组成的 2 线串行接口与单片机等交换数据。


 芯片特点:

  • 内置显示电流驱动级,段电流不小于 25mA,字电流不小于 160mA。
  • 动态显示扫描控制,支持 8×4 或者 7×4,直接驱动 4 位数码管或者 32 只发光管 LED。
  • 内置 28 键键盘控制器,基于 7×4 矩阵键盘扫描。
  • 高速 2 线串行接口,时钟速度从 0 到 4MHz,兼容两线 I2C 总线,节约引脚。
  • 内置上电复位,支持 2.7V~5V 电源电压。
  • 提供低电平有效的键盘中断,提供按键释放标志位,可供查询按键按下与释放。
  • 内置时钟振荡电路,不需要外部提供时钟或者外接振荡元器件,更抗干扰。

     

       也就是说,CH455H芯片可以同时进行4位8段数码管和7*4矩阵键盘的扫描。这里,仅以4*4矩阵键盘为例,设计电路。DIG0~DIG3为列扫描,SEG0~SEG1为行扫描,INT引脚连接单片机的E0引脚。SCL和SDA通过4.7k电阻上拉。

(2)矩阵键盘

       在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式,采用逐行或逐列的“扫描”,就可以读出任何位置按键的状态。这样的行列式键盘结构能够有效地提高单片机系统中I/O口的利用率。节约单片机的资源,其本质和独立按键类似,就是进行逐行扫描和逐列扫描,然后判断是第几行的第几列个按键,进而进行整体按键值得确定。但在使用时,单片机需要定时的逐行逐列扫描按键状态,不仅使用了定时器,而且在程序量较大或对时序要求较高时,定时扫描的方法就比较耗费资源。

       图示为4*4矩阵键盘电路图。SEG和DIG分别连接CH455H芯片的SEG和DIG引脚,DIG0~DIG3、H1~H4引脚单独引出。不使用CH455芯片时,可通过单片机扫描DIG和H1~H4引脚进行按键扫描。

(3)STM32F407VET6单片机

       单片机部分仅说明引脚连接:SCL连接PB8,SDA连接PB9,INT连接PE0。

(4)原理图和PCB

原理图

PCB

三、程序设计

       CH455 的键盘扫描功能支持 7×4 矩阵的 28 键键盘。在键盘扫描期间,DIG3~DIG0 引脚用于列扫描输出,SEG6~SEG0 引脚都带有内部下拉电阻,用于行扫描输入。
       CH455 所提供的按键代码为 8 位,位 7 始终为 0,位 2 始终为 1,位 1~位 0 是列扫描码,位 5~位 3 是行扫描码,位 6 是状态码(键按下为 1,键释放为 0)。例如,连接 DIG1 与 SEG4 的键被按下,则按键代码是 01100101B 或者 65H,键被释放后,按键代码通常是 00100101B 或者 25H(也可能是其它值,但是肯定小于 40H),其中,对应 DIG1 的列扫描码为 01B,对应 SEG4 的行扫描码为 100B。单片机可以在任何时候读取按键代码,但一般在 CH455 检测到有效按键产生键盘中断时读取按键代码,此时按键代码的位 6 总是 1,另外,如果需要了解按键何时释放,单片机可以通过查询方式定期读取按键代码,直到按键代码的位 6 为 0。

       写操作包括以下 6 个步骤:输出启动信号、输出字节 1、应答 1、输出字节 2、应答 2、输出停止信号。其中,启动信号和停止信号如上所述,应答 1 和应答 2 总是固定为 1,输出字节 1 和输出字节 2 各自包含 8 个数据位,即一个字节数据。
       读操作包括以下 6 个步骤:输出启动信号、输出字节 1、应答 1、输入字节 2、应答 2、输出停止信号。其中,启动信号和停止信号如上所述,应答 1 和应答 2 总是固定为 1,输出字节 1 和输入字节 2 各自包含 8 个数据位,即一个字节数据。

       下面,仅给出CH455与main.c程序内容。若有需要整个工程,可直接私信。

(1)CH455.h

#ifndef __CH455_H
#define __CH455_H


#include "stm32f4xx.h"                  // Device header


extern unsigned char key;


void CH455_Init(void);
void CH455_EXIT_Init(void);
unsigned char CH455H_Config(void);
unsigned char CH455H_Read_Key(void);
void CH455_Wait_Ack(void);

#endif


(2)CH455.c

#include "ch455.h"
#include "mpuiic.h"
#include "board.h"

unsigned char key = 0;


void CH455_Init(void)
{
	IIC_Init();
	CH455_EXIT_Init();
	CH455H_Config();
}

unsigned char CH455H_Config(void)
{
	//设置系统参数
    IIC_Start();
    IIC_Send_Byte(0x48);
	
	CH455_Wait_Ack();//应答
	
	IIC_Send_Byte(0x11);		/*[KOFF][INTENS][7SEG][SLEEP]0[ENA]
									ENA: 	1 	使能显示输出和按键扫描
									SLEEP: 	0 	不进入低功耗睡眠状态
									7SEG: 	0 	8段模式
									INTENS: 001 显示驱动占空比为1/8
									KOFF: 	0 	键盘扫描和显示驱动交替进行*/
	CH455_Wait_Ack();//应答
    IIC_Stop();
    return 0;
}


void CH455_EXIT_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct ; 
    EXTI_InitTypeDef    EXTI_InitStruct ;
	
    //使能外设时钟 
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

    //初始化GPIOA引脚1 
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN ; 
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP ; 
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 ; 
    GPIO_Init( GPIOE, & GPIO_InitStruct);

    /* 将引脚和中断线进行连接*/
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE , EXTI_PinSource0 );

    EXTI_InitStruct.EXTI_Line = EXTI_Line0 ;//PA1 对应EXTI_Line1 
    EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt ; 
    EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling ; 
    EXTI_InitStruct.EXTI_LineCmd = ENABLE ; 
    EXTI_Init(&  EXTI_InitStruct) ; 
	
	    /*配置对应外设中断*/
    NVIC_InitTypeDef NVIC_InitStruct ; 
    NVIC_InitStruct.NVIC_IRQChannel =  EXTI0_IRQn  ;  //外部中断1 通道  IRQn 位于stm32f4xx.h 中196行处 
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority =2 ; //抢占优先级 2
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1  ; //响应优先级 2
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE ; //使能中断 

    NVIC_Init(& NVIC_InitStruct);
}


/* 读取键值 */
unsigned char CH455H_Read_Key(void)
{
	unsigned char h=0, l=0;
    unsigned char res;
    IIC_Start();
    IIC_Send_Byte(0x4F);
    CH455_Wait_Ack();             //应答
	res = IIC_Read_Byte(0);		//停止应答
    IIC_Stop();                 //产生一个停止条件
	
	h = (res>>3)&0x7;
	l = res&0x3;
	res = h*4+(4-l);
	
    return res;  
}

/* 等待应答 */
void CH455_Wait_Ack(void)
{
	MPU_SDA_IN();      //SDA设置为输入  
	IIC_SDA=1;
	delay_us(1);   
	IIC_SCL=1;
	delay_us(1);	 
	IIC_SCL=0;//时钟输出0 	   
}


/* 按键中断 */
void EXTI0_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line0) == SET) //检查EXTI_Line1中断标志位
	{
		key = CH455H_Read_Key();
		
		EXTI_ClearITPendingBit(EXTI_Line0) ; //及时清除  EXTI_Line1 的标志位
	}
}




(3) main.c

#include "stm32f4xx.h"                  // Device header
#include "board.h"
#include "led.h"  
#include "key.h"  
#include "exit.h"
#include "ch455.h"
#include "usart.h"  


int main(void)
{
	NVIC_PriorityGroupConfig( NVIC_PriorityGroup_2 ); 
	board_init();
	LED_Init();
	KEY_Init();
	Usart_Config();
	CH455_Init();

	while(1)
	{
		
		printf("%d\r\n", key);
		
		LED1_ON;
		delay_ms(500);
		LED1_OFF;
		delay_ms(500);
	}
}

  • 16
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值