1、概述

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

2、特点

●内置显示电流驱动级,段电流不小于25mA,字电流不小于160mA。

●动态显示扫描控制,支持8×4或者7×4,直接驱动4位数码管或者32只发光管LED。

●内部限流,通过占空比设定提供8级亮度控制。

●内置28键键盘控制器,基于7×4矩阵键盘扫描。

●内置按键状态输入的下拉电阻,内置去抖动电路。

●提供低电平有效的键盘中断,提供按键释放标志位,可供查询按键按下与释放。

●高速2线串行接口,时钟速度从0到4MHz,兼容两线I2C总线,节约引脚。

●内置上电复位,支持2.7V~5V电源电压。

●支持低功耗睡眠,节约电能,可以被按键唤醒或者被命令操作唤醒。

●内置时钟振荡电路,不需要外部提供时钟或者外接振荡元器件,更抗干扰。

3、引脚介绍

VCC:电源正电源,持续电流不小于150mA

GND:电源公共接地,持续电流不小于150mA

SEG0 ~SEG6:三态输出及输入数码管的段驱动,高电平有效,键盘扫描输入,高电平有效,内置下拉

SEG7:输出数码管的小数点段驱动输出,高电平有效,7段模式下的键盘中断输出,低电平有效

DIG0 ~DIG3:输出数码管的字驱动,低电平有效,键盘扫描输出,高电平有效

SDA:内置上拉开漏输出及输入2线串行接口的数据输入和输出,内置上拉电阻SCL:输入2线串行接口的数据时钟,内置上拉电阻

4、键盘扫描功能

  键盘扫描CH455的键盘扫描功能支持7×4矩阵的28键键盘。在键盘扫描期间,DIG3~DIG0引脚用于列扫描输出,SEG6~SEG0引脚都带有内部下拉电阻,用于行扫描输入。CH455定期在显示驱动扫描过程中插入键盘扫描。在键盘扫描期间,DIG3~DIG0引脚按照DIG0至DIG3的顺序依次输出高电平,其余引脚输出低电平;SEG6~SEG0引脚的输出被禁止,当没有键被按下时,SEG6~SEG0都被下拉为低电平;当有键被按下时,例如连接DIG1与SEG4的键被按下,则当DIG1输出高电平时SEG4检测到高电平;为了防止因为按键抖动或者外界干扰而产生误码,CH455实行两次扫描,只有当两次键盘扫描的结果相同时,按键才会被确认有效。如果CH455检测到有效的按键,则记录下该按键代码,并通过INT#引脚产生低电平有效的键盘中断,此时单片机可以通过串行接口读取按键代码;在没有检测到新的有效按键之前,CH455不再产生任何键盘中断。CH455支持SEG1和SEG0针对同一DIG的组合键,组合键是最优先的,除此之外,如果多个键同时按下,那么按键代码较小的按键优先。例如连接DIG1与SEG1及连接DIG1与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。下表是在DIG3~DIG0与SEG6~SEG0之间7×4矩阵的按键编址,也是数码管段位和发光管LED阵列的顺序编址。由于按键代码是8位,键按下时位6总是1,所以当键按下时,CH455所提供的实际按键代码是表中的按键编址加上40H,也就是说,此时的按键代码应该在44H到7FH之间。

编址 DIG3 DIG2 DIG1 DIG0
SEG0 07H 06H 05H 04H
SEG1 0FH 0EH 0DH 0CH
SEG2 17H 16H 15H 14H
SEG3 1FH 1EH 1DH 1CH
SEG4 27H 26H 25H 24H
SEG5 2FH 2EH 2DH 2CH
SEG6 37H 36H 35H 34H
SEG0+SEG1 3FH 3EH 3DH 3CH

5、串行接口

  CH455具有硬件实现的2线串行接口,包含2个主要信号线:串行数据时钟输入线SCL、串行数据输入和输出线SDA;以及1个辅助信号线:中断输出线INT#。其中,SCL是带上拉的输入信号线,CH455中文手册4默认是高电平;SDA是带上拉的准双向信号线,默认是高电平;INT#是带上拉的开漏输出,在启用键盘扫描功能后作为键盘中断输出线,默认是高电平。SDA用于串行数据输入和输出,高电平表示位数据1,低电平表示位数据0,串行数据输入的顺序是高位在前,低位在后。SCL用于提供串行时钟,CH455在其上升沿从SDA输入数据,在其下降沿从SDA输出数据。在SCL为高电平期间发生的SDA下降沿定义为串行接口的启动信号,在SCL为高电平期间发生的SDA上升沿定义为串行接口的停止信号。CH455只在检测到启动信号后才接收并分析命令。所以在单片机I/O引脚资源紧张时,可以在保持SDA引脚状态不变的情况下,将SCL引脚与其它接口电路共用;如果能够确保SDA引脚的变化仅在SCL引脚为低电平期间发生,那么SCL引脚和SDA引脚都可以与其它接口电路共用。INT#用于键盘中断输出,默认是高电平。当CH455检测到有效按键时,INT#输出低电平有效的键盘中断;单片机被中断后,对CH455执行读操作,CH455将INT#恢复为高电平,并从SDA输出按键代码,单片机从SDA获得一个字节的数据,即按键代码。单片机与CH455的通讯过程总是分为6个步骤,按单片机的操作方向分成两种类型,一种是写操作,用于输出数据,一种是读操作,用于输入数据。具体过程可以参考例子程序中的说明。写操作包括以下6个步骤:输出启动信号、输出字节1、应答1、输出字节2、应答2、输出停止信号。其中,启动信号和停止信号如上所述,应答1和应答2总是固定为1,输出字节1和输出字节2各自包含8个数据位,即一个字节数据。读操作包括以下6个步骤:输出启动信号、输出字节1、应答1、输入字节2、应答2、输出停止信号。其中,启动信号和停止信号如上所述,应答1和应答2总是固定为1,输出字节1和输入字节2各自包含8个数据位,即一个字节数据。

6、操作命令

  CH455的操作命令分为3组。各命令的启动信号、停止信号、应答1和应答2都相同,区别在于输出字节1和字节2的数据不同以及字节2的传输方向不同。

加载字数据命令:该命令的输出字节1为地址68H、6AH、6CH或者6EH,分别对应于DIG0~DIG3引脚驱动的4个数码管;输出字节2为[DIG_DATA]B,即00H到0FFH之间的值,是8位的字数据。加载字数据命令用于将字数据DIG_DATA写入字节1指定地址的数据寄存器中。例如,命令数据01101100B(即6CH对应DIG2)、01111001B表示将字数据79H写入第1个数据寄存器,使DIG2引脚驱动的数码管将显示E。

读取按键代码命令:该命令的输出字节1为01001111B,即4FH;输入字节2为按键代码。读取按键代码命令用于获得CH455最近检测到的有效按键的按键代码。该命令属于读操作,是唯一的具有数据返回的命令,单片机必须先释放SDA引脚(三态输出禁止或者上拉到高电平),然后CH455从SDA引脚输出按键代码,按键代码的有效数据是位7~位0,其中位6是状态码,位5~位0是扫描码和按键编址。

7、接口时序

  

TSSTA/THSTA/TSSTO/THSTO/TCLOW/TCHIG:最小时间100ns

TSD:最小时间30ns

THD:最小时间10ns

TAA/TDH:最小时间2ns

Rate:最大速率4Mbps

8、原理图接线

9、程序设计

  由于这次只是做个简单的按键检测,所以只用到键盘扫描功能,数码管有需要再做吧。先定义一下系统参数:

// 设置系统参数命令
#define CH455_SCL_SET HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET)
#define CH455_SCL_CLR HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET)
#define CH455_SCL_D_OUT {} // 设置SCL为输出方向,对于双向I/O需切换为输出 #define CH455_SDA_SET HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET)
#define CH455_SDA_CLR HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET)
#define CH455_SDA_IN HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_9) // 读取SDA输入电平 #define CH455_BIT_ENABLE 0x01 // 开启/关闭位
#define CH455_BIT_SLEEP 0x04 // 睡眠控制位
#define CH455_BIT_7SEG 0x08 // 7段控制位
#define CH455_BIT_INTENS1 0x10 // 1级亮度
#define CH455_BIT_INTENS2 0x20 // 2级亮度
#define CH455_BIT_INTENS3 0x30 // 3级亮度
#define CH455_BIT_INTENS4 0x40 // 4级亮度
#define CH455_BIT_INTENS5 0x50 // 5级亮度
#define CH455_BIT_INTENS6 0x60 // 6级亮度
#define CH455_BIT_INTENS7 0x70 // 7级亮度
#define CH455_BIT_INTENS8 0x00 // 8级亮度 #define CH455_SYSOFF 0x0400 // 关闭显示、关闭键盘
#define CH455_SYSON ( CH455_SYSOFF | CH455_BIT_ENABLE ) // 开启显示、键盘
#define CH455_SLEEPOFF CH455_SYSOFF // 关闭睡眠
#define CH455_SLEEPON ( CH455_SYSOFF | CH455_BIT_SLEEP ) // 开启睡眠
#define CH455_7SEG_ON ( CH455_SYSON | CH455_BIT_7SEG ) // 开启七段模式
#define CH455_8SEG_ON ( CH455_SYSON | 0x00 ) // 开启八段模式
#define CH455_SYSON_4 ( CH455_SYSON | CH455_BIT_INTENS4 ) // 开启显示、键盘、4级亮度
#define CH455_SYSON_8 ( CH455_SYSON | CH455_BIT_INTENS8 ) // 开启显示、键盘、8级亮度 // CH455接口定义
#define CH455_I2C_ADDR 0x40 // CH455的地址
#define CH455_I2C_MASK 0x3E // CH455的高字节命令掩码 // 读取按键代码命令
#define CH455_GET_KEY 0x0700 // 获取按键,返回按键代码

define

另外,用的是stm32的HAL库,但是IIC通讯依然用的是IO口模拟IIC的,主要是因为CH455g的器件地址没有找到,其次是HAL库自带的IIC模块不太可靠。

//--------------------------------------------i2c-------------------------------------------
// 设置SDA为输出方向,对于双向I/O需切换为输出
void CH455_SDA_D_OUT()
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); } // 设置SDA为输入方向,对于双向I/O需切换为输入
void CH455_SDA_D_IN()
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); } void CH455_I2c_Start( void ) // 操作起始
{
//DISABLE_KEY_INTERRUPT; //禁止键盘中断,防止开始时被CH455中断而进入中断服务程序中的START CH455_SDA_SET; /*发送起始条件的数据信号*/
CH455_SDA_D_OUT(); /* 设置SDA为输出方向 */
CH455_SCL_SET;
CH455_SCL_D_OUT; /* 设置SCL为输出方向 */
HAL_Delay(10);
CH455_SDA_CLR; /*发送起始信号*/
HAL_Delay(10);
CH455_SCL_CLR; /*钳住I2C总线,准备发送或接收数据 */
} void CH455_I2c_Stop( void ) // 操作结束
{
CH455_SDA_CLR;
CH455_SDA_D_OUT(); /* 设置SDA为输出方向 */
HAL_Delay(10);
CH455_SCL_SET;
HAL_Delay(10);
CH455_SDA_SET; /*发送I2C总线结束信号*/
HAL_Delay(10);
CH455_SDA_D_IN(); /* 设置SDA为输入方向 */
//ENABLE_KEY_INTERRUPT;
} void CH455_I2c_WrByte( uint8_t dat ) //写一个字节数据
{
uint8_t i;
CH455_SDA_D_OUT(); /* 设置SDA为输出方向 */
for( i = 0; i != 8; i++ ) // 输出8位数据
{
if( dat & 0x80 )
{
CH455_SDA_SET;
}
else
{
CH455_SDA_CLR;
}
HAL_Delay(10);
CH455_SCL_SET;
dat <<= 1;
HAL_Delay(10); // 可选延时
CH455_SCL_CLR;
}
CH455_SDA_D_IN(); /* 设置SDA为输入方向 */
CH455_SDA_SET;
HAL_Delay(10);
CH455_SCL_SET; // 接收应答
HAL_Delay(10);
CH455_SCL_CLR;
} uint8_t CH455_I2c_RdByte( void ) //读一个字节数据
{
uint8_t dat,i;
CH455_SDA_SET;
CH455_SDA_D_IN(); /* 设置SDA为输入方向 */
dat = 0;
for( i = 0; i != 8; i++ ) // 输入8位数据
{
HAL_Delay(10); // 可选延时
CH455_SCL_SET;
HAL_Delay(10); // 可选延时
dat <<= 1;
if( CH455_SDA_IN ) dat++; // 输入1位
CH455_SCL_CLR;
}
CH455_SDA_SET;
HAL_Delay(10);
CH455_SCL_SET; // 发出无效应答
HAL_Delay(10);
CH455_SCL_CLR;
return dat;
} void CH455_Write( uint16_t cmd ) //写命令
{
CH455_I2c_Start(); //启动总线
CH455_I2c_WrByte(((uint8_t)(cmd>>7)&CH455_I2C_MASK)|CH455_I2C_ADDR);
CH455_I2c_WrByte((uint8_t)cmd); //发送数据
CH455_I2c_Stop(); //结束总线
} uint8_t CH455_Read( void ) //读取按键
{
uint8_t keycode;
CH455_I2c_Start(); //启动总线
CH455_I2c_WrByte((uint8_t)(CH455_GET_KEY>>7)&CH455_I2C_MASK|0x01|CH455_I2C_ADDR);
keycode=CH455_I2c_RdByte(); //读取数据
CH455_I2c_Stop(); //结束总线
return keycode;
}

IO口模拟IIC

主函数开启中断和键盘:

HAL_ADC_Start_IT(&hadc1);
CH455_Write( CH455_7SEG_ON );// 开启显示和键盘,8段显示方式

写完回调函数,即可打印输出键码:

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle)
{
RX_AD = HAL_ADC_GetValue(&hadc1);
if(RX_AD == 0)
{
RX_CH455 = CH455_Read();
printf("键码:%x\r\n",RX_CH455);
}
}

完了给大伙看看按键打印结果:

需要程序的记得留言打赏哦

STM32与CH455g通信测试(仅键盘)的更多相关文章

  1. STM32 实现 4*4 矩阵键盘扫描(HAL库、标准库 都适用)

    本文实现的代码是基于STM32HAL库的基础上的,不过标准库也可以用,只是调用的库函数不同,逻辑跟配置是一样的,按我这里的逻辑来配置即可. 1.键盘原理图: 原理举例:先把 F0-F7 内部拉高,这样 ...

  2. Tkinter 鼠标键盘事件(二)

    一个Tkinter主要跑在mainloop进程里.Events可能来自多个地方,比如按键,鼠标,或是系统事件. Tkinter提供了丰富的方法来处理这些事件.对于每一个控件Widget,你都可以为其绑 ...

  3. python tkinter教程-事件绑定

    一个Tkinter主要跑在mainloop进程里.Events可能来自多个地方,比如按键,鼠标,或是系统事件. Tkinter提供了丰富的方法来处理这些事件.对于每一个控件Widget,你都可以为其绑 ...

  4. [FreeRTOS入门] 1.CubeMX中FreeRTOS配置参数及理解

    1.有关优先级 1.1 Configuration --> FreeRTOS MAX_PRIORITIES 设置任务优先级的数量:配置应用程序有效的优先级数目.任何数量的任务都可以共享一个优先级 ...

  5. python tkinter中的事件绑定

    一个Tkinter主要跑在mainloop进程里.Events可能来自多个地方,比如按键,鼠标,或是系统事件. Tkinter提供了丰富的方法来处理这些事件.对于每一个控件Widget,你都可以为其绑 ...

  6. 【STM32学习笔记】STM32f407 使用4*4矩阵键盘

    作者:李剀 出处:https://www.cnblogs.com/kevin-nancy/ 欢迎转载,但也请保留上面这段声明.谢谢! 写在前面: 这是本人第一次开始写博客,可能写的不是很好,也请大家谅 ...

  7. ARM开发(3)基于STM32的矩阵键盘控制蜂鸣器

    一 矩阵键盘控制蜂鸣器原理:  1.1 本实验实现8*7矩阵键盘上按键控制蜂鸣器响.  1.2 实验思路:根据电路图原理,找出矩阵键盘行列所对应的引脚,赋予对应的按键值,然后控制蜂鸣器响.  1.3 ...

  8. stm32 hid 键盘描述

    /* USB Standard Device Descriptor */ const uint8_t Joystick_DeviceDescriptor[JOYSTICK_SIZ_DEVICE_DES ...

  9. stm32矩阵键盘扫描数据通过USB发送

                   Keyboard.c #include "keyboard.h"#include "my_usb.h"#include " ...

随机推荐

  1. 高效IO解决方案-Mmap「给你想要的快」

    随着技术的不断进步,计算机的速度越来越快.但是磁盘IO速度往往让欲哭无泪,和内存中的读取速度有着指数级的差距:然而由于互联网的普及,网民数量不断增加,对系统的性能带来了巨大的挑战,系统性能往往是无数技 ...

  2. Angular 之我见

    很久没有写过技术软文了,虽然 Angular 发布已有四年,得到了越来越多人的关注,但是仍然有很多人不分青红皂白的进行诋毁.我打算结合自己的经历从客观的角度说聊一聊我眼中的 Angular. 本人刚做 ...

  3. linux字符串转数字

    方法一: [root@ffcs211 test_dir]# echo "96.56"| awk '{print int($0)}' 输出结果 96 方法二: A="2&q ...

  4. iview table render 进阶(一)

    Qestion: 如何给表格添加hover 事件? step1:  添加 domProps 选项参数 step2:  废话不多说,直接看demo code render: (h, params) =& ...

  5. [BUUOJ记录] [HCTF 2018]WarmUp

    BUUOJ Web的第一题,其实是很有质量的一道题,但是不知道为什么成了Solved最多的题目,也被师傅们笑称是“劝退题”,这道题的原型应该是来自于phpMyadmin的一个文件包含漏洞(CVE-20 ...

  6. Jmeter 断言-检查点

    1. http请求/添加/断言/响应断言 2. 输入一个返回数据里没有的参数 3.果然报错了 断言的作用是用来查看接口文档里是否有自己想要的数据!

  7. Spring Boot 整合Redis 实现缓存

      本文提纲 一.缓存的应用场景 二.更新缓存的策略 三.运行 springboot-mybatis-redis 工程案例 四.springboot-mybatis-redis 工程代码配置详解   ...

  8. [LeetCode]面试题53 - I. 在排序数组中查找数字 I(二分);面试题53 - II. 0~n-1中缺失的数字(二分)

    ##面试题53 - I. 在排序数组中查找数字 I ###题目 统计一个数字在排序数组中出现的次数. 示例 1: 输入: nums = [5,7,7,8,8,10], target = 8 输出: 2 ...

  9. win10家庭版启用远程桌面

    此电脑右键属性->远程设置->允许远程协助连接这台计算机 勾选 下载RDP Wrapper 地址:https://github.com/stascorp/rdpwrap/releases ...

  10. 我的Python自学之路-001 列表的知识

    #_date_:2020/9/11 '''列表和字典是python中用的最多的数据类型 假如要存储一个班级的人名,需要怎么做?有这么几种方法:1.定义很多个变量: name0 = 'wucaho' n ...