首页 LMVE论坛 资讯 插画 时光机 我的社区 用户 搜索

[HAL库]TM1638芯片驱动详解

无闻风
发表于 2019-10-10 22:34:08
0
123

数据手册: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

最后修改 2019-10-11 10:42:10
0
123
用户评论
一起折腾