STM32硬件SPI控制TM1638 按键数码管LED显示模块

时间:2024-03-19 09:25:26

STM32硬件SPI控制TM1638按键数码管LED显示模块

 

从淘宝买来的,TM1638专门是控制LED的,LED组合起来就可以变成数码管,还有按键,这个我就没管了,不想管了,发这个帖子只是为了记录下经验,待以后会过头来看的时候,可以一遍就知道,所以尽量写得详细点。
   手头上的项目用的是共阳极,而我买的是共阴极的,而且例程给的是STM32模拟IO实现的。

太浪费资源了,想尽办法折腾了1整体,终于搞定了SPI硬件实现的方式。写点东西给大家分享下,免得走弯路。本次重点介绍SPI硬件配置方面。

先来个照片,是共阴极的

 STM32硬件SPI控制TM1638 按键数码管LED显示模块

原理图

STM32硬件SPI控制TM1638 按键数码管LED显示模块 

废话不多说了,开始贴程序。

3.3V供电;

STM32F103c8t6;

SPI1;

SPI_Direction_1Line_Tx;

完整程序如下:

//TM1638.C文件

#ifdef   USE_TM1638_SPI

 

 

#defineTM1638_SPIx                        SPI1

#defineTM1638_SPI_APBxClock_FUN          RCC_APB2PeriphClockCmd

#defineTM1638_SPI_CLK                    RCC_APB2Periph_SPI1

#defineTM1638_SPI_GPIO_APBxClock_FUN     RCC_APB2PeriphClockCmd

#defineTM1638_SPI_GPIO_CLK               RCC_APB2Periph_GPIOA 

 

 

 

#defineTM1638_SPI_SCK_PORT               GPIOA 

#defineTM1638_SPI_SCK_PIN                GPIO_Pin_5

#defineTM1638_SPI_SCK_Low()            GPIO_ResetBits(TM1638_SPI_SCK_PORT, TM1638_SPI_SCK_PIN)

#defineTM1638_SPI_SCK_High()           GPIO_SetBits(TM1638_SPI_SCK_PORT, TM1638_SPI_SCK_PIN)

 

  

#defineTM1638_SPI_MISO_PORT               GPIOA

#defineTM1638_SPI_MISO_PIN               GPIO_Pin_6

 

#defineTM1638_SPI_MOSI_PORT               GPIOA

#defineTM1638_SPI_MOSI_PIN               GPIO_Pin_7

#defineTM1638_SPI_MOSI_Low()            GPIO_ResetBits(TM1638_SPI_MOSI_PORT, TM1638_SPI_MOSI_PIN)

#defineTM1638_SPI_MOSI_High()           GPIO_SetBits(TM1638_SPI_MOSI_PORT, TM1638_SPI_MOSI_PIN)

 

 

#defineTM1638_SPI_CS_CLK                 RCC_APB2Periph_GPIOA   

#defineTM1638_SPI_CS_PORT                 GPIOA  

#defineTM1638_SPI_CS_PIN                 GPIO_Pin_3

#defineTM1638_SPI_CS_ENABLE()            GPIO_ResetBits(TM1638_SPI_CS_PORT, TM1638_SPI_CS_PIN)

#defineTM1638_SPI_CS_DISABLE()           GPIO_SetBits(TM1638_SPI_CS_PORT, TM1638_SPI_CS_PIN)

 

#defineTM1638_CE_CLK                     RCC_APB2Periph_GPIOA   

#defineTM1638_CE_PORT                     GPIOA

#defineTM1638_CE_PIN                     GPIO_Pin_3

#defineTM1638_CE_LOW()                   GPIO_ResetBits(TM1638_CE_PORT, TM1638_CE_PIN)

#defineTM1638_CE_HIGH()                  GPIO_SetBits(TM1638_CE_PORT, TM1638_CE_PIN)

 

#defineTM1638_IRQ_CLK                    RCC_APB2Periph_GPIOA   

#defineTM1638_IRQ_PORT                    GPIOA

#defineTM1638_IRQ_PIN                     GPIO_Pin_2

#defineTM1638_IRQ_PIN_READ()             GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2)

 

 

 

 

voidTM1638_GPIO_init(void)

 

{  

    GPIO_InitTypeDef GPIO_InitStructure;

       SPI_InitTypeDef  SPI_InitStructure;

 

       TM1638_SPI_APBxClock_FUN(TM1638_SPI_CLK,ENABLE); 

      TM1638_SPI_GPIO_APBxClock_FUN(RCC_APB2Periph_GPIOA,ENABLE);    

 

    GPIO_InitStructure.GPIO_Pin =GPIO_Pin_5|GPIO_Pin_7|GPIO_Pin_6;               //PB12上拉防止W25X的干扰

    GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_PP;        //推挽输出

    GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;

    GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化指定IO

 

   

    GPIO_InitStructure.GPIO_Pin= GPIO_Pin_4|GPIO_Pin_3;              //PB12上拉防止W25X的干扰

    GPIO_InitStructure.GPIO_Mode= GPIO_Mode_Out_PP;       //推挽输出

    GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;

    GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化指定IO

 

       TM1638_SPI_CS_DISABLE();            //SPI片选取消                   

  

    SPI_Cmd(TM1638_SPIx, DISABLE); // SPI外设不使能

  

    SPI_InitStructure.SPI_Direction =  SPI_Direction_1Line_Tx;  //SPI设置为双线双向全双工

    SPI_InitStructure.SPI_Mode =SPI_Mode_Master;      //SPI主机

       SPI_InitStructure.SPI_DataSize =SPI_DataSize_8b;      //发送接收8位帧结构

    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;     //时钟悬空低

    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;   //数据捕获于第1个时钟沿

    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;      //NSS信号由软件控制

    SPI_InitStructure.SPI_BaudRatePrescaler =SPI_BaudRatePrescaler_4;        //定义波特率预分频的值:波特率预分频值为16

    SPI_InitStructure.SPI_FirstBit =SPI_FirstBit_LSB;//SPI_FirstBit_MSB; //数据传输从MSB位开始

    SPI_InitStructure.SPI_CRCPolynomial = 7;   //CRC值计算的多项式

    SPI_Init(TM1638_SPIx,&SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器

 

    SPI_Cmd(TM1638_SPIx, ENABLE); //使能SPI外设

             

    //TM1638_CE_HIGH() ;

    TM1638_SPI_CS_ENABLE();        //SPI片选取消                   

}

 

void TM1638_SPIx_SetSpeed(SPI_TypeDef*SPIx, uint8_t SPI_BaudRatePrescaler)

{

  /* Check the parameters */

  assert_param(IS_SPI_ALL_PERIPH(SPIx));

 assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));

    SPIx->CR1&=0XFFC7;

    SPIx->CR1|=SPI_BaudRatePrescaler;  //设置SPI2速度

    SPI_Cmd(SPIx,ENABLE);

}

uint8_tTM1638_SPIx_ReadWriteByte(SPI_TypeDef* SPIx, uint8_t TxData)

 

{      

    SPI_I2S_SendData(SPIx, TxData); //通过外设SPIx发送一个数据

      while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_BSY) == RESET);//等待发送完成

}

 

 

void  TM1638_Write_Reg(uint8_t value)

{

  TM1638_SPI_CS_ENABLE();                 //使能SPI传输

 

 TM1638_SPIx_ReadWriteByte(TM1638_SPIx,value);      //写入寄存器的值

  TM1638_SPI_CS_DISABLE();                 //禁止SPI传输   

}

 

voidWrite_DATA(unsigned char add,unsigned char DATA)     //指定地址写入数据

 

{

    TM1638_Write_Reg(0x44);

    TM1638_SPI_CS_ENABLE() ;

    //TM1638_Write(0xc0|add);

        TM1638_SPIx_ReadWriteByte(TM1638_SPIx,0xc0|add);    //设置起始地址

        TM1638_SPIx_ReadWriteByte(TM1638_SPIx,DATA);    //设置起始地址

    //TM1638_Write(DATA);

    TM1638_SPI_CS_DISABLE();

}

 

/*

voidWrite_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);

}  */

voidWrite_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);

        }

}

voidinit_TM1638(void)

 

{

    unsigned char i;

    TM1638_GPIO_init();

    TM1638_SPIx_SetSpeed(TM1638_SPIx,SPI_BaudRatePrescaler_4);//spi速度为9Mhz(24L01的最大SPI时钟为10Mhz)    

 

    TM1638_Write_Reg(0x8b);       //亮度 (0x88-0x8f)8级亮度可调

    TM1638_Write_Reg(0x40);       //采用地址自动加1

    TM1638_SPI_CS_ENABLE() ;                 //

    TM1638_SPIx_ReadWriteByte(TM1638_SPIx,0xc0);    //设置起始地址

 

    for(i=0;i<16;i++)     //传送16个字节的数据

        TM1638_SPIx_ReadWriteByte(TM1638_SPIx,0x00);

   

    TM1638_SPI_CS_DISABLE();

}

#endif

 

//main.C文件

 

/* 包含头文件 ----------------------------------------------------------------*/

#include"stm32f10x.h"

#include"bsp/usart/bsp_debug_usart.h"

#include"bsp/NRF24l01/NRF24l01.h"

#include"bsp/TM1638/bsp_tm1638.h"

 

 

unsignedchar LedTab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,

                          0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};

 

/* 私有类型定义 --------------------------------------------------------------*/

 

/* 私有宏定义 ----------------------------------------------------------------*/

 

/* 私有变量 ------------------------------------------------------------------*/

/* 扩展变量------------------------------------------------------------------*/

/* 私有函数原形 --------------------------------------------------------------*/

staticvoid Delay(uint32_t time);

 

 

 

/* 函数体 --------------------------------------------------------------------*/

 

/**

  * 函数功能: 主函数.

  * 输入参数: 无

  * 返 回 值: 无

  * 说    明: 无

  */

intmain(void)

{

uint8_ti;

  uint8_t tmp_buf[33]="硬石开发板 NRF24L01 实验";

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

 

  /* 调试串口初始化配置,115200-N-8-1.使能串口发送和接受 */

  DEBUG_USART_Init(); 

 

  /* 调用格式化输出函数打印输出数据 */

  printf("这是一个NRF24L012.4G无线数据传输模块测试实验\n");

 

 

 

  init_TM1638();

 

  /* 无限循环 */

 

     Delay(200);

  for(i=0;i<8;i++)

    Write_DATA(i<<1,tab[0]);                 //初始化寄存器

   

    while(1)

    {

               Delay(100);

        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);

                i++;                          //读按键值

 

        }

        else

            i= 0;

 

 

    }

}

 

/**

  * 函数功能: 简单粗暴的延时函数

  * 输入参数: time;延时时间设置

  * 返 回 值: 无

  * 说    明:使用这种死循环方式的延时函数是没办法精确控制延时时间长短,

  *           只是大概的延时时间,所以基本上都是通过不断修改输入参数

  *           大小然后下载到开发板上看实验效果。

  */

staticvoid Delay(uint32_t time)

{

  uint32_t i,j;

 

  for(i=0;i<time;++i)

  {

    for(j=0;j<10000;++j)

    {      

      //空循环,什么都不做       

    }

  }

}

 

 

 

如果实在搞不懂,发邮件给我[email protected]