0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于CW32L083设计的超低功耗温湿度计

华仔的编程随笔 来源:华仔的编程随笔 作者:华仔的编程随笔 2023-06-25 12:08 次阅读

【开发环境】

1、硬件:CW32L083VxTx StartKit 开发板,板载有8位LCD段码屏。

2、软件环境:MDK5。

3、温湿度计:SHT30。

【硬件连接】

开发板 SHT30

PB11 SDA

PB10 SCL

DVCC VCC

DVSS GND

【功耗测试环境】

合宙IoT Power功耗测试神器。

【硬件框图】

硬件框图.png

【软件流程图】

程序流程图.png

【主要代码设计】

本工程主要代码功能为温湿传感器SHT30的数据采集、LCD显示、RTC自动唤醒。下面展示三个功能模块的主要代码:

1、SHT30采集模拟IIC通信,主要是IIC的时序产生,与SHT30的单次采集指令发送与数据读取以及CRC。

IIC的时序产生主要代码如下:

void IIC_Init(void)

{

//配置PB10 为输出

//使能GPIOB时钟

CW_SYSCTRL->AHBEN_f.GPIOB = 1;

//配置PB10 为输出

CW_GPIOB->ANALOG_f.PIN10 = 0; //设置 GPIOx_ANALOG.PINy 为 0,将端口配置为数字功能;

CW_GPIOB->DIR_f.PIN10 = 0; //设置 GPIOx_DIR.PINy 为 0,将端口配置成输出;

CW_GPIOB->OPENDRAIN_f.PIN10 = 0; //0:推挽输出

CW_GPIOB->ODR_f.PIN10 = 1;

CW_GPIOB->ANALOG_f.PIN11 = 0; //设置 GPIOx_ANALOG.PINy 为 0,将端口配置为数字功能;

CW_GPIOB->DIR_f.PIN11 = 0; //设置 GPIOx_DIR.PINy 为 0,将端口配置成输出;

CW_GPIOB->OPENDRAIN_f.PIN11 = 0; //0:推挽输出

CW_GPIOB->ODR_f.PIN11 = 1;

}

//IO方向设置(SDA)

/ xxxxxxxxxxxxxx ****/

void SDA_IN()

{

CW_GPIOB->DIR_f.PIN11 = 1; //设置 GPIOx_DIR.PINy 为 0,将端口配置成输出;

}

void SDA_OUT()

{

CW_GPIOB->DIR_f.PIN11 = 0; //设置 GPIOx_DIR.PINy 为 0,将端口配置成输出;

CW_GPIOB->OPENDRAIN_f.PIN11 = 0; //0:推挽输出

}

//产生IIC起始信号

void IIC_Start(void)

{

SDA_OUT(); //sda线输出

IIC_SDA=1;

IIC_SCL=1;

delay_us(4);

IIC_SDA=0;//START:when CLK is high,DATA change form high to low

delay_us(4);

IIC_SCL=0;//钳住I2C总线,准备发送或接收数据

}

//产生IIC停止信号

void IIC_Stop(void)

{

SDA_OUT();//sda线输出

IIC_SCL=0;

IIC_SDA=0;//STOP:when CLK is high DATA change form low to high

delay_us(4);

IIC_SCL=1;

IIC_SDA=1;//发送I2C总线结束信号

delay_us(4);

}

//等待应答信号到来

//返回值:1,接收应答失败

// 0,接收应答成功

/ xxxx修改超时时间 ***/

uint8_t IIC_Wait_Ack(void)

{

uint8_t ucErrTime=0;

SDA_IN(); //SDA设置为输入

IIC_SDA=1;delay_us(3);

IIC_SCL=1;delay_us(3);

while(READ_SDA)

{

ucErrTime++;

if(ucErrTime>250)

{

//printf("超时
");

IIC_Stop();

return 1;

}

}

IIC_SCL=0;//时钟输出0

return 0;

}

//产生ACK应答

void IIC_Ack(void)

{

IIC_SCL=0;

SDA_OUT();

IIC_SDA=0;

delay_us(2);

IIC_SCL=1;

delay_us(2);

IIC_SCL=0;

}

//不产生ACK应答

void IIC_NAck(void)

{

IIC_SCL=0;

SDA_OUT();

IIC_SDA=1;

delay_us(2);

IIC_SCL=1;

delay_us(2);

IIC_SCL=0;

}

//IIC发送一个字节

//返回从机有无应答

//1,有应答

//0,无应答

void IIC_Send_Byte(uint8_t txd)

{

uint8_t t;

SDA_OUT();

IIC_SCL=0;//拉低时钟开始数据传输

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

{

if((txd&0x80)>>7)

IIC_SDA=1;

else

IIC_SDA=0;

txd<<=1;

delay_us(2); //对TEA5767这三个延时都是必须的

IIC_SCL=1;

delay_us(2);

IIC_SCL=0;

delay_us(2);

}

}

//读1个字节,ack=1时,发送ACK,ack=0,发送nACK

uint8_t IIC_Read_Byte(unsigned char ack)

{

unsigned char i,receive=0;

SDA_IN();//SDA设置为输入

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

{

IIC_SCL=0;

delay_us(100);

IIC_SCL=1;

receive<<=1;

if(READ_SDA)receive++;

delay_us(100);

}

if (!ack)

IIC_NAck();//发送nACK

else

IIC_Ack(); //发送ACK

return receive;

}

SHT30的测量指令与数据获取及CRC主要代码如下:

#include "sht30.h"

#define POLYNOMIAL_CXDZ 0x31 // X^8 + X^5 + X^4 + 1

//SHT3X CRC校验

unsigned char SHT3X_CRC(uint8_t *data, uint8_t len)

{

unsigned char bit; // bit mask

unsigned char crc = 0xFF; // calculated checksum

unsigned char byteCtr; // byte counter

// calculates 8-Bit checksum with given polynomial @GZCXDZ

for(byteCtr = 0; byteCtr < len; byteCtr++) {

crc ^= (data[byteCtr]);

for(bit = 8; bit > 0; --bit) {

if(crc & 0x80) {

crc = (crc << 1) ^ POLYNOMIAL_CXDZ;

} else {

crc = (crc << 1);

}

}

}

return crc;

}

//SHT30命令函数

//addr:表示产品的序号,因为SHT30使用IIC总线的话一条线上可以挂两个

void SHT30_CMD(uint16_t cmd)

{

IIC_Start();

IIC_Send_Byte(SHT30_ADDR+0); //发送设备地址,写寄存器

IIC_Wait_Ack();

IIC_Send_Byte((cmd>>8)&0xff); //MSB

IIC_Wait_Ack();

IIC_Send_Byte(cmd&0xff); //LSB

IIC_Wait_Ack();

IIC_Stop();

SysTickDelay(500);//命令发完后需要等待20ms以上才能读写

}

//SHT30读取温湿度

//temp:温度,-400~1250,实际温度=temp/10,分辨率0.1℃,精度±0.3℃

//humi:湿度,0~1000,实际湿度=humi/10,分辨率0.1%rh,精度±3

//返回0成功,1失败

uint8_t SHT30_Read_Humiture(int *temp,uint16_t *humi)

{

uint8_t buff[6];

SHT30_CMD(SHT30_READ_HUMITURE);//读温湿度命令

IIC_Start();

IIC_Send_Byte(SHT30_ADDR+1); //发送设备地址,读寄存器

IIC_Wait_Ack();

buff[0]=IIC_Read_Byte(1);//继续读,给应答

buff[1]=IIC_Read_Byte(1);//继续读,给应答

buff[2]=IIC_Read_Byte(1);//继续读,给应答

buff[3]=IIC_Read_Byte(1);//继续读,给应答

buff[4]=IIC_Read_Byte(1);//继续读,给应答

buff[5]=IIC_Read_Byte(0);//不继续给停止应答

IIC_Stop();

//printf("buff=%d,%d,%d,%d,%d,%d
",buff[0],buff[1],buff[2],buff[3],buff[4],buff[5]);

//CRC校验

if(SHT3X_CRC(&buff[0],2)==buff[2] && SHT3X_CRC(&buff[3],2)==buff[5])

{

temp=(-45+(175.0 ((buff[0]<<8)+buff[1])/65535.0)) *10;

humi=10100* ((buff[3]<<8)+buff[4])/65535.0;

if(*temp>1250) *temp=1250;

else if(*temp<-400) *temp=-400;

return 0;

}

else return 1;

}

//SHT30初始化

void SHT30_Init()

{

IIC_Init();

}

2、LCD屏的显示,分为两个部分,一个是定义了段码显示的高、低位显示数组; 二是封装了数量显示了函数,具体代码如下:

/* 段码低8(左) */

static uint8_t num_L[10] = {

0x0d, //0

0x00, //1

0x0e, //2

0x0a, //3

0x03, //4

0x0b, //5

0x0f, //6

0x00, //7

0x0f, //8

0x0b, //9

};

/* 段码高8(右) */

static uint8_t num_H[10] = {

0x07,

0x06,

0x03,

0x07,//3

0x06,//4

0x05, //5

0x05, //

0x07, //7

0x07, //8

0x07, //9

};

void Lcd_clear(void)

{

CW_LCD->RAM0 = 0;

CW_LCD->RAM1 = 0;

CW_LCD->RAM8 = 0;

CW_LCD->RAM9 = 0;

}

void show_nums(uint32_t num)

{

uint8_t i=0;

uint8_t j;

uint32_t temp;

temp = num;

//空显示

Lcd_clear();

if(temp == 0)

show_num(0,0,0);

while(temp>0)

{

j = temp%10;

show_num(i,j,0);

temp /=10;

i++;

}

}

/**

*功能:显示数字到LCD段码屏上

*输入参数1:显示在哪个位上7-0

*输入参数2:需要显示数字

*输入参数3:是否需要显示小数点

*/

void show_num(uint8_t wei, uint8_t num, uint8_t doit)

{

uint8_t temp_H;

temp_H = num_H[num];

if(0 != doit)

{

temp_H = temp_H + 8 ; //第四位置1显示小数点

}

switch(wei)

{

case 7:

{

//显示第7个数码管

CW_LCD->RAM0 |= temp_H <<8 | num_L[num];

break;

}

case 6:

{

//显示第6个数码

CW_LCD->RAM0 |= (temp_H<<8 | num_L[num]) <<16;

break;

}

case 5:

{

//显示第5个数码管

CW_LCD->RAM1 |= num_L[num];

CW_LCD->RAM8 |= temp_H;

break;

}

case 4:

{

//显示第4个数码管

CW_LCD->RAM8 |= temp_H<<16 | num_L[num]<<8;

break;

}

case 3:

{

//显示第3个数码管

CW_LCD->RAM8 |= num_L[num]<<24;

CW_LCD->RAM9 |= temp_H;

break;

}

case 2:

{

//显示第2个数码管

CW_LCD->RAM9 |= temp_H<<16 | num_L[num]<<8;

break;

}

case 1:

{

//显示第1个数码管

CW_LCD->RAM1 |= temp_H<<8;

CW_LCD->RAM9 |= num_L[num]<<24;

break;

}

case 0:

{

//显示第0个数码管

CW_LCD->RAM1 |= temp_H<<24 | num_L[num]<<16;

break;

}

}

}

void LCD_Configuration(void)

{

LCD_InitTypeDef LCD_InitStruct = {0};

LCD_InitStruct.LCD_Bias = LCD_Bias_1_3;

LCD_InitStruct.LCD_ClockSource = LCD_CLOCK_SOURCE_LSI;

LCD_InitStruct.LCD_Duty = LCD_Duty_1_4;

LCD_InitStruct.LCD_ScanFreq = LCD_SCAN_FREQ_128HZ;

LCD_InitStruct.LCD_VoltageSource = LCD_VoltageSource_Internal;

__RCC_LCD_CLK_ENABLE();

RCC_LSI_Enable();

LCD_Init(&LCD_InitStruct); //基本配置

// BTL004 LCD 对应的连接

//PA12 COM3

//PA11 COM2

//PA10 COM1

//PA09 COM0

//PA08 SEG0

//PC09 SEG1

//PC08 SEG2

//PC07 SEG3

//PC06 SEG4

//PD15 SEG32

//PD14 SEG33

//PD13 SEG34

//PD12 SEG35

//PD11 SEG36

//PD10 SEG37

//PD09 SEG38

//PD08 SEG39

//PB15 SEG5

//PB14 SEG6

//PB13 SEG7

// 分配引脚

LCD_COMConfig(LCD_COM0 | LCD_COM1 | LCD_COM2 | LCD_COM3, ENABLE);

LCD_SEG0to23Config(0x0000FF, ENABLE);

LCD_SEG32to55Config(0x0000FF,ENABLE);

CW_LCD->RAM[0] = 0;

CW_LCD->RAM[1] = 0;

CW_LCD->RAM2 = 0;

CW_LCD->RAM3 = 0;

CW_LCD->RAM4 = 0;

CW_LCD->RAM5 = 0;

CW_LCD->RAM6 = 0;

CW_LCD->RAM7 = 0;

CW_LCD->RAM8 = 0;

CW_LCD->RAM9 = 0;

CW_LCD->RAM10 = 0;

CW_LCD->RAM11 = 0;

CW_LCD->RAM12 = 0;

CW_LCD->RAM13 = 0;

LCD_Cmd(ENABLE);

CW_LCD->RAM0 = 0;

LCD_ContrastConfig(LCD_Contrast_Level_6);

LCD_DriveVoltageConfig(LCD_INRS_LEVEL_0);

}

3、功耗控制主要是通过进入深度睡眠模式来实现节能,并通过RTC的AWT模块来实现定时唤醒。在此模块中,我们配置了AWT时钟源为RTC_AWTSOURCE_FROM_RTC1HZ_1即1秒为单位的唤醒,我们可以通过RTC_AWTARR 唤醒定时器重载值,来实现以秒为单位的休眠时长。主要代码如下:

//进入低功耗设置

void entry_power(void)

{

// //1,先判断是否上电复位

RTC_InitTypeDef RTC_InitStruct = {0};

RTC_AWTTypeDef RCT_AWTStruct = {0};

RCC_LSE_Enable(RCC_LSE_MODE_OSC, RCC_LSE_AMP_NORMAL, RCC_LSE_DRIVER_NORMAL); // 选择LSE为RTC时钟

RTC_InitStruct.DateStruct.Day = 0x24; //设置日期,DAY、MONTH、YEAR必须为BCD方式,星期为0~6,代表星期日,星期一至星期六

RTC_InitStruct.DateStruct.Month = RTC_Month_June;

RTC_InitStruct.DateStruct.Week = RTC_Weekday_Monday;

RTC_InitStruct.DateStruct.Year = 0x23;

RTC_InitStruct.TimeStruct.Hour = 0x11; //设置时间,HOUR、MINIUTE、SECOND必须为BCD方式,用户须保证HOUR、AMPM、H24之间的关联正确性

RTC_InitStruct.TimeStruct.Minute = 0x58;

RTC_InitStruct.TimeStruct.Second = 0x59;

RTC_InitStruct.TimeStruct.AMPM = 0;

RTC_InitStruct.TimeStruct.H24 = 0;

RTC_InitStruct.RTC_ClockSource = RTC_RTCCLK_FROM_LSE;

RTC_Init(&RTC_InitStruct); //

//设置自动唤醒

RCT_AWTStruct.AWT_ClockSource = RTC_AWTSOURCE_FROM_RTC1HZ_1;

RCT_AWTStruct.AWT_ARRValue = 60;

RTC_AWTConfig(&RCT_AWTStruct);

RTC_AWTCmd(ENABLE);

RCC_APBPeriphClk_Enable1(RCC_APB1_PERIPH_RTC, ENABLE);

RTC_ITConfig(RTC_IT_AWTIMER, ENABLE);

}

4、在主程序中,我们先初始基本外设后进行循环的采集——显示——休眠——唤醒来实现温湿度采集的目标,主程序主要代码如下:

int32_t main(void)

{

uint16_t temp;

int t[20];

uint16_t h[20];

RCC_Configuration();

NVIC_Configuration();

LCD_Configuration();

InitTick(8000000);

SHT30_Init();

Lcd_clear();

SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

entry_power();

while(1)

{

SHT30_Read_Humiture(t,h);

temp = t[0];

Lcd_clear();

show_num(2, temp/100,0);

show_num(1, (temp/10)%10,1);

show_num(0, temp%10,0);

temp = h[0];

show_num(7, temp/100,0);

show_num(6, (temp/10)%10,1);

show_num(5, temp%10,0);

CW_SYSCTRL->AHBEN_f.GPIOB = 0;

__DSB();

__WFI();

SHT30_Init();

}

}

【实现的效果】

我们设定60秒中唤醒进行一次温显度采集,实现了休眠电流为5uA,综合平均工作电流为13uA、平均功率为。基本满足了以电池供电的环境下的超长工作。

温湿计.jpg

功耗.png

【讨论】

CW32L083集成了LCD控制器,可以实现数据采集、显示的超低功耗工作。非常适合用于电池供电的环境下工作。本次试验虽然获得了理想效果,但是还有一些可以改进的地方。

1、在待机中的主要电流产生是LCD屏产生的功耗,如果在特殊的环境下,不需要长时间显示,可以适时关闭LCD屏,这样可以节约差不多4uA的工作电流。启用按键来人工参与显示数据,这样又可以更进一步降低超机功耗。

2、在工作电流中,主要消耗的是SHT30的温度转换时产生的大电流。如果应用的生产环境,可以在等待温度转换时,降低MCU的主频或者进入sleep模式以降低能耗。

[[]()]()

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 开发板
    +关注

    关注

    25

    文章

    5032

    浏览量

    97371
  • 温湿度计
    +关注

    关注

    1

    文章

    23

    浏览量

    8086
  • MDK5
    +关注

    关注

    0

    文章

    10

    浏览量

    5739
  • CW32
    +关注

    关注

    1

    文章

    203

    浏览量

    626
收藏 人收藏

    评论

    相关推荐

    基于CW32模块的SHT30温湿度传感器设计

    我们的目标是将例程移植至CW32F030C8T6开发板上【测量温湿度的功能】。首先要获取资料,查看数据手册应如何实现读取数据,再移植至我们的工程。
    的头像 发表于 11-12 11:14 281次阅读
    基于<b class='flag-5'>CW</b>32模块的SHT30<b class='flag-5'>温湿度</b>传感器设计

    LORA无线温湿度监测系统

    LORA无线温湿度监测系统,作为现代环境监测技术的重要组成部分,正日益受到各行各业的广泛关注和应用。 LORA无线温湿度监测系统,利用LORA无线通信技术,对环境中温度和湿度的实时监测和数据传输,为
    的头像 发表于 11-07 16:57 310次阅读

    温湿度控制器的功能和应用

    温湿度控制器在电阻柜中的应用主要涉及以下几个方面: 温湿度控制器的功能 检测与控制:温湿度控制器可以同时检测和控制环境中的温度和湿度。它通常由传感器、控制器和加热器三部分组成。传感器负
    的头像 发表于 11-07 15:08 195次阅读

    蓝牙温湿度传感器:准确监测,智能管理

    蓝牙温湿度传感器以其高精度、低功耗、易操作、多功能的特点,成为了现代温湿度监测领域的佼佼者。无论是在工业生产、仓储管理,还是家庭健康、农业生产等领域,它都发挥着重要的作用。
    的头像 发表于 10-15 16:46 309次阅读

    温湿度监测系统应用

    在现代化工业生产、仓储管理、农业种植以及智能家居等领域,温湿度监测已成为不可或缺的一环。温湿度作为环境控制的关键因素,直接影响着产品质量、存储安全、作物生长效率以及居住舒适度。因此,一套高效、精准
    的头像 发表于 07-26 16:15 397次阅读

    库房温湿度自动监测系统

    仓储、库房在管理上,环境控制都是重中之重。库房温湿度自动监测系统作为一种更为便捷的解决方案,已经得到广泛的应用。 库房温湿度自动监测系统通过集成传感器、数据采集器、传输设备和管理平台等硬件设备,实现
    的头像 发表于 07-09 18:00 694次阅读

    粮仓温湿度监测解决方案

    温湿度是影响粮食储存品质的重要因素。过高的温度会加速粮食的呼吸作用,导致水分散失和品质下降。因此,粮仓的温湿度管理,成为了确保粮食储存安全和质量稳定的关键因素。方便及时发现粮仓的发热点,及时减少粮食
    的头像 发表于 07-04 16:37 343次阅读

    想要准确地测量环境温湿度温湿度传感器是关键!

    温湿度是生产生活中最重要的环境指标之一,不仅人需要在适宜的温湿度条件下保持良好的精神状态和敏捷的思维,食品、药品、各种仪器设备等都对环境温湿度有特殊的要求。基于对环境温湿度的要求,
    的头像 发表于 07-04 08:48 548次阅读

    无线温湿度监控系统

    无线温湿度监控系统,作为现代环境监测技术的杰出代表,已经广泛应用于各个行业和领域。利用无线通信技术,实现对环境温湿度的实时、远程监控,从而保障了各种设备和物品的安全运行和保存。 无线温湿度控制系统
    的头像 发表于 05-30 16:43 757次阅读

    小白测功耗之蓝牙温湿度传感器

    小小的温湿度计,是人们日常生活中的智能小帮手,也是极为典型的电池供电类低功耗产品。通常采用纽扣电池供电,可方便地摆放或粘贴于各种应用场景。市面上常见的温湿度计功耗到底有多低?今天,我
    的头像 发表于 04-16 08:04 1277次阅读
    小白测<b class='flag-5'>功耗</b>之蓝牙<b class='flag-5'>温湿度</b>传感器

    温湿度传感器有哪些应用场景?

    温湿度传感器在众多领域,特别是在实时记录温湿度变化的工作中最为广泛。温湿度传感器可以根据所记录的内容,对其进行科学有效的管理、分析和归纳。下面我们就温湿度传感器在不同场景中的应用做下介
    的头像 发表于 02-19 16:28 1326次阅读
    <b class='flag-5'>温湿度</b>传感器有哪些应用场景?

    温湿度传感器工作原理 温湿度传感器的接线方法

    温湿度传感器是一种用于测量环境温度和相对湿度的装置。它通常用于工业、农业、气象、室内空调等领域。本文将详细介绍温湿度传感器的工作原理和接线方法。 一、温湿度传感器的工作原理
    的头像 发表于 02-14 18:00 9358次阅读

    温湿度监测系统解决方案应用场景

    随着生活水平质量不断提高,因温度引发的各行业越来越重视产品生产、物品设备、存储等温湿度管理环境。科学应用温湿度监测系统,确保在储运过程中或实验、生产制造等过程中,有无任何危及产品安全的事件发生
    的头像 发表于 01-24 16:21 594次阅读

    请问如何优化CW32L083微控制器的功耗

    在进行低功耗设计时,如何优化CW32L083系列微控制器的功耗
    发表于 01-17 07:16

    CW32L083系列微控制器的ADC和DAC模块要如何使用?怎么配置?

    如何配置和使用CW32L083系列微控制器的ADC和DAC模块?
    发表于 01-17 06:08