您的位置:首页 > 其它

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

2017-02-28 14:13 260 查看
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????????

ffd3
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:最后做好后送人了,听反馈似乎代码还有点小问题,所以你可以再自己改改。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: