用2553单片机实现按键倒计时响铃,用TM1637显示倒计时时间

由于个人原因近期都没有更新博客了,现在更新一篇关于单片机的入门级的功能实现。
具体要求如下:
实现由2553单片机按键按下,实现开启给定时间的倒计时,在定时结束后蜂鸣器开始响铃。倒计时的时间实现由TM1637数码管显示。
注:TM1637数码管资料如下:
资料链接:https://pan.baidu.com/s/1POymj8LqbfPZexBZc-EpXg

提取码:up4e
本次实验中使用了按键外部中断,和定时器中断:
具体代码如下:

/*
 * 接线 : 蜂鸣器:    p1.0
 *        TM1637: scl: p1.6   sda:p1.7
 * 创作时间:2020-9-10
 * 作者:JuGiaMing
 */
#include 
#include 
#include 

uint16_t number = 10;            // 倒计时初始值
volatile unsigned int flag=0;
unsigned char dpFlag = 0,A1,A2,A3,A4;
unsigned char Data[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
unsigned char DataDp[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};

/********************************************************************
* 名称 : void time_display( void )
* 功能 : 显示时间
* 输入 : void
* 输出 : 无
**************************************************************/
void time_display( void )     //显示时间
{
    TM1637_writeCammand(0x44);
    TM1637_writeData(0xc0, Data[A1]);
    if(dpFlag)
        TM1637_writeData(0xc1, DataDp[A2]); //小数点标志为1则用小数点那个数组
    else
        TM1637_writeData(0xc1, Data[A2]);
    TM1637_writeData(0xc2, Data[A3]);
    TM1637_writeData(0xc3, Data[A4]);
    TM1637_writeCammand(0x8a);
}
int main(void)
{
	WDTCTL = WDTPW | WDTHOLD;	             // 关闭看门狗
	if (CALBC1_1MHZ==0xFF)
	{
	    while(1);
	}
	DCOCTL = 0;
	BCSCTL1 = CALBC1_1MHZ;
	DCOCTL = CALDCO_1MHZ;      //校准时钟
//设置输出端口
    P1DIR |=  BIT0;                          //设置P1.0口输出
    P1OUT &= ~BIT0;
//设置外部中断
    P1REN |= BIT3;                           //启用P1.3口的内部电阻
    P1OUT |= BIT3;                           //设置P1.3内电阻为上拉电阻
    P1DIR &= ~BIT3;                          //设置P1.3口为输入
    P1IES |= BIT3;                           //设置中断为下降沿触发
    P1IE |= BIT3;                            //允许中断

    TA0CCR0 = 20000;
    TA0CTL = TASSEL_1 + MC_1;                   //MC_1: 增计数模式, TASSEL_1:选择时钟为ACLK
    I2C_Init();
    //__bis_SR_register(LPM0_bits + GIE);
    _EINT();
   while(1){
       A1 = number / 1000;
       A2 = number / 100 % 10;
       A3 = number / 10 % 10;
       A4 = number % 10;
       time_display();
   }

}
#pragma vector=PORT1_VECTOR
__interrupt void PORT1(void)
{
    TA0CCTL0 = CCIE;                            //允许TA0CCTL0中断
    P1IFG = 0;
}

#pragma vector=TIMER0_A0_VECTOR
__interrupt void CLOCK_A(void)
{
    if( number > 0){                                // 大于0则自减不响铃
        number--;
        P1OUT &= ~BIT0;
    }else{                                          //  小于0则响铃
        while(1){
            P1OUT ^=  BIT0;
            delay_ms(50);
        }
    }
}

调用模块



#include 


void I2C_Init(void)
{
    P1DIR |=  BIT6 + BIT7;
}
//**************************************
//I2C起始信号
//**************************************
void I2C_Start()   //用
{
    I2C_SDA_M_OUT;

    I2C_SDA_OUT(1);                    //拉高数据线
    I2C_SCL_OUT(1);                    //拉高时钟线
    delay_us(5);
    I2C_SDA_OUT(0);                    //产生下降沿
    delay_us(5);
    I2C_SCL_OUT(0);                    //拉低时钟线
}
//**************************************
//I2C停止信号
//**************************************
void I2C_Stop()  //用
{
  I2C_SDA_M_OUT;

  I2C_SDA_OUT(0);                    //拉低数据线
  I2C_SCL_OUT(0);                    //拉低时钟线
  delay_us(5);                  //延时
  I2C_SCL_OUT(1);                    //拉高时钟线
  delay_us(5);                   //延时
  I2C_SDA_OUT(1);                    //产生上升沿

}


//**************************************
//I2C接收应答信号
//**************************************
uint8_t I2C_RecvACK()   //用
{
  uint8_t tempcount;

  I2C_SDA_M_IN;
  delay_us(5);                 //延时

  I2C_SDA_OUT(1);
  I2C_SCL_OUT(1);                    //拉高时钟线
    delay_us(5);
    while(I2C_SDA_IN){
        tempcount++;
        if(tempcount > 250) return 1;//无应答信号,终止传输
    }
    //检测到Slave应答信号
    I2C_SCL_OUT(0);                    //拉低时钟线
    return 0;

}
//**************************************
//向I2C总线发送一个字节数据
//**************************************
void I2C_WriteByte(uint8_t data0)    //用
{
  uint8_t i;
  I2C_SDA_M_OUT;
  for(i=0; i<8; i++)         //8位计数器
  {
      delay_us(10);
    if(data0 & 0x01)    I2C_SDA_OUT(1);
    else                I2C_SDA_OUT(0);

    data0 >>= 1;

    I2C_SCL_OUT(1);                //拉高时钟线
    delay_us(5);              //延时
    I2C_SCL_OUT(0);                //拉低时钟线
    delay_us(5);              //延时
  }
}


/********************************************************************
* 名称 : void TM1637_writeCammand(unsigned char mData)
* 功能 : 写指令1byte
* 输入 : unsigned char mData
* 输出 :**************************************************************/
void TM1637_writeCammand(unsigned char mData)     //用
{
    I2C_Start();
    I2C_WriteByte(mData);  //数据
    I2C_RecvACK();
    I2C_Stop();
}


/********************************************************************
* 名称 : void TM1637_writeData(unsigned char addr, unsigned char mData)
* 功能 : 固定地址写数据1byte
* 输入 : unsigned char addr, unsigned char mData
* 输出 : 无
**************************************************************/
void TM1637_writeData(unsigned char addr, unsigned char mData)  //用
{
    I2C_Start();
    I2C_WriteByte(addr);  //地址
    I2C_RecvACK();
    I2C_WriteByte(mData);  //数据
    I2C_RecvACK();
    I2C_Stop();
}

void SmgDisplay(uint8_t data) //写显示寄存器
{
    unsigned char i;
    I2C_Start();
    I2C_WriteByte(0x40); // 40H 地址自动加 1 模式,44H 固定地址模式,本程序采用自加 1 模式
    I2C_RecvACK();
    I2C_Stop();
    I2C_Start();
    I2C_WriteByte(0xc0); //设置首地址,
    I2C_RecvACK();
    for(i=0;i<6;i++) //地址自加,不必每次都写地址
    {
        I2C_WriteByte(data); //送数据
        I2C_RecvACK();
    }
    I2C_Stop();
    I2C_Start();
    I2C_WriteByte(0x8f); //开显示 ,最大亮度
    I2C_RecvACK();
    I2C_Stop();
}

你可能感兴趣的:(单片机,嵌入式)