发新帖本帖赏金 5.50元(功能说明)我要提问
返回列表
[开源硬件]

DIY多功能12864液晶显示电子台历-设计篇

[复制链接]
楼主: henangongda123
手机看帖
扫描二维码
随时随地手机跟帖
henangongda123|  楼主 | 2018-6-7 10:38 | 显示全部楼层
SHT31模块收到了,不过DS3231写数据操作程序还有点问题,准备先调试好DS3231写操作再调试这个温湿度传感器模块!
SHT31模块.jpg

使用特权

评论回复
henangongda123|  楼主 | 2018-6-7 21:26 | 显示全部楼层
DS3231写时间数据操作调试成功,分享源码如下:
//设置DS3231年、月、日、时、分、秒、星期等数据
/***********************************************************
函数名: DS3231_Write()
功  能: STM8S207 MCU通过硬件I2C通信更改DS3231内年月日时分秒等数据
参  数: data_buff --- 从DS3231读取的多字节数据指针
                          data_len  --- 从DS3231读取的多字节数据长度(7个)
返回值: 无
***********************************************************/
void DS3231_Write(uchar *data_buff,uchar data_len)
{         
        uchar temp;                 //定义一下,读取MCU状态寄存器用
        uchar i;                    //定义一下,供循环使用
        uint time;                  //定义一下,供等待延时用
        //以下程序为I2C通信防锁死操作,非常重要!
        if((PE_IDR&0x04) == 0x00)   //检测总线是否真的忙碌中(忙碌则SCL=1,SDA=0)
        {
                I2C_CR1 &= 0xFE;          //PE=0,禁用硬件I2C模块,准备直接操作MCU端口
                PE_DDR |= 0x02;           //设置SCL端口为输出
                PE_CR1 |= 0x02;           //上拉输出
                for(i=0;i<9;i++)          //SCL端口发出9个时钟脉冲,让从设备DS3231释放总线(恢复SDA=1)
                {
                        PE_ODR &= 0xFD;         //SCL=0;
                        delay_us(50);           //延时(I2C通信频率10KHz)
                  PE_ODR |= 0x02;         //SCL=1
                  delay_us(50);           //延时(I2C通信频率10KHz)
                }
                time = 500;               //变量赋值,准备延迟等待500次
                while(!(PE_IDR&0x04))     //等待数据线SDA=1
                {
                  if(!--time)             //变量自减
                  return;                 //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
          }
                PE_DDR &= 0xFD;           //SCL端口恢复输入方式
                PE_CR1 &= 0xFD;           //浮空输入
                PE_ODR &= 0xFD;           //清零输出寄存器
                I2C_CR1 |= 0x01;          //重新启动硬件I2C模块,接管SCL、SDA端口
                return;                   //退出函数,放弃本次数据写操作
        }
        //以上程序为I2C通信防锁死操作,非常重要!
        //以下程序为STM8S 硬件I2C通信防BUSY锁死操作,非常重要!
        if((I2C_SR3&0x02) == 0x02)  //检测总线是否正确释放空闲中(总线正确释放则I2C_SR3状态寄存器BUSY=0,否则BUSY=1)
        {
                I2C_CR2 |= 0x80;          //I2C_CR2控制寄存器SWRST=1,软件复位硬件I2C模块
          I2C_CR2 &= 0x7F;          //I2C_CR2控制寄存器SWRST=0,软件复位硬件I2C模块结束
                I2C_FREQR = 0x02;         //配置I2C外设时钟2MHz
                I2C_CCRH = 0x00;          //配置I2C为标准模式及速率
                I2C_CCRL = 0x64;          //I2C通信速率半周期=((1/2)*100us=50us,速率=1/100us=10KHz
          I2C_TRISER = 0x03;        //配置I2C上升时间寄存器,1000ns(SCL最大值)/500ns(2MHz周期)+1
                I2C_CR1 |= 0x01;          //启动I2C硬件模块
                return;                   //退出函数,放弃本次数据写操作
        }
        //以上程序为STM8S 硬件I2C通信防BUSY锁死操作,非常重要!
        I2C_CR2 &= 0xFB;            //关闭ACK应答(清零I2C_CR2控制寄存器ACK位,收到一个字节数据或地址后不返回应答)
        time = 500;                 //变量赋值,准备延迟等待500次
        while(I2C_SR3&0x02)         //检测总线是否忙碌中(I2C_SR3状态寄存器BUSY位=1表示总线上有通信/忙碌)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        I2C_CR2 |= 0x01;            //发起始条件(置位I2C_CR2控制寄存器START位)
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x01))      //I2C_SR1状态寄存器SB位=1表示发送成功
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        delay_us(5);                //短暂延时
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
        I2C_DR = 0xD0;              //发送DS3231从设备地址,同时清除I2C_SR1中BFT位(SLAVE ADDRESS,末位R/W=0表示写操作)
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x02))      //I2C_SR1状态寄存器ADDR位=1时表示地址发送结束(主模式)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        delay_us(5);                //短暂延时
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1数值
        temp = I2C_SR3;             //清除状态寄存器I2C_SR1中ADDR标志位(地址已发送结束)
        I2C_DR = 0x00;              //发送DS3231寄存器地址(WORD ADDRESS,从00H到12H)
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x84))      //等待数据发送完毕(I2C_SR1状态寄存器TxE、BTF位为1时,表示发送时数据寄存器为空且数据字节发送完毕)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        while(data_len)             //循环写入多字节数据
        {
                I2C_DR = *data_buff;      //发送一字节数据
          while(!(I2C_SR1&0x84));   //等待数据发送完毕(I2C_SR1状态寄存器TxE、BTF位为1时,表示发送时数据寄存器为空且数据字节发送完毕)
                data_buff++;              //准备写入下一字节数据
                data_len--;
        }
        I2C_CR2 |= 0x02;            //发停止条件(置位I2C_CR2控制寄存器STOP位///必须先清除I2C_SR1状态寄存器BTF位)
}

写操作要比读简单点,另外,写的时候不需要I2C ACK应答,所以要先关闭应答。
DS3231写操作-1.jpg
DS3231写操作-2.jpg

使用特权

评论回复
评论
henangongda123 2018-6-10 15:01 回复TA
@一叶倾城wwq :嗯,谢谢!今天在调试SHT31温湿度传感器。 
一叶倾城wwq 2018-6-9 14:37 回复TA
期待楼主的成品!哈哈 
henangongda123|  楼主 | 2018-6-10 23:11 | 显示全部楼层
今天调试了一天SHT31温湿度传感器,目前温度数值读取、转换正常了,湿度数值读取也正常,转换不知道为什么出了问题,还在解决。
SHT31调试-1.jpg
SHT31调试-2.jpg

使用特权

评论回复
henangongda123|  楼主 | 2018-6-10 23:14 | 显示全部楼层
共享STM8S硬件I2C操作SHT31温湿度传感器代码如下(湿度转换还未OK):/********* SHT31温湿度传感器驱动及相关数据处理操作 **********/
//SHT31读取温湿度数据
/***********************************************************
函数名: SHT31_Read()
功  能: STM8S207 MCU通过硬件I2C通信读取SHT31内温湿度数据(单次数据采集模式)
参  数: data_buff --- 从SHT31读取的多字节数据指针
                          data_len  --- 从SHT31读取的多字节数据长度(6个)
返回值: 无
***********************************************************/
void SHT31_Read(uchar *data_buff,uchar data_len)
{         
        uchar temp;                 //定义一下,读取MCU状态寄存器用
        uchar i;                    //定义一下,供循环使用
        uint time;                  //定义一下,供等待延时用
        //以下程序为I2C通信防锁死操作,非常重要!
        if((PE_IDR&0x04) == 0x00)   //检测总线是否真的忙碌中(忙碌则SCL=1,SDA=0)
        {
                I2C_CR1 &= 0xFE;          //PE=0,禁用硬件I2C模块,准备直接操作MCU端口
                PE_DDR |= 0x02;           //设置SCL端口为输出
                PE_CR1 |= 0x02;           //上拉输出
                for(i=0;i<9;i++)          //SCL端口发出9个时钟脉冲,让从设备SHT31释放总线(恢复SDA=1)
                {
                        PE_ODR &= 0xFD;         //SCL=0;
                        delay_us(50);           //延时(I2C通信频率10KHz)
                  PE_ODR |= 0x02;         //SCL=1
                  delay_us(50);           //延时(I2C通信频率10KHz)
                }
                time = 500;               //变量赋值,准备延迟等待500次
                while(!(PE_IDR&0x04))     //等待数据线SDA=1
                {
                  if(!--time)             //变量自减
                  return;                 //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
          }
                PE_DDR &= 0xFD;           //SCL端口恢复输入方式
                PE_CR1 &= 0xFD;           //浮空输入
                PE_ODR &= 0xFD;           //清零输出寄存器
                I2C_CR1 |= 0x01;          //重新启动硬件I2C模块,接管SCL、SDA端口
                return;                   //退出函数,放弃本次数据读取操作
        }
        //以上程序为I2C通信防锁死操作,非常重要!
        //以下程序为STM8S硬件I2C通信防BUSY锁死操作,非常重要!
        if((I2C_SR3&0x02) == 0x02)  //检测总线是否正确释放空闲中(总线正确释放则I2C_SR3状态寄存器BUSY=0,否则BUSY=1)
        {
                I2C_CR2 |= 0x80;          //I2C_CR2控制寄存器SWRST=1,软件复位硬件I2C模块
          I2C_CR2 &= 0x7F;          //I2C_CR2控制寄存器SWRST=0,软件复位硬件I2C模块结束
                I2C_FREQR = 0x02;         //配置I2C外设时钟2MHz
                I2C_CCRH = 0x00;          //配置I2C为标准模式及速率
                I2C_CCRL = 0x64;          //I2C通信速率半周期=((1/2)*100us=50us,速率=1/100us=10KHz
          I2C_TRISER = 0x03;        //配置I2C上升时间寄存器,1000ns(SCL最大值)/500ns(2MHz周期)+1
                I2C_CR1 |= 0x01;          //启动I2C硬件模块
                return;                   //退出函数,放弃本次数据读取操作
        }
        //以上程序为STM8S硬件I2C通信防BUSY锁死操作,非常重要!
        //以下为SHT31温湿度传感器读数据操作时序(1-10步)
  //***  1.先检测I2C总线是否忙碌  ***//
        time = 500;                 //变量赋值,准备延迟等待500次
        while(I2C_SR3&0x02)         //检测总线是否忙碌中(I2C_SR3状态寄存器BUSY位=1表示总线上有通信/忙碌)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        //***  2.发起始条件  ***//
        I2C_CR2 |= 0x01;            //发起始条件(置位I2C_CR2控制寄存器START位)
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x01))      //I2C_SR1状态寄存器SB位=1表示发送成功
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        delay_us(5);                //短暂延时
        //***  3.发"地址+写操作"指令  ***//
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
        I2C_DR = 0x88;              //发送SHT31从设备地址("器件地址<0x44>+写操作<左移一位>"),同时清除I2C_SR1中BFT位
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x02))      //I2C_SR1状态寄存器ADDR位=1时表示地址发送结束(主模式)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        delay_us(5);                //短暂延时
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1数值
        temp = I2C_SR3;             //清除状态寄存器I2C_SR1中ADDR标志位(地址已发送结束)
        //***  4.发16位测试指令高八位  ***//
        I2C_DR = 0x2C;              //发送SHT31 16位测试指令代码(高八位)
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x84))      //等待数据发送完毕(I2C_SR1状态寄存器TxE、BTF位为1时,表示发送时数据寄存器为空且数据字节发送完毕)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        //***  5.发16位测试指令低八位  ***//
        I2C_DR = 0x06;              //发送SHT31 16位测试指令代码(低八位)(高可重复性,使能时钟拉伸,单次数据采集模式)
                                    /*备注: 如果使能时钟拉伸,在没有数据发送时,传感器会发出一个ACK信号,并随后拉下SCL线,SCL线被拖到
                                                                                                                                测量完成为止,一旦测量完成,传感器释放SCL线并发送测量结果; 如果未使能时钟拉伸,在没有
                                                                                                                                                        数据发送时,传感器响发出一个NACK.*/
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x84))      //等待数据发送完毕(I2C_SR1状态寄存器TxE、BTF位为1时,表示发送时数据寄存器为空且数据字节发送完毕)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        //***  6.发停止条件 + SCL Free延时  ***//
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
        temp = I2C_DR;              //清除I2C_SR1中BFT位
        I2C_CR2 |= 0x02;            //发停止条件(置位I2C_CR2控制寄存器STOP位///必须先清除I2C_SR1状态寄存器BTF位)
        delay_us(10);               //短暂延时
        //***  7.重发起始条件  ***//
        I2C_CR2 |= 0x01;            //重复发起始条件(置位I2C_CR2控制寄存器START位)
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x01))      //I2C_SR1状态寄存器SB位=1表示发送成功
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        delay_us(5);                //短暂延时
        //***  8.发"地址+读操作"指令  ***//
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
        I2C_DR = 0x89;              //发送SHT31从设备地址("器件地址<0x44>+读操作<左移1位|0x01>"),同时清除I2C_SR1中BFT位
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x02))      //I2C_SR1状态寄存器ADDR位=1时表示地址发送结束(主模式)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        delay_us(5);                //短暂延时
        //***  9.延时等待测量完毕(时钟拉伸已使能)  ***//
        delay_us(100);              //等待测量完毕
        //***  10.循环读取SHT31返回的6个测试数据值  ***//
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1数值
        temp = I2C_SR3;             //清除状态寄存器I2C_SR1中ADDR标志位(地址已发送结束)
        I2C_CR2        |= 0x04;            //使能ACK应答(置位I2C_CR2控制寄存器ACK位,收到一个字节数据或地址后返回应答)
        while(data_len)             //循环读取数据
        {
                if(data_len == 1)         //如果是接收最后一位数据(特殊处理)
                {
                        I2C_CR2 &= 0xFB;        //关闭ACK应答(清零I2C_CR2控制寄存器ACK位,收到一个字节数据或地址后不返回应答)
                        I2C_CR2 |= 0x02;        //发停止条件(置位I2C_CR2控制寄存器STOP位///必须先清除I2C_SR1状态寄存器BTF位)
                }
                if(I2C_SR1 & 0x40)        //数据寄存器为满(I2C_SR1状态寄存器RxNE位为1时,表示接收寄存器数据非空)
                {
                        *data_buff = I2C_DR;    //读取数据寄存器内数值,同时清除BTF位
                        data_buff++;            //准备接收下一字节数据
                        data_len--;
                }
        }
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
        temp = I2C_DR;              //清除I2C_SR1中BFT位
}
/***********************************************************
函数名: Tem_Hum_Get()
功  能: STM8S207 MCU通过硬件I2C通信读取SHT31内温湿度数据,
        并转换数据,保存成独立的显示用十进制数据
参  数: 无
返回值: 无
***********************************************************/
void Tem_Hum_Get(void)
{
        long a;                     //定义一下
        SHT31_Read(SHT31_R_Data,6); //读取SHT31内部温湿度数据
        a = (SHT31_R_Data[0]*256)+SHT31_R_Data[1];
        a = a*175;
        a = a/65535;                //计算温度数值(℃)
        temperature = a-45;         //得到温度数值(℃)
        a = (SHT31_R_Data[3]*256)+SHT31_R_Data[4];
        a = a*100;
        a = a/65535;                //计算湿度数值(%)
        humidity = a;               //得到温度数值(%)
}

SHT31温湿度转换公式.png

使用特权

评论回复
springvirus| | 2018-6-11 08:57 | 显示全部楼层
加油!!

使用特权

评论回复
henangongda123|  楼主 | 2018-6-11 09:30 | 显示全部楼层

使用特权

评论回复
天命风流| | 2018-6-11 13:25 | 显示全部楼层
高!!!!

使用特权

评论回复
henangongda123|  楼主 | 2018-6-11 13:32 | 显示全部楼层

使用特权

评论回复
henangongda123|  楼主 | 2018-6-11 22:41 | 显示全部楼层
今天在多位网友的帮忙下,SHT31温湿度传感器调试完毕,谢谢帮忙的各位!谢谢~
温湿度测量-1.jpg
温湿度测量-2.jpg

使用特权

评论回复
henangongda123|  楼主 | 2018-6-11 22:43 | 显示全部楼层
明天开始准备画电路图,设计PCB板,并初步把外观做出来。
共享SHT31温湿度传感器完整操作代码如下:
/********* SHT31温湿度传感器驱动及相关数据处理操作 **********/
//SHT31读取温湿度数据
/***********************************************************
函数名: SHT31_Read()
功  能: STM8S207 MCU通过硬件I2C通信读取SHT31内温湿度数据(单次数据采集模式)
参  数: data_buff --- 从SHT31读取的多字节数据指针
                          data_len  --- 从SHT31读取的多字节数据长度(6个)
返回值: 无
***********************************************************/
void SHT31_Read(uchar *data_buff,uchar data_len)
{         
        uchar temp;                 //定义一下,读取MCU状态寄存器用
        uchar i;                    //定义一下,供循环使用
        uint time;                  //定义一下,供等待延时用
        //以下程序为I2C通信防锁死操作,非常重要!
        if((PE_IDR&0x04) == 0x00)   //检测总线是否真的忙碌中(忙碌则SCL=1,SDA=0)
        {
                I2C_CR1 &= 0xFE;          //PE=0,禁用硬件I2C模块,准备直接操作MCU端口
                PE_DDR |= 0x02;           //设置SCL端口为输出
                PE_CR1 |= 0x02;           //上拉输出
                for(i=0;i<9;i++)          //SCL端口发出9个时钟脉冲,让从设备SHT31释放总线(恢复SDA=1)
                {
                        PE_ODR &= 0xFD;         //SCL=0;
                        delay_us(50);           //延时(I2C通信频率10KHz)
                  PE_ODR |= 0x02;         //SCL=1
                  delay_us(50);           //延时(I2C通信频率10KHz)
                }
                time = 500;               //变量赋值,准备延迟等待500次
                while(!(PE_IDR&0x04))     //等待数据线SDA=1
                {
                  if(!--time)             //变量自减
                  return;                 //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
          }
                PE_DDR &= 0xFD;           //SCL端口恢复输入方式
                PE_CR1 &= 0xFD;           //浮空输入
                PE_ODR &= 0xFD;           //清零输出寄存器
                I2C_CR1 |= 0x01;          //重新启动硬件I2C模块,接管SCL、SDA端口
                return;                   //退出函数,放弃本次数据读取操作
        }
        //以上程序为I2C通信防锁死操作,非常重要!
        //以下程序为STM8S硬件I2C通信防BUSY锁死操作,非常重要!
        if((I2C_SR3&0x02) == 0x02)  //检测总线是否正确释放空闲中(总线正确释放则I2C_SR3状态寄存器BUSY=0,否则BUSY=1)
        {
                I2C_CR2 |= 0x80;          //I2C_CR2控制寄存器SWRST=1,软件复位硬件I2C模块
          I2C_CR2 &= 0x7F;          //I2C_CR2控制寄存器SWRST=0,软件复位硬件I2C模块结束
                I2C_FREQR = 0x02;         //配置I2C外设时钟2MHz
                I2C_CCRH = 0x00;          //配置I2C为标准模式及速率
                I2C_CCRL = 0x64;          //I2C通信速率半周期=((1/2)*100us=50us,速率=1/100us=10KHz
          I2C_TRISER = 0x03;        //配置I2C上升时间寄存器,1000ns(SCL最大值)/500ns(2MHz周期)+1
                I2C_CR1 |= 0x01;          //启动I2C硬件模块
                return;                   //退出函数,放弃本次数据读取操作
        }
        //以上程序为STM8S硬件I2C通信防BUSY锁死操作,非常重要!
        //以下为SHT31温湿度传感器读数据操作时序(1-10步)
  //***  1.先检测I2C总线是否忙碌  ***//
        time = 500;                 //变量赋值,准备延迟等待500次
        while(I2C_SR3&0x02)         //检测总线是否忙碌中(I2C_SR3状态寄存器BUSY位=1表示总线上有通信/忙碌)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        //***  2.发起始条件  ***//
        I2C_CR2 |= 0x01;            //发起始条件(置位I2C_CR2控制寄存器START位)
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x01))      //I2C_SR1状态寄存器SB位=1表示发送成功
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        delay_us(5);                //短暂延时
        //***  3.发"地址+写操作"指令  ***//
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
        I2C_DR = 0x88;              //发送SHT31从设备地址("器件地址<0x44>+写操作<左移一位>"),同时清除I2C_SR1中BFT位
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x02))      //I2C_SR1状态寄存器ADDR位=1时表示地址发送结束(主模式)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        delay_us(5);                //短暂延时
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1数值
        temp = I2C_SR3;             //清除状态寄存器I2C_SR1中ADDR标志位(地址已发送结束)
        //***  4.发16位测试指令高八位  ***//
        I2C_DR = 0x2C;              //发送SHT31 16位测试指令代码(高八位)
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x84))      //等待数据发送完毕(I2C_SR1状态寄存器TxE、BTF位为1时,表示发送时数据寄存器为空且数据字节发送完毕)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        //***  5.发16位测试指令低八位  ***//
        I2C_DR = 0x06;              //发送SHT31 16位测试指令代码(低八位)(高可重复性,使能时钟拉伸,单次数据采集模式)
                                    /*备注: 如果使能时钟拉伸,在没有数据发送时,传感器会发出一个ACK信号,并随后拉下SCL线,SCL线被拖到
                                                                                                                                测量完成为止,一旦测量完成,传感器释放SCL线并发送测量结果; 如果未使能时钟拉伸,在没有
                                                                                                                                                        数据发送时,传感器响发出一个NACK.*/
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x84))      //等待数据发送完毕(I2C_SR1状态寄存器TxE、BTF位为1时,表示发送时数据寄存器为空且数据字节发送完毕)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        //***  6.发停止条件 + SCL Free延时  ***//
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
        temp = I2C_DR;              //清除I2C_SR1中BFT位
        I2C_CR2 |= 0x02;            //发停止条件(置位I2C_CR2控制寄存器STOP位///必须先清除I2C_SR1状态寄存器BTF位)
        delay_us(10);               //短暂延时
        //***  7.重发起始条件  ***//
        I2C_CR2 |= 0x01;            //重复发起始条件(置位I2C_CR2控制寄存器START位)
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x01))      //I2C_SR1状态寄存器SB位=1表示发送成功
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        delay_us(5);                //短暂延时
        //***  8.发"地址+读操作"指令  ***//
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
        I2C_DR = 0x89;              //发送SHT31从设备地址("器件地址<0x44>+读操作<左移1位|0x01>"),同时清除I2C_SR1中BFT位
        time = 500;                 //变量赋值,准备延迟等待500次
        while(!(I2C_SR1&0x02))      //I2C_SR1状态寄存器ADDR位=1时表示地址发送结束(主模式)
        {
                if(!--time)               //变量自减
                return;                   //延迟等待500次后,未达到预期效果,退出子函数以防程序死机状态
        }
        delay_us(5);                //短暂延时
        //***  9.延时等待测量完毕(时钟拉伸已使能)  ***//
        delay_us(100);              //等待测量完毕
        //***  10.循环读取SHT31返回的6个测试数据值  ***//
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1数值
        temp = I2C_SR3;             //清除状态寄存器I2C_SR1中ADDR标志位(地址已发送结束)
        I2C_CR2        |= 0x04;            //使能ACK应答(置位I2C_CR2控制寄存器ACK位,收到一个字节数据或地址后返回应答)
        while(data_len)             //循环读取数据
        {
                if(data_len == 1)         //如果是接收最后一位数据(特殊处理)
                {
                        I2C_CR2 &= 0xFB;        //关闭ACK应答(清零I2C_CR2控制寄存器ACK位,收到一个字节数据或地址后不返回应答)
                        I2C_CR2 |= 0x02;        //发停止条件(置位I2C_CR2控制寄存器STOP位///必须先清除I2C_SR1状态寄存器BTF位)
                }
                if(I2C_SR1 & 0x40)        //数据寄存器为满(I2C_SR1状态寄存器RxNE位为1时,表示接收寄存器数据非空)
                {
                        *data_buff = I2C_DR;    //读取数据寄存器内数值,同时清除BTF位
                        data_buff++;            //准备接收下一字节数据
                        data_len--;
                }
        }
        temp = I2C_SR1;             //读取状态寄存器I2C_SR1值
        temp = I2C_DR;              //清除I2C_SR1中BFT位
}
/***********************************************************
函数名: Tem_Hum_Get()
功  能: STM8S207 MCU通过硬件I2C通信读取SHT31内温湿度数据,
        并转换数据,保存成独立的显示用十进制数据
参  数: 无
返回值: 无
***********************************************************/
void Tem_Hum_Get(void)
{
        long a=0;                   //定义一下,数据转换使用
        float b=0;                  //定义一下,数据转换使用
        SHT31_Read(SHT31_R_Data,6); //读取SHT31内部温湿度数据
        a = ((long)SHT31_R_Data[0]*256)+(long)SHT31_R_Data[1];
        a = a*175;                  //计算温度数值(℃)
        b = (float)a/65535;         //计算温度数值(℃)
        b = b-45;                   //计算温度数值(℃)
        temperature = b*10;         //得到10倍温度数值(℃)
        a = ((long)SHT31_R_Data[3]*256)+(long)SHT31_R_Data[4];
        a = a*100;                  //计算湿度数值(%)
        b = (float)a/65535;         //计算湿度数值(%)
        humidity = b*10;            //得到10倍温度数值(%)
}

使用特权

评论回复
henangongda123|  楼主 | 2018-6-11 22:44 | 显示全部楼层
henangongda123 发表于 2018-6-11 22:43
明天开始准备画电路图,设计PCB板,并初步把外观做出来。
共享SHT31温湿度传感器完整操作代码如下:
/***** ...

注意,不同类型的数据类型之间运算,要强制转换一致,比如long和uchar之间、int和long之间等等

使用特权

评论回复
henangongda123|  楼主 | 2018-6-13 17:58 | 显示全部楼层
今天画电路图才发现,少调试了一个模块:MAX9814,用于声控LCD背光,感觉有点奢侈啊,呵呵
MAX9814.jpg

使用特权

评论回复
henangongda123|  楼主 | 2018-6-13 20:49 | 显示全部楼层
刚才用示波器测试了一下这个咪头放大模块,反应还不错,对声音(拍手、说话等)都能放大,信号对比也明显,特别是吹气,反应太大了,呵呵  不过它的最大输出电压是1.25V,剩下的就是在程序里面加入ADC转换,并识别这些信号。
咪头放大器-声音1.jpg
咪头放大器-声音2.jpg
咪头放大器-吹气.jpg

使用特权

评论回复
henangongda123|  楼主 | 2018-6-16 11:17 | 显示全部楼层
今天把原理图画的差不多了,在补一些封装,明天就可以画板了!另外,新找了一家深蓝色的12864液晶,效果比之前买的那个好一些。

DIY12864液晶显示电子台历.pdf

449.93 KB

使用特权

评论回复
henangongda123|  楼主 | 2018-6-18 17:39 | 显示全部楼层
今天布板,发现这个Micro-USB头大小并不一样(挖孔部分),干脆取消掉算了
Micro-5P座.png

使用特权

评论回复
henangongda123|  楼主 | 2018-6-18 17:40 | 显示全部楼层
另外,原理图也在更新。

使用特权

评论回复
henangongda123|  楼主 | 2018-6-22 14:05 | 显示全部楼层
今天从立创商城买了DS3231SN芯片,跟之前调试时候买的模块上的IC差异真的有点大啊,丝印也不一样,呵呵
DS3231SN.jpg

使用特权

评论回复
henangongda123|  楼主 | 2018-6-25 18:37 | 显示全部楼层
今天PCB打样回来了,测试没有问题后再共享图纸。
DIY电子台历PCB样板.jpg

使用特权

评论回复
henangongda123|  楼主 | 2018-6-26 10:43 | 显示全部楼层
DS3231SN封装错了!

使用特权

评论回复
henangongda123|  楼主 | 2018-6-26 11:46 | 显示全部楼层
电源部分已测试OK,DS3231SN实际封装是很宽的SOIC-16,我错搞成SO-16了,为了节省打样时间和金钱,只好把DS3231SN管脚处理了先,看看还没有其他问题存在。
电源部分测试OK.jpg
DS3231SN封装错误处理.jpg

使用特权

评论回复
发新帖 本帖赏金 5.50元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则