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應答