stm32f103的数码管显示(1)--TM1629共阳极驱动

这里使用的是tm1629来驱动数码管,数码管采用共阳极,这样可以驱动更多的数码管,不过程序上要有断码和位码的转换

TM1629.H

#ifndef __TM1629_H
#define __TM1629_H

/*定义TM1629端口,如果使用不懂的端口,只需要修改前面的端口就可以了*/
#define TM1_STB_PIN GPIO_Pin_0
#define TM1_STB_PORT GPIOF

#define TM1_DIO_PIN GPIO_Pin_2
#define TM1_DIO_PORT GPIOF

#define TM1_CLK_PIN GPIO_Pin_1
#define TM1_CLK_PORT GPIOF

#define TM1_STB_H GPIO_SetBits(TM1_STB_PORT, TM1_STB_PIN)
#define TM1_STB_L GPIO_ResetBits(TM1_STB_PORT, TM1_STB_PIN)
#define TM1_DIO_H GPIO_SetBits(TM1_DIO_PORT, TM1_DIO_PIN)
#define TM1_DIO_L GPIO_ResetBits(TM1_DIO_PORT, TM1_DIO_PIN)
#define TM1_CLK_H GPIO_SetBits(TM1_CLK_PORT, TM1_CLK_PIN)
#define TM1_CLK_L GPIO_ResetBits(TM1_CLK_PORT, TM1_CLK_PIN)

#define READ_TM1_DIO GPIO_ReadInputDataBit(TM1_DIO_PORT, TM1_DIO_PIN)

/****************************public*********************************************************/
void tm1629a_gpio_init(void); //tm1629a端口初始化,推挽输出
void tm1629_init(void); //tm1629芯片初始化程序

/****************************private*********************************************************/

void tm1629SendByte(unsigned char data); //串行模式 MCU一次输出8个bit
void tm1629SendCmd(unsigned char cmd); //写命令

void tm1639_write(unsigned char *data );//打开TM1629并显示指定的数据
void write_tm1639_off(unsigned char *data );//关闭TM1629显示

void convert(unsigned char SrcNum, unsigned char *pDst , unsigned char seg, unsigned char dot);//共阳数码管数据格式转换 0~9转换
void convert2(unsigned char SrcNum, unsigned char *pDst , unsigned char seg); //共阳数码管数据格式转换 特殊格式转换

#endif

TM1629.C

#include "tm1629.h"
#include"stm32f10x.h" //只要调用库函数,就需要添加此头文件
#include"delay.h"

/***************************************************************************public****************************************************************************/

/*tm1629端口初始化,3个端口都是推挽输出*/
void tm1629a_gpio_init(void){
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE); //使能PF端口时钟

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //TM1的STB挽输出
GPIO_InitStructure.GPIO_Pin=TM1_STB_PIN;
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;
GPIO_Init(TM1_STB_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin=TM1_DIO_PIN; //TM1的DIO推挽输出
GPIO_Init(TM1_DIO_PORT, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin=TM1_CLK_PIN; //TM1的CLK推挽输出
GPIO_Init(TM1_CLK_PORT, &GPIO_InitStructure);
}

/*启动tm1629必须有一个启动模式*/
void tm1629_init(void){
  TM1_CLK_H;
  TM1_DIO_H;
  TM1_STB_H;
  tm1629SendCmd(0x03); //写TM1629显示模式
  tm1629SendCmd(0x40); //写数据到显示寄存器的方式采用地址自动加一
  tm1629SendCmd(0x88); //开显示,亮度可以通过改变低三位调节
}

/***************************************************************************private****************************************************************************/

/*串行模式 在时钟的上升沿通过MCU向LED驱动IC——TM16xx写数据 */
void tm1629SendByte(unsigned char dat){
  unsigned char i;
  TM1_STB_L;//保证“STB”为低电平,程序不依赖于之前端口的状态;保证程序在实际运行中不会出现“端口迷失”
  for(i=0;i<8;i++)
  {
    TM1_CLK_L; //clk置低,等待发送数据
    if((dat & 0x01) == 0x01){ //传送最高位给DI
    TM1_DIO_H; //需要传送的数据的低位为“1”,则把“DIO”置高
    }
    else{
      TM1_DIO_L; //需要传送的数据的低位为“0”,则把“DIO”置零
    }
    delay_ms(1);
    TM1_CLK_H; //送时钟的上升沿
    dat >>= 1; //准备送下一个BIT
    //delay_ms(1);
  }
}

/*写命令*/
void tm1629SendCmd(unsigned char cmd){
  TM1_STB_H;
  TM1_CLK_H;
  TM1_DIO_H; //通讯开始前通讯端口全部初始化为“1”
  delay_ms(2);
  TM1_STB_L; //片选(低电平)
  tm1629SendByte(cmd);
  TM1_STB_H;
}

/*打开TM1629并显示指定的数据*/
void tm1639_write(unsigned char *data ){
  unsigned char i=0;

  TM1_STB_H;
  tm1629SendByte(0x40); //传数据设置命令,设置采用地址自动加一方式显示数据
  TM1_STB_H;
  tm1629SendByte(0xc0); //传送起始地址,地址命令传完后,“STB”保持为0继续传需要显示的数据
  for(i=0;i<16;i++) {//在连续显示的数据过程汇总,“STB”一直保持为0,
    tm1629SendByte(data[i]);
  }
  TM1_STB_H; //传送完所有的显示数据后(最多14BYTE),将STB置1
  tm1629SendByte(0x88);//0x8f //开显示,脉冲宽度为1/16 这个是最低的脉冲宽度
  TM1_STB_H;
}

/*关闭TM1629显示*/
void write_tm1639_off(unsigned char *data ){
  unsigned char i=0;

  TM1_STB_H;
  tm1629SendByte(0x40); //传数据设置命令,设置采用地址自动加一方式显示数据
  TM1_STB_H;
  tm1629SendByte(0xc0); //传送起始地址,地址命令传完后,“STB”保持为0继续传需要显示的数据
  for(i=0;i<16;i++){
    tm1629SendByte(data[i]);
  }
  TM1_STB_H;
  tm1629SendByte(0x87); //关显示,脉冲宽度为14/16
  TM1_STB_H;
}

/*共阳数码管数据格式转换

输入参数: SrcNum为0-9
pDst为转换后的数据
seg为当前数码管对应的sel管脚编号减1, 比如数码管片选接到芯片的SEG2,那么seg为1
dot为当前数码管是否带点显示
*/
void convert(unsigned char SrcNum, unsigned char *pDst , unsigned char seg, unsigned char dot){
  unsigned char table[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
  unsigned char i,uSrc;

  if(dot == 0)
    uSrc = table[SrcNum];
  else
    uSrc = table[SrcNum] | 0x80;

  for(i=0; i<8; i++){ //一位一位移过去
  if((uSrc & 0x01) == 1){//如果将要移过去的位是1,在对应的位置写1,紧跟着后一位写0
    if(seg < 8){
      pDst[2*i] = (1<<seg); //SEG<8,在地址的0、2、4、6、8、10、12、14写入有效数据
      pDst[2*i + 1] = 0;//在地址的1、3、5、7、9、11、13、15填零
    }
    else if(seg > 7){
      pDst[2*i] = 0;//SEG>8,在地址的0、2、4、6、8、10、12、14填零
      pDst[2*i + 1] = (1<<(seg - 8));//在地址的1、3、5、7、9、11、13、15写入有效数字(9是左移1位,依次类推)
    }
  }
  else{//如果将要移过去的位是0,在对应的位置写0,紧跟着后一位写0
    pDst[2*i] = 0;
    pDst[2*i + 1] = 0;
  }
  uSrc>>=1;//右移,移第二位
  }

}

猜你喜欢

转载自www.cnblogs.com/wlstm/p/9853290.html