【51单片机】童年回忆,咬手鲨鱼改装闹钟

2 篇文章 0 订阅
2 篇文章 0 订阅

1.概要:
还记得小时候玩的咬手鲨鱼吗?数十颗牙齿随机按下,鲨鱼嘴巴就会咬下。现在来试着把它改成闹钟吧!
这里写图片描述
2.最后成品图:
使用方法:闹钟响起,必须按下那颗会使嘴巴闭合的牙齿才能关闭闹钟(每次随机)。也就是说,早上起床会被鲨鱼咬到痛醒,或者你也能闪躲不被咬到,如果足够清醒的话。
这里写图片描述
3.教程:
(1)材料:咬手鲨鱼+51单片机+DS3231+ TM1637驱动数码管
(2)程序:(看程序注释应该知道怎么接线)
4.STC89C52RC程序:

#include <reg52.h>
#include <intrins.h>  
#define uchar unsigned char
#define uint unsigned int

#define DS3231_WriteAddress 0xD0  
#define DS3231_ReadAddress  0xD1   
#define DS3231_SECOND       0x00   
#define DS3231_MINUTE       0x01  
#define DS3231_HOUR         0x02   
#define DS3231_WEEK         0x03   
#define DS3231_DAY          0x04   
#define DS3231_MONTH        0x05   
#define DS3231_YEAR         0x06   

unsigned char dpFlag = 0; //dp标志位
unsigned char code SEGData[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//1-9,不带数点 
unsigned char code SEGDataDp[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; //1-9,带数点 
unsigned int countTime = 0;  
unsigned char time, sec;  
uchar alarmHour = 24, alarmMin = 60, alarmHour2 = 24, alarmMin2 = 60;

sbit CLK = P0^0;   //数码管时钟
sbit DIO = P0^1;   //数码管数据
sbit SDA = P0^2;     //模拟I2C数据传送位SDA        
sbit SCL = P0^3;     //模拟I2C时钟控制位SCL 
sbit we1 = P1^0;   //时,十位
sbit we2 = P1^1;   //时,个位
sbit we3 = P1^2;   //分,十位
sbit we4 = P1^3;   //分,个位
sbit we5 = P1^4;   //秒,十位
sbit we6 = P1^5;   //秒,个位
sbit closeBeep = P2^6;    //??
sbit beep = P2^7;    //蜂鸣器
bit  ack;          //应答标志位

struct {  
                char shi;  
    char ge;  
} Hour;  

struct {  
    char shi;  
    char ge;  
} Minute;  

uchar flag = 0;
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar Recive_table[3]; 
static uchar i = 0;
uchar num = 0;

void TM1637_start();  
void TM1637_stop();  
void TM1637_write1Bit(unsigned char mBit);  
void TM1637_write1Byte(unsigned char mByte);  
void TM1637_writeCammand(unsigned char mData);  
void TM1637_writeData(unsigned char addr, unsigned char mData);  
void time_set(char hour, char min);  
void time_display();  
void timer0_init();  

void delay_140us();  
void delayus(uint us);  


uchar BCD2HEX(uchar val)    //BCD码转换为Byte
{
    uchar temp;
    temp=val&0x0f;
    val>>=4;
    val&=0x0f;
    val*=10;
    temp+=val;
    return temp;
}

uchar HEX2BCD(uchar val)    //B码转换为BCD码
{ 
     return (((val%100)/10)<<4)|(val%10);
}

void delayus(uint us) 
{
    while (us--);
}

void Start_I2C()
{
    SDA=1;                  //???????????
    delayus(1);
    SCL=1;
    delayus(5);             //??????????4.7us,??

    SDA=0;                  //??????
    delayus(5);             // ??????????4祍

    SCL=0;                  //??I2C??,?????????
    delayus(2);
}

void Stop_I2C()
{
    SDA=0;                  //???????????
    delayus(1);             //???????????
    SCL=1;                  //??????????4us
    delayus(5);

    SDA=1;                  //??I2C??????
    delayus(4);
}

void SendByte(uchar c)
{
    uchar BitCnt;

    for(BitCnt=0;BitCnt<8;BitCnt++)         //?????????8?
    {
        if((c<<BitCnt)&0x80)
            SDA=1;                          //?????
        else 
            SDA=0;               
          delayus(1);
          SCL=1;                            //??????,????????????
          delayus(5);                       //???????????4祍   
          SCL=0;
    }

    delayus(2);
    SDA=1;                                  //8??????????,???????
    delayus(2);  
    SCL=1;
    delayus(3);
    if(SDA==1)
        ack=0;    
    else
        ack=1;                              //???????????
    SCL=0;
    delayus(2);
}

uchar RcvByte()
{
   uchar retc;
   uchar BitCnt;

   retc = 0;
   SDA = 1;                           //?????????
   for(BitCnt = 0;BitCnt < 8;BitCnt++)
   {
        delayus(1);  
        SCL = 0;                      //??????,???????

        delayus(5);                 //?????????4.7祍

        SCL = 1;                      //???????????????
        delayus(3);
        retc = retc << 1;
        if(SDA == 1)
            retc = retc + 1;            //????,????????retc?
        delayus(2);
   }
   SCL = 0;
   delayus(2);
   return(retc);
}

void Ack_I2C(bit a)
{
    if(a == 0)
        SDA = 0;              //????????????
    else
        SDA = 1;
    delayus(3);     
    SCL = 1;

    delayus(5);             //?????????4祍

    SCL = 0;                  //????,??I2C????????
    delayus(2);   
}


uchar write_byte(uchar addr, uchar write_data)
{
    Start_I2C();
    SendByte(DS3231_WriteAddress);
    if (ack == 0)
        return 0;

    SendByte(addr);   
    if (ack == 0)
        return 0;

    SendByte(write_data);
    if (ack == 0)
        return 0;

    Stop_I2C();
    delayus(10);      
    return 1;
}


uchar read_current()
{
    uchar read_data;
    Start_I2C();
    SendByte(DS3231_ReadAddress);
    if(ack == 0)
        return(0);

    read_data = RcvByte();
    Ack_I2C(1);
    Stop_I2C();
    return read_data;
}


uchar read_random(uchar random_addr)
{
    Start_I2C();
    SendByte(DS3231_WriteAddress);
    if(ack == 0)
        return(0);

    SendByte(random_addr);
    if(ack == 0)
        return(0);

    return(read_current());
}
/******************************************************************** 
* 名称 : void init() 
* 功能 : 程序初始化
* 输入 : void
* 输出 : 无 
**************************************************************/  
void init()   
{
                TMOD = 0X21;  //用定时器设置串口波特率           9600 
                TH0 = (65536 - 50000) / 256;
                TL0 = (65536 - 50000) % 256;
                TR0 = 1;    
    ET0 = 1;  
    EA = 1;  
                //for bluetooth
                TH1 = 0xfd;
                TL1 = 0xfd;
                TR1 = 1;
                REN = 1;          //串口初始化
                SM0 = 0;
                SM1 = 1;
                EA = 1;           //开启总中断
                ES = 1;
}
/******************************************************************** 
* 名称 : void time_display()
* 功能 : 显示时间
* 输入 : void
* 输出 : 无 
**************************************************************/  
void TimeDisplay(uchar Dhour,uchar Dmin)
{
    Hour.shi = Dhour / 10;                //时,十位
    Hour.ge = Dhour % 10;                        //时,个位
    Minute.shi = Dmin / 10;                //分,十位
    Minute.ge = Dmin % 10;                 //分,个位

          TM1637_writeCammand(0x44);  
    TM1637_writeData(0xc0, SEGData[Hour.shi]);  
    if(dpFlag)  
        TM1637_writeData(0xc1, SEGDataDp[Hour.ge]); //带数点 
    else  
        TM1637_writeData(0xc1, SEGData[Hour.ge]);  //不带数点 
    TM1637_writeData(0xc2, SEGData[Minute.shi]);  
    TM1637_writeData(0xc3, SEGData[Minute.ge]);  
    TM1637_writeCammand(0x8a);            
}
/******************************************************************** 
* 名称 : void computer_and_display_time()
* 功能 : 显示时间
* 输入 : void
* 输出 : 无 
**************************************************************/  
void compute_and_display_time()
{
                //计算时间
    uchar Htemp1, Htemp2, Mtemp1, Mtemp2;// Stemp1, Stemp2; 
    Htemp1 = read_random(DS3231_HOUR);    //获取时
    Htemp1&=0x3f;                   
    Htemp2 = BCD2HEX(Htemp1);
    Mtemp1 = read_random(DS3231_MINUTE);  //获取分
    Mtemp2 = BCD2HEX(Mtemp1);

                if(alarmHour == Htemp2 && alarmMin == Mtemp2)
                {
                        if(closeBeep == 0)
                        {
                                if(beep == 1)
                                        beep = 0;
                                else
                                        beep = 1;
                        }                        
                        else 
                        {
                                beep = 0;
                        }
                }
                else
                        closeBeep = 0;

                //显示时间
    TimeDisplay(Htemp2, Mtemp2);
}
/******************************************************************** 
* 名称 : void TM1637_start()
* 功能 : start信号
* 输入 : void
* 输出 : 无 
**************************************************************/  
void TM1637_start()  
{  
    CLK = 1;  
    DIO = 1;  
    delay_140us();  
    DIO = 0;  
    delay_140us();  
    CLK = 0;  
    delay_140us();  
}
/******************************************************************** 
* 名称 : void TM1637_stop()  
* 功能 : stop信号
* 输入 : void
* 输出 : 无 
**************************************************************/  
void TM1637_stop()  
{  
    CLK = 0;  
    delay_140us();  
    DIO = 0;  
    delay_140us();  
    CLK = 1;  
    delay_140us();  
    DIO = 1;  
    delay_140us();  
}
/******************************************************************** 
* 名称 : void TM1637_write1Bit(unsigned char mBit)  
* 功能 : 写入1bit
* 输入 : unsigned char mBit
* 输出 : 无 
**************************************************************/  
void TM1637_write1Bit(unsigned char mBit)  
{  
    CLK = 0;  
    delay_140us();  
    if(mBit)  
        DIO = 1;  
    else  
        DIO = 0;  
    delay_140us();    
    CLK = 1;  
    delay_140us();  
}  

/******************************************************************** 
* 名称 : void TM1637_write1Byte(unsigned char mByte)  
* 功能 : 写入1bit数据
* 输入 : unsigned char mByte
* 输出 : 无 
**************************************************************/  
void TM1637_write1Byte(unsigned char mByte)  
{  
    char loop = 0;  
    for(loop = 0; loop < 8; loop++)  
    {  
        TM1637_write1Bit((mByte>>loop)&0x01); //取得最低位
    }  
    CLK = 0;  
    delay_140us();  
    DIO = 1;  
    delay_140us();  
    CLK = 1;  
    delay_140us();  
    while(DIO == 1);  //获得应答位  
}
/******************************************************************** 
* 名称 : void TM1637_writeCammand(unsigned char mData) 
* 功能 : 写入1byte指令
* 输入 : unsigned char mData
* 输出 : 无 
**************************************************************/  
void TM1637_writeCammand(unsigned char mData)  
{  
    TM1637_start();  
    TM1637_write1Byte(mData);  //指令数据
    TM1637_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)
{  
    TM1637_start();  
    TM1637_write1Byte(addr);  //地址
    TM1637_write1Byte(mData);  //数据
    TM1637_stop();    
}
/******************************************************************** 
* 名称 : void timer0_isr()
* 功能 : 定时50ms(实际运行时由于指令运行的延时,会大于50ms)
* 输入 : void
* 输出 : 无 
**************************************************************/  
void timer0_isr() interrupt 1  
{  
          TH0 = (65536 - 50000) / 256;    //5 ????
    TL0 = (65536 - 50000) % 256;
                countTime ++;  
}
/******************************************************************** 
* 名称 : delay_140us()
* 功能 : 延时
* 输入 : void
* 输出 : 无 
**************************************************************/  
void delay_140us()  
{  
    int i;  
    for(i = 0; i < 20; i++)  
      _nop_();  
}  
/******************************************************************** 
* 名称 : void ModifyTime(uchar hou,uchar min,uchar sec)
* 功能 : 修改时间(全)
* 输入 : void
* 输出 : 无 
**************************************************************/ 
void ModifyTime(uchar hou, uchar min,uchar sec)
{
    uchar temp = 0;

    temp = HEX2BCD(hou);
    write_byte(DS3231_HOUR, temp);   //设置时

    temp = HEX2BCD(min);
    write_byte(DS3231_MINUTE, temp); //设置分

    temp = HEX2BCD(sec);
    write_byte(DS3231_SECOND, temp); //设置秒
}
/******************************************************************** 
* 名称 : void ModifyTime(uchar hou,uchar min,uchar sec)
* 功能 : 修改时间(时)
* 输入 : void
* 输出 : 无 
**************************************************************/ 
void ModifyHour(hour)
{
          uchar temp = HEX2BCD(hour);
    write_byte(DS3231_HOUR, temp);   //设置时
}
/******************************************************************** 
* 名称 : void Modifymin(minute)
* 功能 : 修改时间(分)
* 输入 : void
* 输出 : 无 
**************************************************************/ 
void ModifyMinute(minute)
{   
          uchar temp = HEX2BCD(minute);
    write_byte(DS3231_MINUTE, temp); //设置分  
}
/******************************************************************** 
* 名称 : void ModifyTime(uchar hou,uchar min,uchar sec)
* 功能 : 修改时间(秒)
* 输入 : void
* 输出 : 无 
**************************************************************/ 
void ModifySecond(second)
{
          uchar temp = HEX2BCD(second);
    write_byte(DS3231_SECOND, temp); //设置秒
}
/******************************************************************** 
* 名称 : void receiveData() interrupt 4
* 功能 : 接收蓝牙数据
* 输入 : void
* 输出 : 无 
**************************************************************/ 
void receiveData() interrupt 4
{
      if(RI == 1) 
      {
                                RI = 0;   
                                Recive_table = SBUF;                   
                                if(Recive_table == '\n')
                                {        
                                                if(i == 4)//调整时间
                                                {
                                                                num = (Recive_table[1] - '0') * 10 + (Recive_table[2] - '0');
                                                                if(Recive_table[0] == 'h')                
                                                                                ModifyHour(num);
                                                                else if(Recive_table[0] == 'm')
                                                                                ModifyMinute(num);
                                                }
                                                else if(i == 2)//获取时钟时间并发给手机
                                                                flag = 1;
                                                else if(i == 5)
                                                {
                                                                alarmHour = (Recive_table[0] - '0') * 10 + (Recive_table[1] - '0');
                                                                alarmMin = (Recive_table[2] - '0') * 10 + (Recive_table[3] - '0');
                                                                flag = 2;
                                                }
                                                i = 0;
                                }
                                else
                                        i++;
                        }
      else 
                                TI = 0;  
}
/*********************************************************** 
***** 
***** 主函数
***** 
***********************************************************/  
void main()  
{  
                init();
//                bluetoothVcc = 1;
//                bluetoothGnd = 0;
                beep = 0;
                closeBeep = 0;
    while(1)  
    {  
                                //计算+显示时间
                                compute_and_display_time();
        if(countTime <= 10)  //第一微秒:不带数点
        {  
            dpFlag = 0;           
        }  
        else if(countTime <= 20)  //第二微秒:带数点
        {  
            dpFlag = 1;   
        }  
        else                                                           //重置计数器
        {  
            countTime = 0;  
        }  
                                //蓝牙操作
                                if(flag == 1)   //反馈回当前时间
                                {
                                          uchar Htemp1, Htemp2, Mtemp1, Mtemp2;
                                                Htemp1 = read_random(DS3231_HOUR);    //获取时
                                                Htemp1&=0x3f;                   
                                                Htemp2 = BCD2HEX(Htemp1);
                                                Mtemp1 = read_random(DS3231_MINUTE);  //获取分
                                                Mtemp2 = BCD2HEX(Mtemp1);
                                                //发送时
                                                ES = 0;
                                                SBUF = Htemp2;
                                                while(!TI);
                                                TI = 0;
                                                ES = 1;
                                                //发送分
                                                ES = 0;
                                                SBUF = Mtemp2;
                                                while(!TI);
                                                TI = 0;
                                                ES = 1;

                                                flag = 0;
                                }
                                else if(flag == 2)//设置闹钟
                                {
                                                dpFlag = 1;  
                                                TimeDisplay(alarmHour, alarmMin);
                                                ES = 0;
                                                SBUF = 1;                         //单片机的数据发送到计算机,表示闹钟设置成功
                                                while(!TI);
                                                TI = 0;
                                                ES = 1;
                                                flag = 0;
                                                delayus(100000); 
                                }

    }  
}

5.塞进去,大功告成:
这里写图片描述
这里写图片描述

PS:最后做好后送人了,听反馈似乎代码还有点小问题,所以你可以再自己改改。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值