数据手册:TM1638芯片详细手册.pdf
TM1638芯片同时支持LED控制与矩阵键盘扫描,数据通过仅3根线传输
26_DIO 数据I/O(数据低位开始)
27_CLK 时钟I(上升沿有效)
28_STB 片选I ( 在上升或下降沿初始化串行接口,随后等待接收指令。 STB 为低后的第一个字节作为指令)
以这3个引脚为例配置好GPIO
/******************************************************************************/
//引脚控制定义
#define DIO_0 HAL_GPIO_WritePin(TM1638_DIO_GPIO_Port,TM1638_DIO_Pin,0)
#define DIO_1 HAL_GPIO_WritePin(TM1638_DIO_GPIO_Port,TM1638_DIO_Pin,1)
#define CLK_0 HAL_GPIO_WritePin(TM1638_DIOA5_GPIO_Port,TM1638_DIOA5_Pin ,0)
#define CLK_1 HAL_GPIO_WritePin(TM1638_DIOA5_GPIO_Port,TM1638_DIOA5_Pin ,1)
#define STB_0 HAL_GPIO_WritePin(TM1638_DIOA7_GPIO_Port,TM1638_DIOA7_Pin,0)
#define STB_1 HAL_GPIO_WritePin(TM1638_DIOA7_GPIO_Port,TM1638_DIOA7_Pin,1)
/******************************************************************************/
char dis_buff[8]={0x39,0x38,0x3F,0x6D,0x79,0,0,0}; //显存 8个字节的显存-_-
char num[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};//0-f字膜
void DIO_IN_OR_OUT(char a) //设置DIO输入或者输出 a=0时输入,a=1时输出
{
GPIO_InitTypeDef GPIO_InitStruct; //引脚设置的结构体 参考HAL库手册
if(a==0)
{
GPIO_InitStruct.Pin = TM1638_DIO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;//设为输入
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(TM1638_DIO_GPIO_Port, &GPIO_InitStruct);
}
if(a==1)
{
GPIO_InitStruct.Pin = TM1638_DIO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;//设为输出
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(TM1638_DIO_GPIO_Port, &GPIO_InitStruct);
}
}
void TM1638_Write(char data) //向芯片写入数据
{
char a,ddata; //缓存。。
ddata=data; //当时不知道发什么神经要这样写 问题不大
DIO_IN_OR_OUT(1); //把DIO设为输出
for(a=0;a<8;a++) //发送8位数据
{
CLK_0; //拉低时钟线
//HAL_Delay(1);
if(ddata&0x01) //最低位先开
{
DIO_1;
}else
{
DIO_0;
}
CLK_1; //1个位数据准备好后时钟拉高发送数据
//HAL_Delay(1);
ddata>>=1; //数据向右移动
}
}
char TM1638_Read() //从芯片读取数据
{
char a,data=0; //缓存
DIO_IN_OR_OUT(0); //将引脚设为输入
for(a=0;a<8;a++) //读取8个数据
{
data>>=1; //先位移数据,防止最后一位数据丢失
CLK_0; //拉低时钟
//HAL_Delay(1);
if(HAL_GPIO_ReadPin(TM1638_DIO_GPIO_Port,TM1638_DIO_Pin)) //直接读取DIO引脚状态
{
data|=0x80; //因为是从最低位开始读所以把数据放在最高位,一位一位的推到最低位
}
CLK_1;
//HAL_Delay(1);
}
return data; //返回最后数据
}
void TM1638_COM(char com) //发送命令(参考下面图1)
{
STB_0;
TM1638_Write(com);
STB_1;
}
void Write_DATA(unsigned char add,unsigned char DATA) //向芯片某个地址发送数据(参考图2)
{
STB_0;
TM1638_Write(0xc0|add);
TM1638_Write(DATA);
STB_1;
}
char TM1638_Read_Key() //读取按键键值
{
char key_buff[4];
char a,key_value=0;//键值buff
STB_0;
TM1638_Write(0x42);//根据数据手册先发送0x42
for(a=0;a<4;a++) //后连续读4个数据
{
key_buff[a]=TM1638_Read();
}
if((key_buff[0]==0)&(key_buff[1]==0)&(key_buff[2]==0)&(key_buff[3]==0))
{
return 16; //如果4个数据都是0说明没按键被按下(因为我只设计了16个按键键值是0-15,所以16是不存在的按键作为nothing的依据)
}
for(a=0;a<4;a++) //这里是矩阵键盘的算法
{
if(a==0)
{
if(key_buff[a]==2)
{
key_value=0x07;
}
if(key_buff[a]==4)
{
key_value=0x01;
}
if(key_buff[a]==32)
{
key_value=0x08;
}
if(key_buff[a]==64)
{
key_value=0x02;
}
}
if(a==1)
{
if(key_buff[a]==2)
{
key_value=0x09;
}
if(key_buff[a]==4)
{
key_value=0x03;
}
if(key_buff[a]==32)
{
key_value=0x0c;
}
if(key_buff[a]==64)
{
key_value=0x0a;
}
}
if(a==2)
{
if(key_buff[a]==2)
{
key_value=0x0e;
}
if(key_buff[a]==4)
{
key_value=0x04;
}
if(key_buff[a]==32)
{
key_value=0x00;
}
if(key_buff[a]==64)
{
key_value=0x05;
}
}
if(a==3)
{
if(key_buff[a]==2)
{
key_value=0x0f;
}
if(key_buff[a]==4)
{
key_value=0x06;
}
if(key_buff[a]==32)
{
key_value=0x0d;
}
if(key_buff[a]==64)
{
key_value=0x0b;
}
}
}
return key_value; //返回键值
}
void Display() //显示输出(需要循环调用)参考图3
{
char a;
TM1638_COM(0x44); //采用固定地址模式
for(a=0;a<8;a++)
{
Write_DATA(a*2,dis_buff[a]);//因为地址在双数位置所以要*2 参考图4
}
TM1638_COM(0x8f); //设置亮度
}
/*****************************/
//调用
void main()
{
char key_v;//按键键值缓存
while(1)
{
//修改dis_buff[8]里的数据就可以控制显示的内容
key_v=TM1638_Read_Key();//读取按键的键值
if(key_v!=16) //判断有按键被按下
{
dis_buff[0]=num[key_v];//把键值显示在数码管第一位(通过num数组转成字膜)
}
Display(); //显示出来
}
}
图1
图2
图3
图4