CW32L031实现低功耗温湿度
【硬件环境】
- CW32L031C8开发板
- SHT30温湿度传感器
- E31-TTL-50无线串口模块
【开发板环境】
Ubuntu20.0.4
【代码编辑器】
VSCODE ssh远程
【编译器】
arm-none-eabi-gcc
【工程包】
Cw32l031_gcc工程包
【工程概述】
本工程的核心分为sht30数据采集后,经无线串口模块发送给上位机,利用自动唤醒模块休眠指定时长后再次唤醒系统进行数据采集。
【初略原理图】
【程序流程图】
【主要代码】
- 自动唤醒定时器(AWT) 包含一个 16bit 向下计数器,并由一个可编程预分频器驱动。AWT 可选 5 种计数时钟源,可工作于定时模式或计数模式。当计数器时钟源为 LSE 或 LSI 时,AWT 可在深度休眠模式下保持运行,下溢出中断可唤醒 MCU 回到运行模式。具体配置代码如下:
void Init_awt_power(void)
{
AWT_TimeCntInitTypeDef AWT_TimeCntInitStruct = {0};
RCC_APBPeriphClk_Enable2(RCC_APB2_PERIPH_AWT, ENABLE); //Open AWT Clk
RCC_SystemCoreClockUpdate( RCC_Sysctrl_GetHClkFreq() );
RCC_LSI_Enable();
AWT_TimeCntStructInit( &AWT_TimeCntInitStruct );
AWT_TimeCntInitStruct.AWT_ClkSource = AWT_CLKSOURCE_LSI;
AWT_TimeCntInitStruct.AWT_Prescaler = AWT_PRS_DIV32768;
AWT_TimeCntInitStruct.AWT_Mode = AWT_MODE_TIMECNT;
AWT_TimeCntInitStruct.AWT_Period = 120;
AWT_TimeCntInit(&AWT_TimeCntInitStruct);
__disable_irq();
NVIC_EnableIRQ(AWT_IRQn);
__enable_irq();
//使能AWT下溢出中断
AWT_ITConfig(AWT_IT_UD, ENABLE);
AWT_Cmd(ENABLE);
//DeepSleep唤醒时,保持原系统时钟来源
RCC_WAKEUPCLK_Config(RCC_SYSCTRL_WAKEUPCLKDIS);
}
#include "myiic.h"
#define I2C1_SCL_GPIO_PORT CW_GPIOB
#define I2C1_SCL_GPIO_PIN GPIO_PIN_10
#define I2C1_SDA_GPIO_PORT CW_GPIOB
#define I2C1_SDA_GPIO_PIN GPIO_PIN_11
void delay_us(uint32_t us)
{
while(us--)
{
__NOP();
__NOP();
__NOP();
__NOP();
__NOP();
}
}
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("超时\\n");
IIC_Stop();
return 1;
}
}
IIC_SCL=0;//时钟输出0
return 0;
}
//产生ACK应答