本次实验用到的TMI1638是淘宝优信电子上面购买的,可实现8个LED8个数码管8个按键
首先创建TM1638.H和TM1638.C文件、需要注意的是引脚定义,SYS,H和delay可直接用正点原子的代码,代码如下:
TM1638.H
#ifndef __TM1638_H
#define __TM1638_H
#define DATA_COMMAND 0X40
#define DISP_COMMAND 0x80
#define ADDR_COMMAND 0XC0
//TM1638模块引脚定义
#define DIO_SET() GPIO_SetBits(GPIOB, GPIO_Pin_7)
#define DIO_RESET() GPIO_ResetBits(GPIOB, GPIO_Pin_7)
#define CLK_SET() GPIO_SetBits(GPIOB, GPIO_Pin_8)
#define CLK_RESET() GPIO_ResetBits(GPIOB, GPIO_Pin_8)
#define STB_SET() GPIO_SetBits(GPIOB, GPIO_Pin_9)
#define STB_RESET() GPIO_ResetBits(GPIOB, GPIO_Pin_9)
#define DIO_IN() GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7)
void TM1638_Write(unsigned char DATA);
unsigned char TM1638_Read(void);
void Write_COM(unsigned char cmd);
unsigned char Read_key(void);
void Write_DATA(unsigned char add,unsigned char DATA);
void Write_oneLED(unsigned char num,unsigned char flag);
void Write_allLED(unsigned char LED_flag);
void init_TM1638(void);
void TM1638_GPIO_Init(void);
#endif
TM1638.C
#include "tm1638.h"
#include "stm32f10x.h"
void TM1638_Write(unsigned char DATA) //写数据函数
{
unsigned char i;
for(i=0;i<8;i++)
{
CLK_RESET();//CLK=0;
if(DATA&0X01)
DIO_SET();//DIO=1;
else
DIO_RESET();//DIO=0;
DATA>>=1;
CLK_SET();//CLK=1;
}
}
unsigned char TM1638_Read(void) //读数据函数
{
unsigned char i;
unsigned char temp=0;
DIO_SET();//DIO=1; //设置为输入
for(i=0;i<8;i++)
{
temp>>=1;
CLK_RESET();//CLK=0;
if(DIO_IN())//if(DIO)
temp|=0x80;
CLK_SET();//CLK=1;
}
return temp;
}
void Write_COM(unsigned char cmd) //发送命令字
{
STB_RESET();//STB=0;
TM1638_Write(cmd);
STB_SET();//STB=1;
}
unsigned char Read_key(void)
{
unsigned char c[4],i,key_value=0;
STB_RESET();//STB=0;
TM1638_Write(0x42); //读键扫数据 命令
for(i=0;i<4;i++)
c[i]=TM1638_Read();
STB_SET();//STB=1; //4个字节数据合成一个字节
for(i=0;i<4;i++)
key_value|=c[i]<<i;
for(i=0;i<8;i++)
if((0x01<<i)==key_value)
break;
return i;
}
void Write_DATA(unsigned char add,unsigned char DATA) //指定地址写入数据
{
Write_COM(0x44);
STB_RESET();//STB=0;
TM1638_Write(0xc0|add);
TM1638_Write(DATA);
STB_SET();//STB=1;
}
void Write_oneLED(unsigned char num,unsigned char flag) //单独控制一个LED函数,num为需要控制的led序号,flag为0时熄灭,不为0时点亮
{
if(flag)
Write_DATA(2*num+1,1);
else
Write_DATA(2*num+1,0);
}
void Write_allLED(unsigned char LED_flag) //控制全部LED函数,LED_flag表示各个LED状态
{
unsigned char i;
for(i=0;i<8;i++)
{
if(LED_flag&(1<<i))
//Write_DATA(2*i+1,3);
Write_DATA(2*i+1,1);
else
Write_DATA(2*i+1,0);
}
}
//TM1638初始化函数
void init_TM1638(void)
{
unsigned char i;
Write_COM(0x8b); //亮度 (0x88-0x8f)8级亮度可调
Write_COM(0x40); //采用地址自动加1
STB_RESET();//STB=0; //
TM1638_Write(0xc0); //设置起始地址
for(i=0;i<16;i++) //传送16个字节的数据
TM1638_Write(0x00);
STB_SET();//STB=1;
}
void TM1638_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //GPIO参数设置结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //APB2外设时钟使能:GPIOC
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;//选定引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //工作方式:推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //最大速度50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化引脚
}
MAIN.C
#include "sys.h"
#include "tm1638.h"
//共阴数码管显示代码
unsigned char tab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
unsigned char num[8]; //各个数码管显示的值
int main(void)
{
unsigned char i;
TM1638_GPIO_Init();
init_TM1638();
for(i=0;i<8;i++)
Write_DATA(i<<1,tab[0]); //初始化寄存器
while(1)
{
i=Read_key(); //读按键值
if(i<8)
{
num[i]++;
while(Read_key()==i); //等待按键释放
if(num[i]>15)
num[i]=0;
Write_DATA(i*2,tab[num[i]]);
Write_allLED(1<<i);
}
}
}