#申请原创# @21小跑堂
随着集成电路的快速发展,LED驱动芯片的功能也随之丰富,很多在驱动LED的同时增加了按键检测的功能,支持矩阵式的按键扫描;使用这类的LED驱动在驱动LED的同时,又提供了按键功能,尽最大程度上节省了MCU所占用的软件、硬件等资源。 本篇将主要实现带有按键功能的LED驱动模块的显示及按键检测的功能: 1、数码管显示驱动之AiP650 2、数码管显示驱动之TM1638
1、数码管显示驱动之AiP650 AiP650是无锡中微爱芯推出的一款带有键盘扫描电路接口的LED驱动控制专用芯片。最多可驱动4位8段的共阴极数码管,最大支持7*4个按键;芯片内置了上电复位电路和时钟振荡电路,通过高速两线串行通讯接口进行控制;芯片工作在3V~5.5V之间,提供不小于25mA的段驱动电流和不小于150mA的字驱动电路,满足了市场上决大多数的数码管驱动能力。由于在淘宝上没有买到带按键检测的AiP650模组,所以就自己画了一个块来调试验证。 1.1、数码管显示驱动之AiP650原理图设计 参考AiP650数据手册上的应用线路图进行绘制,使用立创EDA进行设计,原理图如下所示:
1.2、数码管显示驱动之AiP650 PCB设计2D图
1.3、数码管显示驱动之AiP650焊接调试 根据AiP650数据手册上应用线路图的设计,在R1~R4起初都是选用的2K的电路,但在实际调试程序的时候,矩阵按键的扫描结果会出现异常,同一个按键会出现不同按键值的问题,在咨询了原厂以及把板子寄给他们调试都没法确认问题出在哪里,因为完全是参考数据手册来设计的;在后来的调试、尝试下不断的去修改R1~R4的阻值,加大阻值会有明显的改善效果,最后将R1~R4的阻值定在了4.7K。
1.4、数码管显示驱动之AiP650驱动程序 sI2C_TypeDef sI2C_AiP650 =
{
RCC_AHBENR_GPIOB, GPIOB, GPIO_Pin_10,
RCC_AHBENR_GPIOB, GPIOB, GPIO_Pin_11,
500
};
uint8_t AiP650_GetKey(sI2C_TypeDef *sI2C)
{
uint8_t KeyValue = 0;
sI2C_GenerateStart(sI2C);
sI2C_WriteByte(sI2C, 0x4F);
if(sI2C_GetACK(sI2C))
{
sI2C_GenerateStop(sI2C); return 0x00;
}
KeyValue = sI2C_ReadByte(sI2C);
sI2C_PutACK(sI2C, 1);
sI2C_GenerateStop(sI2C);
return KeyValue;
}
void AiP650_WriteCMD(sI2C_TypeDef *sI2C, uint16_t Command)
{
sI2C_GenerateStart(sI2C);
sI2C_WriteByte(sI2C, (Command >> 8) & 0xFF);
if(sI2C_GetACK(sI2C))
{
sI2C_GenerateStop(sI2C); return;
}
sI2C_WriteByte(sI2C, (Command >> 0) & 0xFF);
if(sI2C_GetACK(sI2C))
{
sI2C_GenerateStop(sI2C); return;
}
sI2C_GenerateStop(sI2C);
}
void AiP650_Display(char *str)
{
uint8_t i = 0, j = 0, Data[4];
memset(Data, 0, sizeof(Data));
for(i = 0; i < 4; i++)
{
for(j = 0; j < 38; j++)
{
if(DIGITRON_TABLE[j].ch == str[i])
{
Data[i] = DIGITRON_TABLE[j].Data;
}
}
}
AiP650_WriteCMD(&sI2C_AiP650, AiP650_DIG0 | Data[0]);
AiP650_WriteCMD(&sI2C_AiP650, AiP650_DIG1 | Data[1]);
AiP650_WriteCMD(&sI2C_AiP650, AiP650_DIG2 | Data[2]);
AiP650_WriteCMD(&sI2C_AiP650, AiP650_DIG3 | Data[3]);
}
void AiP650_DisplayNumber(uint16_t Value)
{
char Number[10];
memset(Number, 0, sizeof(Number));
sprintf(Number, "%04d", Value);
AiP650_Display(Number);
}
void AiP650_Init(void)
{
/* 初始化模拟I2C引脚 */
sI2C_Init(&sI2C_AiP650);
/* AiP650芯片配置 */
AiP650_WriteCMD(&sI2C_AiP650, AiP650_SYSON_7_8SEG_ON);
/* 在LED数码管上显示内容 */
AiP650_Display("----");
}
void AiP650_Handler(void)
{
static uint8_t OldKeyValue = 0;
uint8_t KeyTable[][4] =
{
{0x74, 0x75, 0x76, 0x77},
{0x6C, 0x6D, 0x6E, 0x6F},
{0x64, 0x65, 0x66, 0x67},
{0x5C, 0x5D, 0x5E, 0x5F},
{0x54, 0x55, 0x56, 0x57},
{0x4C, 0x4D, 0x4E, 0x4F},
{0x44, 0x45, 0x46, 0x47},
};
uint8_t KeyValue = AiP650_GetKey(&sI2C_AiP650);
if(KeyValue != OldKeyValue)
{
OldKeyValue = KeyValue;
for(uint8_t i = 0; i < 4; i++)
{
for(uint8_t j = 0; j < 7; j++)
{
if(KeyValue == KeyTable[j][i])
{
AiP650_DisplayNumber(i * 7 + j + 1);
printf("\r\nSW%02d : 0x%02x", i * 7 + j + 1, KeyValue);
}
}
}
}
}
void HMI_Init(void)
{
AiP650_Init();
TASK_Append(TASK_ID_HMI, HMI_Handler, 10);
}
void HMI_Handler(void)
{
AiP650_Handler();
}
1.5、数码管显示驱动之AiP650运行演示
2、数码管显示驱动之TM1638 TM1638是深圳天微电子推出的一款带按键扫描接口的LED(发光二极管显示器)驱动控制专用IC。最多可驱动8位10段的数码管(共阳极、共阴极都支持),最大支持8*3个按键;芯片内置了上电复位电路和RC振荡电路;通过3线串行通讯接口进行控制;在数据手册上提供典型的带矩阵按键扫描的共阳极和共阴极的应用硬件电路图。
2.1、数码管显示驱动之TM1638驱动程序 #define TM1638_STB_H() GPIO_WriteBit(GPIOB, GPIO_Pin_0, Bit_SET)
#define TM1638_STB_L() GPIO_WriteBit(GPIOB, GPIO_Pin_0, Bit_RESET)
#define TM1638_CLK_H() GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_SET)
#define TM1638_CLK_L() GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_RESET)
#define TM1638_DIO_H() GPIO_WriteBit(GPIOB, GPIO_Pin_2, Bit_SET)
#define TM1638_DIO_L() GPIO_WriteBit(GPIOB, GPIO_Pin_2, Bit_RESET)
#define TM1638_DIO_GET() GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_2)
uint8_t TM1638_RAM[16];
void TM1638_WriteCMD(uint8_t Command)
{
TM1638_STB_L();
for(uint8_t i = 0; i < 8; i++)
{
TM1638_CLK_L();
if(Command & (0x01 << i)) TM1638_DIO_H();
else TM1638_DIO_L();
TM1638_CLK_H();
}
TM1638_STB_H();
}
void TM1638_WriteRAM(uint8_t Address, uint8_t Data)
{
TM1638_STB_L();
for(uint8_t i = 0; i < 8; i++)
{
TM1638_CLK_L();
if(Address & (0x01 << i)) TM1638_DIO_H();
else TM1638_DIO_L();
TM1638_CLK_H();
}
for(uint8_t i = 0; i < 8; i++)
{
TM1638_CLK_L();
if(Data & (0x01 << i)) TM1638_DIO_H();
else TM1638_DIO_L();
TM1638_CLK_H();
}
TM1638_STB_H();
}
void TM1638_Read(uint8_t Command, uint8_t *Buffer)
{
GPIO_InitTypeDef GPIO_InitStructure;
uint8_t Data = 0;
TM1638_STB_L();
for(uint8_t i = 0; i < 8; i++)
{
TM1638_CLK_L();
if(Command & (0x01 << i)) TM1638_DIO_H();
else TM1638_DIO_L();
TM1638_CLK_H();
}
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
for(uint8_t j = 0; j < 4; j++)
{
Data = 0;
for(uint8_t i = 0; i < 8; i++)
{
TM1638_CLK_L();
Data >>= 1;
if(TM1638_DIO_GET() != Bit_RESET)
{
Data |= 0x80;
}
TM1638_CLK_H();
}
Buffer[j] = Data;
}
TM1638_STB_H();
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
TM1638_DIO_H();
}
void TM1638_RAM_Refresh(void)
{
TM1638_WriteCMD(0x88);
TM1638_WriteCMD(0x40);
for(uint8_t i = 0; i < 16; i++)
{
TM1638_WriteRAM(0xC0 + i, TM1638_RAM[i]);
}
}
void TM1638_DisplayChar(uint8_t Index, char ch, uint8_t Update)
{
uint8_t Data = 0x00;
if(Index > 8) return;
for(uint8_t i = 0; i < 38; i++)
{
if(DIGITRON_TABLE[i].ch == ch)
{
Data = DIGITRON_TABLE[i].Data;
}
}
for(uint8_t i = 0; i < 8; i++)
{
if(Data & (0x01 << i))
{
TM1638_RAM[i*2] |= (0x01 << Index);
}
else
{
TM1638_RAM[i*2] &= ~(0x01 << Index);
}
}
if(Update) TM1638_RAM_Refresh();
}
void TM1638_DisplayString(char *str)
{
uint8_t Index = 8;
while(*str != '\0')
{
if(Index == 0) break;
TM1638_DisplayChar(--Index, *str++, 0);
}
TM1638_RAM_Refresh();
}
void TM1638_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
memset(TM1638_RAM, 0, sizeof(TM1638_RAM));
RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOB, ENABLE);
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_WriteBit(GPIOB, GPIO_Pin_0, Bit_SET);
GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_SET);
GPIO_WriteBit(GPIOB, GPIO_Pin_2, Bit_SET);
TM1638_RAM_Refresh();
TM1638_DisplayString("--------");
}
void TM1638_Handler(void)
{
uint8_t Buffer[4] = {0, 0, 0, 0};
uint8_t String[10];
TM1638_Read(0x42, Buffer);
if((Buffer[0] != 0) || (Buffer[1] != 0) || (Buffer[2] != 0) || (Buffer[3] != 0))
{
printf("\r\n");
if(Buffer[0] & 0x02) printf("S09");
if(Buffer[0] & 0x20) printf("S10");
if(Buffer[0] & 0x04) printf("S01");
if(Buffer[0] & 0x40) printf("S02");
if(Buffer[1] & 0x02) printf("S11");
if(Buffer[1] & 0x20) printf("S12");
if(Buffer[1] & 0x04) printf("S03");
if(Buffer[1] & 0x40) printf("S04");
if(Buffer[2] & 0x02) printf("S13");
if(Buffer[2] & 0x20) printf("S14");
if(Buffer[2] & 0x04) printf("S05");
if(Buffer[2] & 0x40) printf("S06");
if(Buffer[3] & 0x02) printf("S15");
if(Buffer[3] & 0x20) printf("S16");
if(Buffer[3] & 0x04) printf("S07");
if(Buffer[3] & 0x40) printf("S08");
memset(String, 0, sizeof(String));
sprintf((char *)String, "%02x%02x%02x%02x", Buffer[0], Buffer[1], Buffer[2], Buffer[3]);
TM1638_DisplayString((char *)String);
}
}
void HMI_Init(void)
{
TM1638_Init();
TASK_Append(TASK_ID_HMI, HMI_Handler, 200);
}
void HMI_Handler(void)
{
TM1638_Handler();
}
2.2、数码管显示驱动之TM1638运行演示
附件:
|