51單片機語音播報模塊:
以8位STC89C52單片機為控制核心,利用DHT11、GY-30、MQ-2傳感器實時采集溫濕度、光照強度、氣體濃度等環境參數,用戶可以通過LCD1602液晶查看當前環境參數數據。NY3P035芯片控制語音播報,加入藍牙通信接口電路,手機連接藍牙模塊,下位機和上位機進行通信,手機藍牙串口界面可以接收當前的環境數據,手機發命令給單片機,可控制語音的播報。
實物圖:
IMG_20160525_213316_HDR.jpg (3.76 MB, 下載次數: 52)
下載附件
2020-8-13 18:32 上傳
IMG_20160525_214408_HDR.jpg (4.65 MB, 下載次數: 59)
下載附件
2020-8-13 18:32 上傳
單片機源程序如下:
- #include <reg51.h>
- #include <intrins.h>
- #include <uart.h>
- #define uchar unsigned char
- #define uint unsigned int
- uchar write_add[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80}; //數據的地址
- uchar read_add[7]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};
- uchar code table3[]=" "; //清屏內容
- sbit rs=P1^0; //LCD1602
- sbit rw=P1^1; //LCD1602
- sbit e=P2^5; //LCD1602
- sbit SCL=P1^5; //IIC時鐘引腳定義 //BH1750fvi光照強度傳感器
- sbit SDA=P1^6; //IIC數據引腳定義
- sbit cs=P3^6; //TLC2543
- sbit clk=P2^7;
- sbit sdi=P2^6;
- sbit sdo=P2^4;
- sbit flag=P3^4;
- sbit bit7=B^7;
- sbit Data =P1^3; //DHT11
- int temperature; //全局變量 溫度
- int Count; //T0中斷次數
- sbit KEY1=P3^5; //播放語音
- //sbit KEY2=P3^6; //暫停
- sbit BUSY=P2^0; //語音芯片
- sbit DATA=P2^1; //語音芯片
- sbit RST=P2^2; //語音芯片
- void delay_ms( uint ms);
- void delay1();
- void ADC_read( uint ch);
- void volt_result();
- void disp_volt(uint value);
- uchar y;
- uchar first,second,third,forth;
- bit date;
- uint adval=0;
- uint volt=0;
- uchar temppp=0;
- uchar flag_table[3]={0};
- uchar flagx;
- bit SetFlag=0; //更新時間標志位
- uchar shi,ge;
- uchar temp,tempp; //八個bit數據位的變量
- uchar comdata; //總線接收到的數據
- uchar T_data_H_temp,T_data_L_temp,RH_data_H_temp,RH_data_L_temp,checkdata_temp,temp_data;
- uchar T_data_H,T_data_L,RH_data_H,RH_data_L,checkdata;
- void music(uchar k);
- uchar uart_wendu_shi,uart_wendu_ge,uart_shidu_shi,uart_shidu_ge;
- uchar uart_sun_shi,uart_sun_ge;
- #define SlaveAddress 0x46 //定義器件在IIC總線中的從地址,根據ALT ADDRESS地址引腳不同修改
- //ALT ADDRESS引腳接地時地址為0x46,接電源時地址為0xB8
- typedef unsigned char BYTE;
- typedef unsigned short WORD;
- BYTE BUF[8]; //接收數據緩存區
- uchar gee,shii,bai,qian,wan; //顯示變量
- int dis_data;
- void delay_nms(unsigned int k);
- void Init_BH1750(void);
- void WriteDataLCM(uchar dataW);
- void WriteCommandLCM(uchar CMD,uchar Attribc);
- void DisplayOneChar(uchar X,uchar Y,uchar DData);
- void conversion(uint temp_data);
- void Single_Write_BH1750(uchar REG_Address); //單個寫入數據
- uchar Single_Read_BH1750(uchar REG_Address); //單個讀取內部寄存器數據
- void Multiple_Read_BH1750(); //連續的讀取內部寄存器數據
- //------------------------------------
- void Delay5us();
- void Delay5ms();
- void BH1750_Start(); //起始信號
- void BH1750_Stop(); //停止信號
- void BH1750_SendACK(bit ack); //應答ACK
- bit BH1750_RecvACK(); //讀ack
- void BH1750_SendByte(BYTE dat); //IIC單個字節寫
- BYTE BH1750_RecvByte(); //IIC單個字節讀
- /*********************************************************************************************************************/
- void delay1(uint z) //延時1ms函數
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=80;y>0;y--);
- }
- /***********************************
- 延時 BH1750
- ************************************/
- /**************************************
- 延時5微秒(STC90C52RC@12M)
- 不同的工作環境,需要調整此函數,注意時鐘過快時需要修改
- 當改用1T的MCU時,請調整此延時函數
- **************************************/
- void Delay5us()
- {
- _nop_();_nop_();_nop_();_nop_();
- _nop_();_nop_();_nop_();_nop_();
- _nop_();_nop_();_nop_();_nop_();
- _nop_();_nop_();_nop_();_nop_();
- }
- /**************************************
- 延時5毫秒(STC90C52RC@12M)
- 不同的工作環境,需要調整此函數
- 當改用1T的MCU時,請調整此延時函數
- **************************************/
- void Delay5ms()
- {
- WORD n = 560;
- while (n--);
- }
- //毫秒延時**************************
- void delay_nms(unsigned int k)
- {
- unsigned int i,j;
- for(i=0;i<k;i++)
- {
- for(j=0;j<121;j++)
- {;}}
- }
- /*******************************/
- void write_com(uchar com) //寫指令函數
- {
- rw=0;
- delay1(5);
- rs=0;
- delay1(5);
- e=1;
- delay1(5);
- P0=com;
- delay1(5);
- e=0;
- delay1(5);
- }
- void write_date(uchar date) //寫數據函數
- {
- rw=0;
- delay1(5);
- rs=1;
- delay1(5);
- e=1;
- delay1(5);
- P0=date;
- delay1(5);
- e=0;
- delay1(5);
- }
- void LCDinit() //初始化函數
- {
- uchar num;
- e=0; // 時序表e初始為0
- write_com(0x38); //設置16*2顯示,5*7點陣,8位數據接口
- write_com(0x0c); //設置光標
- write_com(0x06); //光標自動加1,光標輸入方式
- write_com(0x01); //清屏
- write_com(0x80); //設置初始顯示位置
- for(num=0;num<16;num++)
- {
- // write_date(table1[num]);
- delay1(5);
- }
- write_com(0x80+0x40);
- for(num=0;num<16;num++)
- {
- // write_date(table2[num]);
- delay1(5);
- }
- }
- void SetTime_dispaly(uchar add,uchar dat) //第一個:參數的地址,第二個:參數的內容
- {
- shi=dat/10; //把溫度的十位提取出來
- ge=dat%10; //把溫度的個位提取出來
- write_com(add); //要寫的地址
- write_date(0x30+shi); //十位的內容 1602字符庫
- write_date(0x30+ge); //個位的內容 1602字符庫
- }
- void Date_dispaly(uchar add,uchar dat) //第一個:參數的地址,第二個:參數的內容
- {
- // uchar shi,ge;
- shi=dat/16; //把溫度的十位提取出來
- ge=dat%16; //把溫度的個位提取出來
- write_com(add); //要寫的地址
- write_date(0x30+shi); //十位的內容 1602字符庫
- write_date(0x30+ge); //個位的內容 1602字符庫
-
- }
- void LCD_Clean(uchar i) //液晶屏清除顯示
- {
- uchar num;
- if(i==1)
- {
- write_com(0x80); //設置初始顯示位置
- for(num=0;num<16;num++) //顯示第一行內容
- {
- write_date(table3[num]);
- delay1(1);
- }
- }
- if(i==2)
- {
- write_com(0x80+0x40);
- for(num=0;num<16;num++) //顯示第二行內容
- {
- write_date(table3[num]);
- delay1(1);
- }
- }
- }
- void LCD_Display_String(unsigned char line,unsigned char *string)
- { //液晶屏顯示內容,把要顯示的內容寫到對應的位置
- unsigned char i;
- unsigned char address=0;
- if(line==1)
- {
- address=0x80; //0X80是第1行的第1個位置 ,0x81第2位
- }
- else if(line==2)
- {
- address=0x80+0x40; //0X80+0x40是第2行的第1個位置 ,0X80+0x40+1是第2行第2位
- }
-
- for(i=0;i<16;i++)
- {
- write_com(address);
- write_date(string[i]);
- address++;
- }
- }
- /***********************************************語音*****************************************************************/
- void music(uchar k)
- {
- RST=1;
- delay(2);
- RST=0; //發送復位脈沖,即起始信號
- delay(2);
- while(k>0) //發送K個脈沖,播放第K段內容
- {
- DATA=1;
- delay(1);
- DATA=0;
- delay(1);
- k--;
- }
- }
- void Voice(void)
- {
-
- if(KEY1==0) //按鍵按下,播放溫濕度。
- {
- delay_nms(10);
- if(KEY1==0)
- {
- music(23); //你好
- while(!BUSY);
- delay(1000); //中間間隔約1s
- // music(24); //我是語音播報環境測試儀
- // while(!BUSY);
- // delay(500); //中間間隔約0.5s
- music(19); //播放“現在溫度是
- while(!BUSY); //等待播完
- if(T_data_H/10==1) //溫度大于10小于20
- {
- music(12); //播放“十”
- while(!BUSY); //等待播完
- }
- if(T_data_H/10>1) //溫度大于20
- {
- music(T_data_H/10+2); //播放“高位”
- while(!BUSY); //等待播完
- music(12); //播放“十”
- while(!BUSY); //等待播完
- }
- if((T_data_H%10)!=0) //低位不等于0
- {
- music(T_data_H%10+2); //播放“低位”
- while(!BUSY); //等待播完
- }
- if(T_data_H==0) //溫度等于0
- {
- music(1); //播放“低位”
- while(!BUSY); //等待播完
- }
- music(18); //播放“度”
- while(!BUSY); //等待播完
- delay(1000); //中間間隔約1s
- music(20); //播放“現在濕度是”
- while(!BUSY); //等待播完
- music(17); //播放“百分之”
- while(!BUSY); //等待播完
- if(RH_data_H/10==1) //濕度大于10小于20
- {
- music(12); //播放“十”
- while(!BUSY); //等待播完
- }
- if(RH_data_H/10>1) //濕度大于20
- {
- music(RH_data_H/10+2); //播放“高位”
- while(!BUSY); //等待播完
- music(12); //播放“十”
- while(!BUSY); //等待播完
- }
- if((RH_data_H%10)!=0) //低位不等于0
- {
- music(RH_data_H%10+2); //播放“低位”
- while(!BUSY); //等待播完
- }
- if(RH_data_H==0) //濕度等于0
- {
- music(2); //播放“低位”
- while(!BUSY); //等待播完
- }
- delay(1000); //間隔1S
- music(21); //光照強度是
- while(!BUSY);
- if(tempp/10==1) //光照強度大于10小于20
- {
- music(12); //播放“十”
- while(!BUSY); //等待播完
- }
- if(tempp/10>1) //光照強度大于20
- {
- music(tempp/10+2); //播放“高位”
- while(!BUSY); //等待播完
- music(12); //播放“十”
- while(!BUSY); //等待播完
- }
- if((tempp%10)!=0) //低位不等于0
- {
- music(tempp%10+2); //播放“低位”
- while(!BUSY); //等待播完
- }
- if(tempp==0) //光照強度等于0
- {
- music(2); //播放“低位”
- while(!BUSY); //等待播完
- }
-
- delay(1000);
- music(22);
- while(!BUSY);
- music(17);
- while(!BUSY);
- if(volt/10==1) //煙霧濃度大于10小于20
- {
- music(12); //播放“十”
- while(!BUSY); //等待播完
- }
- if(volt/10>1) //煙霧濃度大于20
- {
- music(volt/10+2); //播放“高位”
- while(!BUSY); //等待播完
- music(12); //播放“十”
- while(!BUSY); //等待播完
- }
- if((volt%10)!=0) //低位不等于0
- {
- music(volt%10+2); //播放“低位”
- while(!BUSY); //等待播完
- }
- if(volt==0) //煙霧濃度等于0
- {
- music(2); //播放“低位”
- while(!BUSY); //等待播完
- }
-
- }
- }
- }
- /*******************************溫濕度DHT11*************************************************/
- void Delay_DHT(uint j)
- {
- uchar i;
- for(;j>0;j--)
- {
- for(i=0;i<27;i++);
- }
- }
- void Delay_10us(void) //使用12M晶振的時間剛好為10us
- {
- uchar i;
- i--;
- i--;
- i--;
- i--;
- i--;
- i--;
- }
- void COM(void)
- {
- uchar i;
- for(i=0;i<8;i++)
- {
- while(!Data);
- Delay_10us();
- Delay_10us();
- Delay_10us();
- Delay_10us();
- Delay_10us();
- temp=0;
- if(Data) //判斷數據位是0還是1,發出低電平數據開始信號后,數據拉高,高電平的時間決定數據位為1或者0,
- temp=1; //當高電平時間小于30us時為0,大于30us且小于70us為1,大于70us則進入下一個bit
- while(Data); //等待數據接受完
- comdata<<=1; //左移一位
- comdata|=temp;//將該位賦給comdata
- }
- }
- void RH(void)
- {
- //主機拉低18ms
- Data=0;
- Delay_DHT(180);
- Data=1;
- //總線由上拉電阻拉高 主機延時20us
- Delay_10us();
- Delay_10us();
- Delay_10us();
- Delay_10us();
- //主機設為輸入 判斷從機響應信號
- Data=1;
- //判斷從機是否有低電平響應信號 如不響應則跳出,響應則向下運行
- if(!Data) //T !
- {
- //判斷從機是否發出 80us 的低電平響應信號是否結束
- while(!Data);
- //判斷從機是否發出 80us 的高電平,如發出則進入數據接收狀態
- while(Data);
- //數據接收狀態
- //部分用于以后擴展 , 現讀出為零 . 操作流程如下 :
- //一次完整的數據傳輸為 40bit, 高位先出。
- //數據格式 :8bit 濕度整數數據 +8bit 濕度小數數據
- COM(); //+8bi 溫度整數數據 +8bit 溫度小數數據
- RH_data_H_temp=comdata;
- COM();
- RH_data_L_temp=comdata;
- COM();
- T_data_H_temp=comdata;
- COM();
- T_data_L_temp=comdata;
- COM();
- checkdata_temp=comdata;
- Data=1; //總線拉高,進入空閑模式
-
- temp=(T_data_H_temp+T_data_L_temp+RH_data_H_temp+RH_data_L_temp);
- if(temp==checkdata_temp) //數據校驗
- {
- RH_data_H=RH_data_H_temp;
- RH_data_L=RH_data_L_temp;
- T_data_H=T_data_H_temp; //溫濕度的分辨率都為1,小數部分都是0
- T_data_L=T_data_L_temp;
- checkdata=checkdata_temp;
- }
- }
- }
- /*********************************************************************************************************************/
- void Timer_init(void)
- {
- TMOD=0x11; //設置定時器0為工作方式1
- TH0=(65536-50000)/256; //50MS定時
- TL0=(65536-50000)%256;
- EA=1; //開定時器T0的中斷 總中斷
- ET0=1; //允許T0中斷
- TR0=1; //開啟定時器
- }
- /************************************************************************
- 光照強度BH1750
- *************************************************************************/
-
- void SetBH1750_dispaly(uchar addd,uchar temp_data) //第一個:參數的地址,第二個:參數的內容
- {
- uchar wan,qian,bai,shii,gee;
- wan=temp_data/10000;
- temp_data=temp_data%10000;
- qian=temp_data/1000%10;
- temp_data=temp_data%1000;
- bai=temp_data/100%10;
- temp_data=temp_data%100;
- shii=temp_data/10%10;
- temp_data=temp_data%10;
- gee=temp_data/1%10;
- write_com(addd);
- write_date(0x30+wan);
- write_date(0x30+qian);
- write_date(0x30+bai);
- write_date(0x30+shii);
- write_date(0x30+gee);
-
- }
- /**************************************
- 起始信號
- **************************************/
- void BH1750_Start()
- {
- SDA = 1; //拉高數據線
- SCL = 1; //拉高時鐘線
- Delay5us(); //延時
- SDA = 0; //產生下降沿
- Delay5us(); //延時
- SCL = 0; //拉低時鐘線
- }
- /**************************************
- 停止信號
- **************************************/
- void BH1750_Stop()
- {
- SDA = 0; //拉低數據線
- SCL = 1; //拉高時鐘線
- Delay5us(); //延時
- SDA = 1; //產生上升沿
- Delay5us(); //延時
- }
- /**************************************
- 發送應答信號
- 入口參數:ack (0:ACK 1:NAK)
- **************************************/
- void BH1750_SendACK(bit ack)
- {
- SDA = ack; //寫應答信號
- SCL = 1; //拉高時鐘線
- Delay5us(); //延時
- SCL = 0; //拉低時鐘線
- Delay5us(); //延時
- }
- /**************************************
- 接收應答信號
- **************************************/
- bit BH1750_RecvACK()
- {
- SCL = 1; //拉高時鐘線
- Delay5us(); //延時
- CY = SDA; //讀應答信號
- SCL = 0; //拉低時鐘線
- Delay5us(); //延時
- return CY;
- }
- /**************************************
- 向IIC總線發送一個字節數據
- **************************************/
- void BH1750_SendByte(BYTE dat)
- {
- BYTE i;
- for (i=0; i<8; i++) //8位計數器
- {
- dat <<= 1; //移出數據的最高位
- SDA = CY; //送數據口
- SCL = 1; //拉高時鐘線
- Delay5us(); //延時
- SCL = 0; //拉低時鐘線
- Delay5us(); //延時
- }
- BH1750_RecvACK();
- }
- /**************************************
- 從IIC總線接收一個字節數據
- **************************************/
- BYTE BH1750_RecvByte()
- {
- BYTE i;
- BYTE dat = 0;
- SDA = 1; //使能內部上拉,準備讀取數據,
- for (i=0; i<8; i++) //8位計數器
- {
- dat <<= 1;
- SCL = 1; //拉高時鐘線
- Delay5us(); //延時
- dat |= SDA; //讀數據
- SCL = 0; //拉低時鐘線
- Delay5us(); //延時
- }
- return dat;
- }
- void Single_Write_BH1750(uchar REG_Address)
- {
- BH1750_Start(); //起始信號
- BH1750_SendByte(SlaveAddress); //發送設備地址+寫信號
- BH1750_SendByte(REG_Address); //內部寄存器地址,
- // BH1750_SendByte(REG_data); //內部寄存器數據,
- BH1750_Stop(); //發送停止信號
- }
- //*********************************************************
- //
- //連續讀出BH1750內部數據
- //
- //*********************************************************
- void Multiple_read_BH1750(void)
- { uchar i;
- BH1750_Start(); //起始信號
- BH1750_SendByte(SlaveAddress+1); //發送設備地址+讀信號
-
- for (i=0; i<3; i++) //連續讀取2個地址數據,存儲中BUF
- {
- BUF[i] = BH1750_RecvByte(); //BUF[0]存儲0x32地址中的數據
- if (i == 3)
- {
- BH1750_SendACK(1); //最后一個數據需要回NOACK
- }
- else
- {
- BH1750_SendACK(0); //回應ACK
- }
- }
- BH1750_Stop(); //停止信號
- Delay5ms(); //加延時
- }
- //初始化BH1750,根據需要請參考pdf進行修改****
- void Init_BH1750()
- {
- Single_Write_BH1750(0x01);
- }
- //2543
- void ADC_read( uint ch)
- {
- uchar i;
- sdo=1;
- clk=0;
- cs=1;
- delay_nms(1);
- cs=0;
- B=ch;
- for(i=8;i>0;i--)
- {
- date=sdo;
- sdi=bit7;
- clk=1;
- B=B<<1;
- clk=0;
- temppp=temppp<<1;
- if(date==1)
- {temppp++;}
- }
- adval=temppp;
- adval=adval<<4;
- for(i=4;i>0;i--)
- {
- date=sdo;
- temppp=temppp<<1;
- if(date==1)
- {temppp++;}
- clk=1;
- clk=0;
- }
- cs=1;
- adval=adval+temppp;
- volt=adval;
- }
- void ADC_dispaly(uchar adddd,uchar value)
- {
- first=(uchar)(value/1000);
- delay_nms(1);
- second=(uchar)(value%1000/100);
- delay_nms(1);
- third=(uchar)(value%100/10);
- delay_nms(1);
- forth=(uchar)(value%10);
- delay_nms(1);
- write_com(adddd);
- write_date(0x30+first);
- write_date(0x30+second);
- write_date(0x30+third);
- write_date(0x30+forth);
-
- if(first>4)
- {flagx=0;}
- else
- {flagx=1;}
- flag_table[0]=flag_table[1] ;
- flag_table[1]=flag_table[2] ;
- flag_table[2]=flagx ;
- }
- void main()
- {
- delay_nms(100); //延時100ms
- BUSY=0; //語音芯片
- DATA=0; //語音芯片
- RST=0;
- LCDinit(); //液晶初始化
- Init_BH1750(); //初始化BH1750
- Timer_init();
- init(); //串口初始化
-
- while(1)
- {
-
- if(Count>=10) //每0.5秒采一次溫濕度,避免顯示錯亂,10*50ms=0.5s
- {
- RH(); //讀取溫濕度
- uart_wendu_shi=T_data_H/10;
- uart_wendu_ge=T_data_H%10;
- uart_shidu_shi=RH_data_H/10;
- uart_shidu_ge=RH_data_H%10;
-
-
- SetTime_dispaly(0x80+2,T_data_H); //顯示溫度
- SetTime_dispaly(0x80+0x40+2,RH_data_H); //顯示濕度
-
-
- write_com(0x80);
- write_date(0x54); //寫 T 溫度
- write_com(0x80+0x40);
- write_date(0x52); //寫 R 濕度
- write_com(0x80+6);
- write_date(0x53); //寫 S 光照強度
- write_com(0x80+0x40+6);
- write_date(0x57); //寫 W 氣體煙霧
-
- write_com(0x80+4);
- write_date(0x43); //寫 C
- write_com(0x80+0x40+4);
- write_date(0x25); //寫 %
- write_com(0x80+13);
- write_date(0x4C); //寫 L
- write_com(0x80+14);
- write_date(0x78); //寫 x
- write_com(0x80+0x40+12);
- write_date(0x25); //寫 %
-
- Count=0; //清零
-
-
- Single_Write_BH1750(0x01); // power on
- Single_Write_BH1750(0x10); // H- resolution mode
- delay_nms(180); //延時180ms
- Multiple_Read_BH1750(); //連續讀出數據,存儲在BUF中
- dis_data=BUF[0];
- dis_data=(dis_data<<8)+BUF[1]; //合成數據,即光照數據
- tempp=(float)dis_data/1.2;
-
- SetBH1750_dispaly(0x80+8,tempp);
- uart_sun_shi=tempp/10; //串口
- uart_sun_ge=tempp%10; //
-
- if(K2==0)
- {
- delay_nms(20);
- if(!K2)
- {
- while(!K2);
- send(uart_wendu_shi,uart_wendu_ge,uart_shidu_shi,uart_shidu_ge,uart_sun_shi,uart_sun_ge);
- }
- }
- ADC_read();
- volt=volt*5000/4095;
- ADC_dispaly(0x80+0x40+8,volt);
-
- y=SBUF;
- SetFlag=1;
- switch(y)
- {
- case 0x01 :KEY1=0;break;
-
- }
-
- Voice();
- }
- }
- }
- void Timer0() interrupt 1 //定時器T0中斷函數
- {
- TH0=(65536-50000)/256; //賦初值=50ms
- TL0=(65536-50000)%256; //TH0=3C,TL0=B0
- Count++; //每中斷一次,Count加一,計數20次,表示1s的時間到
- }
復制代碼
APP:無
上位機:無
單片機程序和原理圖下載(僅供參考):
51單片機語音播報.7z
(7.55 MB, 下載次數: 99)
2020-8-19 16:38 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|