这里使用的TM1637是不带键盘的四数字显示的版本
具体的TM1637的操作可以去网上搜索它的使用手册,上面有这个器件的原理图和使用方法
这个代码的效果是每隔1s(大概是)数码管显示数字减一
这是要用到的头文件,我把要显示的四位数字用a、b、c、d四个变量来做数组和显示函数的连接
这里数据线设置的是P1.5端口,时钟线是P1.4端口TM1637对应的DIO、CLK对应接到P1.5、P1,4.如果不方便接线可以更改
void DIO_OUT()和void CLK_OUT()两个函数中的P1OUT |= BIT4 和P1OUT |= BIT5
如果想用P1.6设置为数据线可以把void DIO_OUT()中的P1OUT |= BIT5改为
P1OUT |= BIT6这样P1.6端口就变成数据线的端口了
如果想要用P2.0~P2..5中的端口作为数据线和时钟线还需要更改
void TM1637_Init()函数中的内容,将要设置的两个端口设置为输出就可以了
P2DIR |= BITX + BIT X;(X就是你选择的两个端口)
/*
* TM1637_H.h
* Created on: 2022年4月22日
* Author: CircleCheng
*/
#ifndef TM1637_H_H_
#define TM1637_H_H_
//0~9数字和带小数点数码管数字16进制值
/*
* 0=0x3f 1=0x06 2=0x5b 3=0x4f 4=0x66
* 5=0x6d 6=0x7d 7=0x07 8=0x7f 9=0x6f
* a=0x77 b=0x7c c=0x58 d=0x5e e=0x79 f=0x71
*/
unsigned char Ldata[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; 不带小数点
unsigned char Ldatadp[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; //带小数点的
unsigned char a = 4;unsigned char b = 8;unsigned char c = 7;unsigned char d = 3; //设置初始要显示的四个数字
void DIO_OUT(char i) //DIO高低电平输出0为低电平1为高电平
{
if(i == 0) P1OUT &= ~BIT5;
else P1OUT |= BIT5;
}
void CLK_OUT(char i) //CLK高低电平输出0为低电平1为高电平
{
if(i == 0) P1OUT &= ~BIT4;
else P1OUT |= BIT4;
}
void TM1637_Init(void)
{
P1DIR |= BIT5 + BIT4; //P1.6为数据线、P1.7为时钟线
}
//数据输入开始
void TM1637_Start()
{
CLK_OUT(1); //拉高时钟线
DIO_OUT(1); //拉高数据线
__delay_cycles(5000); //延时5um
DIO_OUT(0); //拉低数据线开始数据输入
}
//输入结束
void TM1637_Stop()
{
CLK_OUT(1); //拉高时钟线
DIO_OUT(0); //拉低数据线
__delay_cycles(5000); //延时5um
DIO_OUT(1); //拉高数据线结束数据输入
}
//TM1637应答
void TM1637_ACK()
{
CLK_OUT(0); //拉低时钟线 使能改变数据线信号
__delay_cycles(5000); //延时
CLK_OUT(1); //拉高时钟线
__delay_cycles(5000); //延时5um
//while(P1OUT & BIT6); //检验数据线是否被拉低
CLK_OUT(0); //拉低时钟线使能改变数据线信号
}
//发送字节
void TM1637_WByte(unsigned char Byte)
{
unsigned char i;
for(i = 0;i < 8;i++)
{
CLK_OUT(0); //拉低时钟,使能改变数据线信号
if(Byte & BIT0) //应为TM1637要从低位输入数据所以与0x01与与运算后将数据右移得到每位的数据存到数据线中
{DIO_OUT(1);} //拉高数据线
else
{DIO_OUT(0);} //拉低数据线
__delay_cycles(5000);//延时
Byte = Byte >> 1; //取走最低位后右移
CLK_OUT(1); //拉高时钟线
__delay_cycles(5000);//延时
}
}
//显示寄存器
void SmgDisplay(unsigned char a,unsigned char b,unsigned char c,unsigned char d)
{
unsigned char i;
TM1637_Start();
TM1637_WByte(0x40); //选择使用地址自加模式
TM1637_ACK();
TM1637_Stop();
TM1637_Start();
TM1637_WByte(0xc0); //设置首地址为00H
TM1637_ACK();
TM1637_WByte(a); //送数据
TM1637_ACK();
TM1637_WByte(b); //送数据
TM1637_ACK();
TM1637_WByte(c); //送数据
TM1637_ACK();
TM1637_WByte(d); //送数据
TM1637_ACK();
TM1637_Stop();
TM1637_Start();
TM1637_WByte(0x8a); //B0~B2控制脉冲宽度(数码管亮度)7个等级、B3控制显示开关
TM1637_ACK();
TM1637_Stop();
}
#endif /* TM1637_H_H_ */
然后是主文件,主文件只需要配置一下时钟打开定时器中断然后写一个中断函数就可以了
#include <msp430g2553.h>
#include <TM1637_H.h>
unsigned char num = 0;
//初始化时钟为1MHZ分频系数为1
void InitSystemClock(void){
//配置时钟源为1MHz
DCOCTL = CALDCO_1MHZ;
BCSCTL1 = CALBC1_1MHZ;
//选择SMCLK的时钟源为DCO;
BCSCTL2 &= ~SELS;
//SMCLK选择分频系数为1
BCSCTL2 &= ~(DIVS0 + DIVS1);}
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // 关闭看门狗
InitSystemClock();//初始化时钟
TA1CTL |= TASSEL_2; //选择SMCLK为定时器时钟源
TA1CTL |= MC_1; //选择上数模式
TA1CCR0 = 49999; //设置计数值
TA1CTL |= TAIE; //打开定数器中断
TM1637_Init(); //初始化TM1637
SmgDisplay(Ldata[a],Ldata[b],Ldata[c],Ldata[d]);
_EINT(); //打开总中断
while(1)
{}
return 0;
}
#pragma vector = TIMER1_A1_VECTOR
__interrupt void digital_ISR(void)
{
if(TA1IV & 0x0A)
{
num++; //完成1s计数变量
if(num == 20) //1MHZ计数50000耗时5ms;20次就是1s
{
num = 0;
SmgDisplay(Ldata[a],Ldata[b],Ldata[c],Ldata[d]);
if(a == 0 && b == 0 && c == 0 && d == 0){a = 10;}
if(b == 0 && c == 0 && d == 0){b = 10; a--;}
if(c == 0 && d == 0){c = 10; b--;}
if(d == 0){d = 10; c--;} //结束后会自减1所以初值设为10
d--;
}
}
}
编译后就能点亮了