打印
[STM32F4]

STM32F407控制TM1638按键数码管显示模块

[复制链接]
1819|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
kxsi|  楼主 | 2021-8-9 13:42 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

TM1638按键数码管显示模块
实物图

原理图



使用特权

评论回复
沙发
kxsi|  楼主 | 2021-8-9 13:43 | 只看该作者
tm1638.c文件

#include "tm1638.h"
#include "delay.h"
//         
                                                          
//        
//共阴数码管显示代码
unsigned char tab[16]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
                           0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};


// **************************************** TM1638 ************************
//发送一个字节
void TM1638_Write(u8        DATA)                        //写字节
{
        unsigned char i;
        SDA_OUT();
        delay_us(2);
        for(i=0;i<8;i++)
        {
                TM1638_CLK=0;
                delay_us(2);
                if(DATA&0X01)
                        OUT_SDA=1;
                else
                        OUT_SDA=0;
                delay_us(2);
                DATA>>=1;
                TM1638_CLK=1;
                delay_us(2);
        }
}

u8 TM1638_Read(void)                                        //读字节
{
        unsigned char i;
        unsigned char temp=0;

        SDA_IN();//SDA设置为输入
        delay_us(2);
        for(i=0;i<8;i++)
        {
                temp>>=1;
                TM1638_CLK=0;
                delay_us(2);
                if(READ_SDA)
                        temp|=0x80;
                TM1638_CLK=1;
                delay_us(2);
        }
        return temp;
}

void Write_COM(unsigned char cmd)                //发送命令字
{
        TM1638_STB=0;
        TM1638_Write(cmd);
        TM1638_STB=1;
}

void Write_DATA(unsigned char add,unsigned char DATA)                //指定地址写入数据
{
        TM1638_STB=0;
        TM1638_Write(0xc0|add); //1100 0000
        TM1638_Write(DATA);
        TM1638_STB=1;
}

u8 Read_key(void)  //读按键
{
        unsigned char c[4],i,key_value=0;
        TM1638_STB=0;
        delay_us(2);
        TM1638_Write(0x42);                  //读键扫数据 命令
        for(i=0;i<4;i++)               
                c[i]=TM1638_Read();
        TM1638_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;  //返回键值  无键值按下返回0x08
               
   // 8键  col:K3  row:KS1~KS8
//  if(c[0]==0x01)  key_value=1;
//        if(c[0]==0x10)  key_value=5;
//        if(c[1]==0x01)  key_value=2;
//        if(c[1]==0x10)  key_value=6;
//        if(c[2]==0x01)  key_value=3;
//        if(c[2]==0x10)  key_value=7;
//        if(c[3]==0x01)  key_value=4;
//        if(c[3]==0x10)  key_value=8;   
//  return (key_value);         // 返回键值
}

//单独控制一个LED函数
//num为需要控制的led序号,flag为0时熄灭,不为0时点亮
void Write_oneLED(unsigned char num,unsigned char flag)        //控制一个LED
{
        if(flag)
                Write_DATA(2*num+1,1);
        else
                Write_DATA(2*num+1,0);
}         

//控制全部LED函数
//LED_flag表示各个LED状态
void Write_allLED(unsigned char 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);
                }
}

void TM1638_Clear(void)  //清除显示
{       
        u8 i;
        Write_COM(0x8f);       //亮度 (0x88-0x8f)8级亮度可调
  Write_COM(0x40);       //自动地址
       
        TM1638_STB=0;                  
        TM1638_Write(0xc0);    //设置起始地址
        for(i=0;i<16;i++)           //传送16个字节的数据
                TM1638_Write(0x00);
        TM1638_STB=1;
}

void NixieShow(void) //数码管显示01234567
{
        u8 i;
        Write_COM(0x8d);  //亮度 (0x88-0x8f)8级亮度可调
        Write_COM(0x44);  //地址固定
        for(i=0;i<8;i++)
                        Write_DATA(i<<1,tab[i]);         //依次显示01234567
}

//num数码管序号    data显示的数字
void NixieShowOne(u8 num,u8 data) //单个数码管显示
{
        Write_COM(0x8d);  //亮度 (0x88-0x8f)8级亮度可调
        Write_COM(0x44);  //地址固定
        Write_DATA(num<<1,tab[data]);         //依次显示01234567
}


void NixieShowNum(u32 data) //数码管显示数字
{
                NixieShowOne(0,data/10000000%10); //单个数码管显示
                NixieShowOne(1,data/1000000%10); //单个数码管显示
                NixieShowOne(2,data/100000%10); //单个数码管显示
                NixieShowOne(3,data/10000%10); //单个数码管显示
                NixieShowOne(4,data/1000%10); //单个数码管显示
                NixieShowOne(5,data/100%10); //单个数码管显示
                NixieShowOne(6,data/10%10); //单个数码管显示
                NixieShowOne(7,data%10); //单个数码管显示
}

//初始化LED
void LED_init(void)
{                       
  GPIO_InitTypeDef  GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);//使能GPIOC时钟

  //GPIOB8,B9初始化设置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化
}

//初始化
void TM1638_init(void)
{                       
  GPIO_InitTypeDef  GPIO_InitStructure;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);//使能GPIOE时钟

  //GPIOB8,B9初始化设置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化
        TM1638_CLK=1;
        OUT_SDA=1;
}


使用特权

评论回复
板凳
kxsi|  楼主 | 2021-8-9 13:44 | 只看该作者
tm1638.h文件

#ifndef __TM1638_H
#define __TM1638_H
#include "sys.h"
                                                  
//        
                                
//共阴数码管显示代码
extern  unsigned char tab[16];
                                                 
                                                 
//DIO输入输出设置
#define SDA_IN()  {GPIOE->MODER&=~(3<<(9*2));GPIOE->MODER|=0<<9*2;}        //PE9输入模式
#define SDA_OUT() {GPIOE->MODER&=~(3<<(9*2));GPIOE->MODER|=1<<9*2;} //PE9输出模式

//IO操作函数         
#define TM1638_CLK    PEout(8) //CLK
#define OUT_SDA       PEout(9) //DIO         
#define READ_SDA      PEin(9)  //输入DIO
#define TM1638_STB    PEout(10)//片选信号STB

#define LED    PCout(4) //LED

//TM1638
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);        //单独控制一个LED函数,num为需要控制的led序号,flag为0时熄灭,不为0时点亮
void Write_allLED(unsigned char LED_flag);                                        //控制全部LED函数,LED_flag表示各个LED状态

void TM1638_Clear(void);  //清除显示
void NixieShow(void); //数码管显示
void NixieShowOne(u8 num,u8 data); //单个数码管显示
void NixieShowNum(u32 data); //数码管显示数字
       
void TM1638_init(void);

void LED_init(void);
#endif


使用特权

评论回复
地板
kxsi|  楼主 | 2021-8-9 13:45 | 只看该作者
第一种:显示数字

main.c主函数

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "tm1638.h"

unsigned char num[8];                //各个数码管显示的值

int main(void)
{
        unsigned char i;
        delay_init(168);
        LED_init();
        LED=1;
       
        TM1638_init();        //初始化TM1638
        NixieShow(); //数码管显示01234567   初始化必须加上       
        TM1638_Clear();  //清除显示       

        while(1)
        {       
                NixieShow(); //数码管显示01234567
                delay_ms(10);               
        }       
}


使用特权

评论回复
5
kxsi|  楼主 | 2021-8-9 13:46 | 只看该作者
实际显示

逻辑分析仪查看时序
0X44固定地址模式
跟着8个按键(地址+数据)
0X8F显示亮度


使用特权

评论回复
6
kxsi|  楼主 | 2021-8-9 13:48 | 只看该作者
第二种:扫描键盘

按下按键,对应位置数码管显示数字并计数,对应位置LED点亮

main.c主函数

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "tm1638.h"

unsigned char num[8];                //各个数码管显示的值

int main(void)
{
        unsigned char i;
        delay_init(168);
        LED_init();
        LED=1;
       
        TM1638_init();        //初始化TM1638
        NixieShow(); //数码管显示01234567   初始化必须加上       
        TM1638_Clear();  //清除显示       

        while(1)
        {       
                i=Read_key();     //读按键值
                if(i<8)
                {
                        num++;
                        while(Read_key()==i);                //等待按键释放
                        if(num>15)
                                        num=0;
                        Write_DATA(i*2,tab[num]); //数码管显示+1
                        Write_allLED(1<<i);  //按键对应LED灯点亮
                }
               
//                NixieShow(); //数码管显示01234567
                delay_ms(10);               
        }       
}


无按键按下时的时序
0X42扫描键盘指令
后面四个字节表示返回键值



使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

45

主题

3310

帖子

2

粉丝