找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 749|回复: 6
打印 上一主题 下一主题
收起左侧

基于STM32婴儿床检测控制系统及源程序

[复制链接]
跳转到指定楼层
楼主
一、系统方案
1、本设计采用STM32单片机作为主控器。
2、DHT11检测湿度,液晶OLED显示,声音检测声音,有声音或尿床,蜂鸣器报警。
3、手机APP可以控制音乐播放。

二、硬件设计
原理图如下:
三、单片机软件设计
1、首先是系统初始化
void LED_Init(void)
{

GPIO_InitTypeDef  GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);         //使能PA,PD端口时钟

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;                                 //LED0-->PA.8 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                 //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure);                                         //根据设定参数初始化GPIOA.8
GPIO_SetBits(GPIOB,GPIO_Pin_2);                                                 //PA.8 输出高

}

2、液晶显示程序
/************************************************************************************
*  Copyright (c), 2014, HelTec Automatic Technology co.,LTD.
*            All rights reserved.
*


*
* File name: OLED_I2C.c
* Project  : HelTec.uvprij
* Processor: STM32F103C8T6
* Compiler : MDK fo ARM
*
* Author : 小林
* Version: 1.00
* Date   : 2014.4.8
* Modification: none
*
* Description:128*64点阵的OLED显示屏驱动文件,仅适用于惠特自动化的SD1306驱动IIC通信方式显示屏
*
* Others: none;
*
* Function List:
*        1. void I2C_Configuration(void) -- 配置CPU的硬件I2C
* 2. void I2C_WriteByte(uint8_t addr,uint8_t data) -- 向寄存器地址写一个byte的数据
* 3. void WriteCmd(unsigned char I2C_Command) -- 写命令
* 4. void WriteDat(unsigned char I2C_Data) -- 写数据
* 5. void OLED_Init(void) -- OLED屏初始化
* 6. void OLED_SetPos(unsigned char x, unsigned char y) -- 设置起始点坐标
* 7. void OLED_Fill(unsigned char fill_Data) -- 全屏填充
* 8. void OLED_CLS(void) -- 清屏
* 9. void OLED_ON(void) -- 唤醒
* 10. void OLED_OFF(void) -- 睡眠
* 11. void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize) -- 显示字符串(字体大小有6*8和8*16两种)
* 12. void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N) -- 显示中文(中文需要先取模,然后放到codetab.h中)
* 13. void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]) -- BMP图片
*
* History: none;
*
*************************************************************************************/

#include "OLED_I2C.h"
#include "delay.h"
#include "codetab.h"

void I2C_Configuration(void)
{
        I2C_InitTypeDef  I2C_InitStructure;
        GPIO_InitTypeDef  GPIO_InitStructure;

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

        /*STM32F103C8T6芯片的硬件I2C: PB6 -- SCL; PB7 -- SDA */
        GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//I2C必须开漏输出
        GPIO_Init(GPIOB, &GPIO_InitStructure);

        I2C_DeInit(I2C1);//使用I2C1
        I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
        I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
        I2C_InitStructure.I2C_OwnAddress1 = 0x30;//主机的I2C地址,随便写的
        I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
        I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
        I2C_InitStructure.I2C_ClockSpeed = 400000;//400K

        I2C_Cmd(I2C1, ENABLE);
        I2C_Init(I2C1, &I2C_InitStructure);
}

void I2C_WriteByte(uint8_t addr,uint8_t data)
{
  while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));

        I2C_GenerateSTART(I2C1, ENABLE);//开启I2C1
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));/*EV5,主模式*/

        I2C_Send7bitAddress(I2C1, OLED_ADDRESS, I2C_Direction_Transmitter);//器件地址 -- 默认0x78
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

        I2C_SendData(I2C1, addr);//寄存器地址
        while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

        I2C_SendData(I2C1, data);//发送数据
        while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

        I2C_GenerateSTOP(I2C1, ENABLE);//关闭I2C1总线
}

void WriteCmd(unsigned char I2C_Command)//写命令
{
        I2C_WriteByte(0x00, I2C_Command);
}

void WriteDat(unsigned char I2C_Data)//写数据
{
        I2C_WriteByte(0x40, I2C_Data);
}

void OLED_Init(void)
{
delay_ms(100); //这里的延时很重要

        WriteCmd(0xAE); //display off
        WriteCmd(0x20);        //Set Memory Addressing Mode        
        WriteCmd(0x10);        //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
        WriteCmd(0xb0);        //Set Page Start Address for Page Addressing Mode,0-7
        WriteCmd(0xc8);        //Set COM Output Scan Direction
        WriteCmd(0x00); //---set low column address
        WriteCmd(0x10); //---set high column address
        WriteCmd(0x40); //--set start line address
        WriteCmd(0x81); //--set contrast control register
        WriteCmd(0xff); //亮度调节 0x00~0xff
        WriteCmd(0xa1); //--set segment re-map 0 to 127
        WriteCmd(0xa6); //--set normal display
        WriteCmd(0xa8); //--set multiplex ratio(1 to 64)
        WriteCmd(0x3F); //
        WriteCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
        WriteCmd(0xd3); //-set display offset
        WriteCmd(0x00); //-not offset
        WriteCmd(0xd5); //--set display clock divide ratio/oscillator frequency
        WriteCmd(0xf0); //--set divide ratio
        WriteCmd(0xd9); //--set pre-charge period
        WriteCmd(0x22); //
        WriteCmd(0xda); //--set com pins hardware configuration
        WriteCmd(0x12);
        WriteCmd(0xdb); //--set vcomh
        WriteCmd(0x20); //0x20,0.77xVcc
        WriteCmd(0x8d); //--set DC-DC enable
        WriteCmd(0x14); //
        WriteCmd(0xaf); //--turn on oled panel
}

void OLED_SetPos(unsigned char x, unsigned char y) //设置起始点坐标
{
        WriteCmd(0xb0+y);
        WriteCmd(((x&0xf0)>>4)|0x10);
        WriteCmd((x&0x0f)|0x01);
}

void OLED_Fill(unsigned char fill_Data)//全屏填充
{
        unsigned char m,n;
        for(m=0;m<8;m++)
        {
                WriteCmd(0xb0+m);                //page0-page1
                WriteCmd(0x00);                //low column start address
                WriteCmd(0x10);                //high column start address
                for(n=0;n<128;n++)
                        {
                                WriteDat(fill_Data);
                        }
        }
}

void OLED_CLS(void)//清屏
{
        OLED_Fill(0x00);
}

//--------------------------------------------------------------
// Prototype      : void OLED_ON(void)
// Calls          :
// Parameters     : none
// Description    : 将OLED从休眠中唤醒
//--------------------------------------------------------------
void OLED_ON(void)
{
        WriteCmd(0X8D);  //设置电荷泵
        WriteCmd(0X14);  //开启电荷泵
        WriteCmd(0XAF);  //OLED唤醒
}

//--------------------------------------------------------------
// Prototype      : void OLED_OFF(void)
// Calls          :
// Parameters     : none
// Description    : 让OLED休眠 -- 休眠模式下,OLED功耗不到10uA
//--------------------------------------------------------------
void OLED_OFF(void)
{
        WriteCmd(0X8D);  //设置电荷泵
        WriteCmd(0X10);  //关闭电荷泵
        WriteCmd(0XAE);  //OLED休眠
}

//--------------------------------------------------------------
// Prototype      : void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
// Calls          :
// Parameters     : x,y -- 起始点坐标(x:0~127, y:0~7); ch[] -- 要显示的字符串; TextSize -- 字符大小(1:6*8 ; 2:8*16)
// Description    : 显示codetab.h中的ASCII字符,有6*8和8*16可选择
//--------------------------------------------------------------
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
{
        unsigned char c = 0,i = 0,j = 0;
        switch(TextSize)
        {
                case 1:
                {
                        while(ch[j] != '\0')
                        {
                                c = ch[j] - 32;
                                if(x > 126)
                                {
                                        x = 0;
                                        y++;
                                }
                                OLED_SetPos(x,y);
                                for(i=0;i<6;i++)
                                        WriteDat(F6x8[c][ i]);
                                x += 6;
                                j++;
                        }
                }break;
                case 2:
                {
                        while(ch[j] != '\0')
                        {
                                c = ch[j] - 32;
                                if(x > 120)
                                {
                                        x = 0;
                                        y++;
                                }
                                OLED_SetPos(x,y);
                                for(i=0;i<8;i++)
                                        WriteDat(F8X16[c*16+i]);
                                OLED_SetPos(x,y+1);
                                for(i=0;i<8;i++)
                                        WriteDat(F8X16[c*16+i+8]);
                                x += 8;
                                j++;
                        }
                }break;
        }
}

//--------------------------------------------------------------
// Prototype      : void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
// Calls          :
// Parameters     : x,y -- 起始点坐标(x:0~127, y:0~7); N:汉字在codetab.h中的索引
// Description    : 显示codetab.h中的汉字,16*16点阵
//--------------------------------------------------------------
void OLED_ShowCN(unsigned char x, unsigned char y, unsigned char N)
{
        unsigned char wm=0;
        unsigned int  adder=32*N;
        OLED_SetPos(x , y);
        for(wm = 0;wm < 16;wm++)
        {
                WriteDat(F16x16[adder]);
                adder += 1;
        }
        OLED_SetPos(x,y + 1);
        for(wm = 0;wm < 16;wm++)
        {
                WriteDat(F16x16[adder]);
                adder += 1;
        }
}

//--------------------------------------------------------------
// Prototype      : void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]);
// Calls          :
// Parameters     : x0,y0 -- 起始点坐标(x0:0~127, y0:0~7); x1,y1 -- 起点对角线(结束点)的坐标(x1:1~128,y1:1~8)
// Description    : 显示BMP位图
//--------------------------------------------------------------
void OLED_DrawBMP(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[])
{
        unsigned int j=0;
        unsigned char x,y;

  if(y1%8==0)
                y = y1/8;
  else
                y = y1/8 + 1;
        for(y=y0;y<y1;y++)
        {
                OLED_SetPos(x0,y);
    for(x=x0;x<x1;x++)
                {
                        WriteDat(BMP[j++]);
                }
        }
}

3、按键程序
void KEY_Init(void)
{

        GPIO_InitTypeDef GPIO_InitStructure;

         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能PORTA,PORTC时钟

        GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);//关闭jtag,使能SWD,可以用SWD模式调试

        GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_1;//PA15
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
         GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA15

        GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_2;//PC5
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
         GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOC5

        GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;//PA0
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0设置成输入,默认下拉         
        GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.0

}
//按键处理函数
//返回按键值
//mode:0,不支持连续按;1,支持连续按;
//返回值:
//0,没有任何按键按下
//KEY0_PRES,KEY0按下
//KEY1_PRES,KEY1按下
//WKUP_PRES,WK_UP按下
//注意此函数有响应优先级,KEY0>KEY1>WK_UP!!
u8 KEY_Scan(u8 mode)
{         
        static u8 key_up=1;//按键按松开标志
        if(mode)key_up=1;  //支持连按                  
        if(key_up&&(KEY0==0||KEY1==0||WK_UP==1))
        {
                delay_ms(10);//去抖动
                key_up=0;
                if(KEY0==0)return KEY0_PRES;
                else if(KEY1==0)return KEY1_PRES;
                else if(WK_UP==1)return WKUP_PRES;
        }else if(KEY0==1&&KEY1==1&&WK_UP==0)key_up=1;              
        return 0;// 无按键按下
}
4、核心算法程序
int main(void)
{               

         u8 t=0,num=0,cnt;                           
        u8 temperature;              
        u8 humidity;  
         u8 hh=60;
        delay_init();                     //延时函数初始化         
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
        uart_init(9600);         //串口初始化为9600

         I2C_Configuration();
        OLED_Init();
                  KEY_Init();                  //初始化与按键连接的硬件接口
                        OLED_Fill(0xFF);//全屏点亮
                delay_ms(2);

        OLED_Fill(0x00);//全屏灭
        delay_ms(2);
                  while(DHT11_Init())        //DHT11初始化        
        {

        }        
          LED_Init();
        HW_Init();
        while(1){




                if(Res=='1')        
                {

LED0=0;

                }
                if(Res=='2')
                {
        LED0=1;
                }

                        num=KEY_Scan(0);                //得到键值
                switch(num)
                {                                 
                        case KEY0_PRES:
                          if(hh>=1) hh--;
                                break;
                                break;

                        case KEY1_PRES:


                        case WKUP_PRES:                                
                     hh++;
                           if(hh>100) hh=99;

                                break;

                }  






                OLED_ShowStr(0,0,"TEMP:",2);                                //测试8*16字符
                OLED_ShowStr(0,2,"HUMI:",2);                                //测试8*16字符
                OLED_ShowStr(0,4,"Alar:",2);                                //测试8*16字符
                if(hw==0)
                {
                OLED_ShowStr(80,4,"sound",2);                                //测试8*16字符
                        printf("sound\n");
                }
                else

                {
                        OLED_ShowStr(80,4,"     ",2);                                //测试8*16字符
                }
                if(humidity>=hh)
                {
                                OLED_ShowStr(0,6,"bed-wetting",2);                                //测试8*16字符
                           printf("bed-wetting\n");
                }
                else
                                 OLED_ShowStr(0,6,"           ",2);                                //测试8*16字符
                delay_ms(2);
                if(t%5==0)//每100ms读取一次
                {                                                                          
                        DHT11_Read_Data(&temperature,&humidity);                //读取温湿度值                        
     display(40,0,temperature/10);
                         display(48,0,temperature%10);
                         display(40,2,humidity/10);
                         display(48,2,humidity%10);
                        display(40,4,hh/10);
                         display(48,4,hh%10);

                        printf("TEMP:%d\n",temperature);
                        printf("HUMI:%d\n",humidity);

                        //LCD_ShowNum(60+40,150,temperature,2,16);                //显示温度                           

                        //LCD_ShowNum(60+40,170,humidity,2,16);                        //显示湿度                    
                }                                   
                 delay_ms(10);
                t++;
                if(t==10)
                {
                        t=0;

                }


        //printf("t:%d\n",t);
        //delay_ms(500);
        //t++;
        }
}

四、 proteus仿真设计
Proteus软件是一款应用比较广泛的工具,它可以在没有硬件平台的基础上通过自身的软件仿真出硬件平台的运行情况,这样就可以通过软件仿真来验证我们设计的方案有没有问题,如果有问题,可以重新选择器件,连接器件,直到达到我们设定的目的,避免我们搭建实物的时候,如果当初选择的方案有问题,我们器件都已经焊接好了,再去卸载下去,再去焊接新的方案的器件,测试,这样会浪费人力和物力,也给开发者带来一定困惑,Proteus仿真软件就很好的解决这个问题,我们在设计之初,就使用该软件进行模拟仿真,测试,选择满足我们设计的最优方案。最后根据测试没问题的仿真图纸,焊接实物,调试,最终完成本设计的作品。


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:16255 发表于 2023-11-17 16:23 | 只看该作者
宝宝尿床
     ↓
宝宝哭了↖
      ↓       ↑
检测到了  ↑
      ↓       ↑
蜂鸣器响↗
回复

使用道具 举报

板凳
ID:190577 发表于 2023-11-18 10:38 | 只看该作者
mengsiu 发表于 2023-11-17 16:23
宝宝尿床
     ↓
宝宝哭了↖

对的,没错,还可以手机控制播放音乐
回复

使用道具 举报

地板
ID:914077 发表于 2023-11-19 21:29 | 只看该作者
非常不错
回复

使用道具 举报

5#
ID:914077 发表于 2023-11-19 21:30 | 只看该作者
功率电子保护技术
回复

使用道具 举报

6#
ID:16255 发表于 2023-11-20 21:13 | 只看该作者
mengsiu 发表于 2023-11-17 16:23
宝宝尿床
     ↓
宝宝哭了↖

还有一个问题!
使用DHT11检测宝宝尿床,难道是要把DHT11塞到宝宝纸尿裤里?还是说整台机器塞进去?
回复

使用道具 举报

7#
ID:343102 发表于 2023-11-21 00:08 | 只看该作者
搞这么复杂?
用2个三极管组成音频振荡电路驱动喇叭发声(用1个三极管驱动蜂鸣器发声也行),再用2层纱布缝入2根细铜丝检测水分,控制发声电路就ok了。
至于小孩哭不需要提醒吧?除非是远程。
必须尊重你的探索精神。
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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