CW32L031實(shí)現(xiàn)低功耗溫濕度
【硬件環(huán)境】
- CW32L031C8開發(fā)板
- SHT30溫濕度傳感器
- E31-TTL-50無線串口模塊
【開發(fā)板環(huán)境】
Ubuntu20.0.4
【代碼編輯器】
VSCODE ssh遠(yuǎn)程
【編譯器】
arm-none-eabi-gcc
【工程包】
Cw32l031_gcc工程包
【工程概述】
本工程的核心分為sht30數(shù)據(jù)采集后,經(jīng)無線串口模塊發(fā)送給上位機(jī),利用自動(dòng)喚醒模塊休眠指定時(shí)長后再次喚醒系統(tǒng)進(jìn)行數(shù)據(jù)采集。
【初略原理圖】
【程序流程圖】
【主要代碼】
- 自動(dòng)喚醒定時(shí)器(AWT) 包含一個(gè) 16bit 向下計(jì)數(shù)器,并由一個(gè)可編程預(yù)分頻器驅(qū)動(dòng)。AWT 可選 5 種計(jì)數(shù)時(shí)鐘源,可工作于定時(shí)模式或計(jì)數(shù)模式。當(dāng)計(jì)數(shù)器時(shí)鐘源為 LSE 或 LSI 時(shí),AWT 可在深度休眠模式下保持運(yùn)行,下溢出中斷可喚醒 MCU 回到運(yùn)行模式。具體配置代碼如下:
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喚醒時(shí),保持原系統(tǒng)時(shí)鐘來源
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時(shí)鐘
CW_SYSCTRL- >AHBEN_f.GPIOB = 1;
//配置PB10 為輸出
CW_GPIOB- >ANALOG_f.PIN10 = 0; //設(shè)置 GPIOx_ANALOG.PINy 為 0,將端口配置為數(shù)字功能;
CW_GPIOB- >DIR_f.PIN10 = 0; //設(shè)置 GPIOx_DIR.PINy 為 0,將端口配置成輸出;
CW_GPIOB- >OPENDRAIN_f.PIN10 = 0; //0:推挽輸出
CW_GPIOB- >ODR_f.PIN10 = 1;
CW_GPIOB- >ANALOG_f.PIN11 = 0; //設(shè)置 GPIOx_ANALOG.PINy 為 0,將端口配置為數(shù)字功能;
CW_GPIOB- >DIR_f.PIN11 = 0; //設(shè)置 GPIOx_DIR.PINy 為 0,將端口配置成輸出;
CW_GPIOB- >OPENDRAIN_f.PIN11 = 0; //0:推挽輸出
CW_GPIOB- >ODR_f.PIN11 = 1;
}
//IO方向設(shè)置(SDA)
/*********xxxxxxxxxxxxxx*************/
void SDA_IN()
{
CW_GPIOB- >DIR_f.PIN11 = 1; //設(shè)置 GPIOx_DIR.PINy 為 0,將端口配置成輸出;
}
void SDA_OUT()
{
CW_GPIOB- >DIR_f.PIN11 = 0; //設(shè)置 GPIOx_DIR.PINy 為 0,將端口配置成輸出;
CW_GPIOB- >OPENDRAIN_f.PIN11 = 0; //0:推挽輸出
}
//產(chǎn)生IIC起始信號(hào)
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總線,準(zhǔn)備發(fā)送或接收數(shù)據(jù)
}
//產(chǎn)生IIC停止信號(hào)
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;//發(fā)送I2C總線結(jié)束信號(hào)
delay_us(4);
}
//等待應(yīng)答信號(hào)到來
//返回值:1,接收應(yīng)答失敗
// 0,接收應(yīng)答成功
/*********xxxx修改超時(shí)時(shí)間************/
uint8_t IIC_Wait_Ack(void)
{
uint8_t ucErrTime=0;
SDA_IN(); //SDA設(shè)置為輸入
IIC_SDA=1;delay_us(3);
IIC_SCL=1;delay_us(3);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime >250)
{
//printf("超時(shí)\\n");
IIC_Stop();
return 1;
}
}
IIC_SCL=0;//時(shí)鐘輸出0
return 0;
}
//產(chǎn)生ACK應(yīng)答