×
单片机 > 单片机程序设计 > 详情

51单片机gy906测温,语音播报,eepromc存储

发布时间:2021-05-11 发布时间:
|

这是去年我做的一个小设计,主要是用来测量体温。今年由于疫情影响情况特殊,就想分享一下这个设计,但是某宝找材料才发现一个问题,都涨价了,有点难受。之前也在51黑下过资料,这次把资料发上来大家一起分享学习。实物图:

没有涉及PCB,用的洞洞板。第一次发帖。东西做出来有点丑,大家莫见怪。


主要功能:

通过按键控制测温,按一次检测一次。自动存储三次数据,可t通过按键切换显示。并可通过OLED显示和语音播报温度。

系统供电采用,USB供电,也可以通过干电池,或者锂电池。

主要使用元器件。

主控用的是51单片机,温度传感器用的是GY906,显示用的是0.96寸0LED,通讯方式采用IIC,语音播报用的现成的模块。



语音播报采用串口通讯,比较简单。直接

printf("你好");



就可以直接播报你好。

主要原理图:


主要来说说GY906和eeprom

直接上代码吧。

先来测温的

#include "reg52.h"

#include "GY906.h"


#define Nack_counter 10


//************ 数据定义****************

bdata uchar flag;//可位寻址数据

sbit bit_out=flag^7;

sbit bit_in=flag^0;

unsigned char DataH,DataL,Pecreg;




void delay(uint a)

{

uint b;

for(;a>0;a--)

for(b=125;b>0;b--);

}



void i2c_Init(void)

{

SCL=1;

SDA=1;

_nop_();

_nop_();

_nop_();

_nop_();

SCL=0;

delay(1);

SCL=1;

}


//************************************

void start_bit(void)

{

SDA=1;

_nop_();_nop_();_nop_();_nop_();_nop_();

SCL=1;

_nop_();_nop_();_nop_();_nop_();_nop_();

SDA=0;

_nop_();_nop_();_nop_();_nop_();_nop_();

SCL=0;

_nop_();_nop_();_nop_();_nop_();_nop_();


}

//------------------------------

void stop_bit(void)

{


SCL=0;

_nop_();_nop_();_nop_();_nop_();_nop_();

SDA=0;

_nop_();_nop_();_nop_();_nop_();_nop_();

SCL=1;

_nop_();_nop_();_nop_();_nop_();_nop_();

SDA=1;

}

//--------- 发送一个字节---------

void tx_byte(uchar dat_byte)

{

char i,n,dat;

n=Nack_counter;

TX_again:

dat=dat_byte;

for(i=0;i<8;i++)

{

if(dat&0x80)

bit_out=1;

else

bit_out=0;

send_bit();

dat=dat<<1;

}

receive_bit();

if(bit_in==1)

{

stop_bit();

if(n!=0)

{n--;goto Repeat;}

else

goto exit;

}

else

goto exit;

Repeat:

start_bit();

goto TX_again;

exit: ;

}

//-----------发送一个位---------

void send_bit(void)

{

if(bit_out==0)

SDA=0;

else

SDA=1;

_nop_();

SCL=1;

_nop_();_nop_();_nop_();_nop_();

_nop_();_nop_();_nop_();_nop_();

SCL=0;

_nop_();_nop_();_nop_();_nop_();

_nop_();_nop_();_nop_();_nop_();

}

//---------- 接收一个字节--------

uchar rx_byte(void)

{

uchar i,dat;

dat=0;

for(i=0;i<8;i++)

{

dat=dat<<1;

receive_bit();

if(bit_in==1)

dat=dat+1;

}

send_bit();

return dat;

}


//---------- 接收一个位----------

void receive_bit(void)

{

SDA=1;bit_in=1;

SCL=1;

_nop_();_nop_();_nop_();_nop_();

_nop_();_nop_();_nop_();_nop_();

bit_in=SDA;

_nop_();

SCL=0;

_nop_();_nop_();_nop_();_nop_();

_nop_();_nop_();_nop_();_nop_();

}

////------------ 延时--------------

//void delay(uint N)

//{

// uint i;

// for(i=0;i

//

// _nop_();

//}

//------------------------------

float memread(void)

{

float wendu_change;

start_bit();

tx_byte(0xB4); //Send SlaveAddress ==============================

//tx_byte(0x00);

tx_byte(0x07); //Send Command

//------------

start_bit();

tx_byte(0x01);

bit_out=0;

DataL=rx_byte();

bit_out=0;

DataH=rx_byte();

bit_out=1;

Pecreg=rx_byte();

stop_bit();

wendu_change = (DataH*256+DataL)*0.02-273.15;

return(wendu_change);

}


eeprom也比较简单。

#include "reg52.h"

#include "eepom.h"


/* ================ 打开 ISP,IAP 功能 ================= */

void ISP_IAP_enable(void)

{

EA = 0; /* 关中断 */

ISP_CONTR = ISP_CONTR & 0x18; /* 0001,1000 */

ISP_CONTR = ISP_CONTR | WaitTime; /* 写入硬件延时 */

ISP_CONTR = ISP_CONTR | 0x80; /* ISPEN=1 */

}

/* =============== 关闭 ISP,IAP 功能 ================== */

void ISP_IAP_disable(void)

{

ISP_CONTR = ISP_CONTR & 0x7f; /* ISPEN = 0 */

ISP_TRIG = 0x00;

EA = 1; /* 开中断 */

}

/* ================ 公用的触发代码 ==================== */

void ISPgoon(void)

{

ISP_IAP_enable(); /* 打开 ISP,IAP 功能 */

ISP_TRIG = 0x46; /* 触发ISP_IAP命令字节1 */

ISP_TRIG = 0xb9; /* 触发ISP_IAP命令字节2 */

_nop_();

}

/* ==================== 字节读 ======================== */

unsigned char byte_read(unsigned int byte_addr)

{

EA = 0;

ISP_ADDRH = (unsigned char)(byte_addr >> 8);/* 地址赋值 */

ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);

ISP_CMD = ISP_CMD & 0xf8; /* 清除低3位 */

ISP_CMD = ISP_CMD | RdCommand; /* 写入读命令 */

ISPgoon(); /* 触发执行 */

ISP_IAP_disable(); /* 关闭ISP,IAP功能 */

EA = 1;

return (ISP_DATA); /* 返回读到的数据 */

}

/* ================== 扇区擦除 ======================== */

void SectorErase(unsigned int sector_addr)

{

unsigned int iSectorAddr;

iSectorAddr = (sector_addr & 0xfe00); /* 取扇区地址 */

ISP_ADDRH = (unsigned char)(iSectorAddr >> 8);

ISP_ADDRL = 0x00;

ISP_CMD = ISP_CMD & 0xf8; /* 清空低3位 */

ISP_CMD = ISP_CMD | EraseCommand; /* 擦除命令3 */

ISPgoon(); /* 触发执行 */

ISP_IAP_disable(); /* 关闭ISP,IAP功能 */

}

/* ==================== 字节写 ======================== */

void byte_write(unsigned int byte_addr, unsigned char original_data)

{

EA = 0;

// SectorErase(byte_addr);

ISP_ADDRH = (unsigned char)(byte_addr >> 8); /* 取地址 */

ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);

ISP_CMD = ISP_CMD & 0xf8; /* 清低3位 */

ISP_CMD = ISP_CMD | PrgCommand; /* 写命令2 */

ISP_DATA = original_data; /* 写入数据准备 */

ISPgoon(); /* 触发执行 */

ISP_IAP_disable(); /* 关闭IAP功能 */

EA =1;

}


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
MSP430F5529 上手小例程2