极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 14233|回复: 2

[51]童年回忆,咬手鲨鱼改装闹钟

[复制链接]
发表于 2016-9-2 15:51:26 | 显示全部楼层 |阅读模式
1.概要:
还记得小时候玩的咬手鲨鱼吗?数十颗牙齿随机按下,鲨鱼嘴巴就会咬下。现在来试着把它改成闹钟吧!


2.最后成品图:
使用方法:闹钟响起,必须按下那颗会使嘴巴闭合的牙齿才能关闭闹钟(每次随机)。也就是说,早上起床会被鲨鱼咬到痛醒,或者你也能闪躲不被咬到,如果足够清醒的话。


3.教程:
(1)材料:咬手鲨鱼+51单片机+DS3231+ TM1637驱动数码管
(2)程序:(看程序注释应该知道怎么接线)
[pre lang="51" line="1" file="咬手鲨闹钟"]
#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);
                                }
                               
    }  
}[/code]

(3)塞进去,大功告成

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2016-9-2 21:56:51 | 显示全部楼层
好久没见51程序了,都怪Arduino。哈哈……还是那么亲切。
程序写不错。
回复 支持 反对

使用道具 举报

发表于 2016-11-1 20:47:47 | 显示全部楼层
能做出来不容易啊
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-27 06:33 , Processed in 0.045187 second(s), 21 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表