TM1648A 开发
前言
本文介绍了TM1648A 这款led触摸IC相关应用开发
链接:TM1648A规格书
一、寄存器说明
序号 | 寄存器地址 | R/W | 初始值 | 功能说明 | 备注 |
---|---|---|---|---|---|
1 | 0XBD | W | 0X00 | 显示模式设置 | - |
2 | 0XBE | W | 0X00 | 数据读写及地址增加模式设置 | - |
3-16 | 0XC0-0XCD | W | 0X00 | 显示内容设置 | 控制灯光 |
4 | 0XBF | W | 0X00 | 显示开关及亮度设置 | - |
19 | 0XCE | W | 0X00 | 蜂鸣器响声时间设置 | - |
20 | 0xCF | W | 0X00 | 休眠模式设置 | - |
21 | 0XF0 | R | 0X00 | 触摸按键寄存器 | 按键操作 |
二、通信协议
TM1648A 通过I2C协议与其他设备进行通信,其中每次通信支持单字节读出
和多字节写入
,具体格式附上图。
三、通信流程
代码如下:
1.发送数据
void TM1648A_SEND_BYTE(uint8_t data, uint8_t adress)
{
//打开开关
IIC_START();
IIC_SENDBYTE(TM1648A_ADDRESS); //发送设备地址
IIC_WaitAck();
Delay_us(100); //busy
IIC_SENDBYTE(SWITCH_BRIGHT); //发送设备数据地址
IIC_WaitAck();
Delay_us(100); //busy
IIC_SENDBYTE(0x8F); //发送数据 显示打开
IIC_WaitAck();
Delay_us(100); //busy
IIC_STOP();
Delay_us(5);
IIC_START();
IIC_SENDBYTE(TM1648A_ADDRESS); //发送设备地址
IIC_WaitAck();
Delay_us(100); //busy
IIC_SENDBYTE(adress); //发送设备数据地址
IIC_WaitAck();
Delay_us(100); //busy
IIC_SENDBYTE(data); //发送数据
IIC_WaitAck();
Delay_us(100); //busy
IIC_STOP();
Delay_us(5);
}
2.读取数据
uint8_t TM1648A_READ_BYTE()
{
uint8_t data; //存储接收数据
IIC_START();
IIC_SENDBYTE(TM1648A_ADDRESS); //发送设备地址
IIC_Ack();
Delay_us(100); //busy
IIC_SENDBYTE(KRY_TOUCH); //发送设备数据地址
IIC_Ack();
Delay_us(100); //busy
IIC_START();
IIC_SENDBYTE(TM1648A_R_ADDRESS); //发送设备地址
IIC_Ack();
Delay_us(100); //busy
data = IIC_ReadByte(); //读取数据
IIC_NAck();
Delay_us(100); //busy
IIC_STOP();
Delay_us(5);
return data;
}
3.i2c
void IIC_SetSDAOutputMode(void)
{
/* enable the led clock */
rcu_periph_clock_enable(RCU_GPIOB);
systick_config();
/* configure led GPIO port */
gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_0);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
}
void IIC_SetSDAInputMode(void)
{
/* enable the led clock */
rcu_periph_clock_enable(RCU_GPIOB);
systick_config();
/* configure led GPIO port */
gpio_mode_set(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_0);
}
//IIC通信的起始位(开始信号的发送)
void IIC_START(void)
{
//确保引脚为输出模式
IIC_SetSDAOutputMode();
//直接拉高,确保可以正常发送起始信号
SDA_1;
SCL_1;
Delay_us(5);
SDA_0;
Delay_us(5); //用于等待引脚电平稳定;
//发送起始信号后, 为了方便直接发送器件地址,直接把SCL线拉低
SCL_0;
Delay_us(5);
}
void IIC_STOP(void)
{
//确保引脚为输出模式
IIC_SetSDAOutputMode();
//全部拉低,确保后续能全部拉高
SDA_0;
SCL_0;
Delay_us(5);
//SCL拉高
SCL_1;
Delay_us(5);
//SDA从低电平切换为高电平:以发送停止位
SDA_1;
Delay_us(5);
}
//IIC发送:数据或者地址或者命令
void IIC_SENDBYTE(uint8_t data)
{
uint8_t i = 0;
//确保引脚为输出模式
IIC_SetSDAOutputMode();
//两根线全部拉低,方便数据的发送(SCL为低电平时,SDA才可以更改电平位)
SDA_0;
SCL_0;
Delay_us(5);
for(i=0; i<8; i++)
{
//判断数据的的最高位是否为1(MSB最高位先发送)MSB:高位先出
if(data & 0x80)
{
SDA_1;
}
else
{
SDA_0;
}
Delay_us(5);
//把SCL拉高以便通知从器件读取SDA引脚数据
SCL_1;
Delay_us(5);
data<<= 1;
//为了方便发送第二个位,直接把SCL拉低,方便数据的发送(SCL为低电平时,SDA才可以更改电平位)
SCL_0;
Delay_us(5);
}
}
//IIC主机接收从机应答
int IIC_WaitAck(void)
{
int ack = 0;
//确保引脚为输入模式
IIC_SetSDAInputMode();
//允许从机应答:SCL线需要拉低
SCL_0;
Delay_us(5);
//一旦从机应答,即拉高SCL,锁定SDA的电平以稳定读取SDA的电平位
SCL_1;
Delay_us(5);
//读取SDA线的电平位
if(IIC_SDA_READ == 0) //从机
{
ack = 0; //从机应答
}
else
{
ack = 1;
}
//为了方便后续数据的发送,直接把SCL拉低(SCL为低电平时,SDA才可以更改电平位)
SCL_0;
Delay_us(5);
return ack;
}
//主机读取从机1个字节数据(应答是1bit)
uint8_t IIC_ReadByte(void)
{
uint8_t i = 0, data = 0;
//确保引脚为输入模式
IIC_SetSDAInputMode();
for(i=0; i<8; i++)
{
//由于时钟线是由主机控制的,所以得要由主机把SCL拉高稳定从机发送的数据
SCL_1;
Delay_us(5);
data <<= 1; //先左移保存之前获取到的1bit数据,在或赋值操作
if(IIC_SDA_READ == 1) //读取SDA引脚数据
{
data |= 0x01; //0000 0000 |= 0000 0001
}
//由于时钟线是由主机控制的,所以得要由主机把SCL拉低通知从机发送数据
SCL_0; //允许从机更改SDA线的电平位
Delay_us(5);
}
return data;
}
void IIC_Ack(void)
{
IIC_SetSDAOutputMode();
//数据线一直保持为低电平,时钟线出现上升沿即为应答
//CW2217_SDA_PIN_SET_OUT;
//Delay_xus(1);
SCL_0; //将时钟线拉低允许数据改变
SDA_0; //数据线拉低,保持为低电平
Delay_us(5);
SCL_1; //时钟线拉高,产生上升沿
Delay_us(5);
//应答完成后,将时钟线拉低,允许数据修改
SCL_0; //时钟线拉低
SDA_1; //数据线拉高,允许数据修改
Delay_us(5);
}
void IIC_NAck(void)
{
IIC_SetSDAOutputMode();
//数据线一直保持为高电平,时钟线出现上升沿即为非应答
//CW2217_SDA_PIN_SET_OUT;
//Delay_xus(1);
SCL_0; //将时钟线拉低允许数据改变
SDA_1; //数据线拉高,保持为高电平
Delay_us(5);
SCL_1; //时钟线拉高,产生上升沿
Delay_us(5);
//应答完成后,将时钟线拉低,允许数据修改
SCL_0; //时钟线拉低
SDA_1; //数据线拉高,允许数据修改
Delay_us(1);
}
四、按键控制
TM1648A中的寄存器0XF0用来用作I2C读取按键触摸数据的寄存器。Bit7-Bit0用于指示相应的触摸按键Key8-Key1是否被触摸。
(注:若所读寄存器不为0XF0,则返回为0XFF)
寄存器:0XF0
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
R/W | R | R | R | R | R | R | R | R |
Bit | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Bit7-0 按键读取位
0:未按下
1:按下
五、led控制
以驱动共阴LED为例:
寄存器CH0(GRID1)
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Name | SEG8 | SEG7 | SEG6 | SEG5 | SEG4 | SEG3 | SEG2 | SEG1 |
R/W | W | W | W | W | W | W | W | W |
Bit | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Bit7-0 LED写入位
0:不亮
1:点亮
注:无论是驱动共阴还是共阳led,SEG引脚只能接led阳极,GRID只能接led阴极。
总结
TM1648A这款芯片已开发,原理简单,能适应很多场景,主要技术实现包括I2C通信和寄存器的读写。