
武汉芯源CW32L031实现超远距离超低耗无线采集_当前滚动
2023-06-30 16:09:16 来源:华仔的编程随笔
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); }
软件IIC的配置,这里使用软件模拟实现。具体代码如下:#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应答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的采集程序如下:#include "sht30.h"#include "myiic.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(50);//命令发完后需要等待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\\r\\n",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=10*100*((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();}
在主程序中,我们首先对串口、IIC、AWT、SHT30进行初始化,然后进入采集程序,实现的代码如下:int main(void){ int t[6]; uint16_t h[6]; E31_UART_Init(); SHT30_Init(); USART_ITConfig(CW_UART1, USART_IT_RC, ENABLE); Init_awt_power(); InitTick(24000000ul); //初始化SysTick // 开启两线调试接口RCC_SWDIO_Config(RCC_SYSCTRL_SWDIOEN); while (1) { SHT30_Read_Humiture(t,h); e31_send(t[0],h[0]); enter_lowpower(); exit_lowpower(); } return 0;}
【程序效果】
模块采集的数据,在上位机的串口助手上接收到以16进制数据发送的温湿度数据。
上位机根据具体的需要再进行解析、判断或者分发。
【功耗测试】
此工程以合宙的IoTPower来采集功率耗数据,并做出基本的分析,具体效果如下图:
从上面的数据我们可以看出,待机电流为7.5微安左右,在每两分钟启用一次数据上报,最在工作电流为46.5mA,平均电流为110uA,平均功率为362微瓦。可以推算一下,1000mAH的电池可以持续供电100天左右。如果我们采用在温湿度正常的范围内缓存,每一个小时做一次数据上传,那么预计可以延长30倍的工作时间,那就是10年左右的待机。
【讨论】
CW32L031具有超低功耗的出色性能,此实验的意义验证了在电池供电的环境下,可以持续的工作数年的可能。433M无线超远距离无线转输模块可以提供长达5公里(空旷)数据传输,广泛适用于智慧农业等野外的数据持续采集。也可以把温湿度传感器更改为土壤湿度、门禁等传感器,实现无线报警等功能。
审核编辑:汤梓红
标签:
互联网

武汉芯源的CW32L031实现超低功耗无线温湿度采集,可实现在电池供电下,
2023-06-30 16:09:16

今日热闻!苑丽:牢记“国之大者” 带领青年助力农业农村现代化
青年是祖国的未来、民族的希望。奋进新征程、建功新时代,为充分展现新
2023-06-30 15:52:37

简述新能源汽车随车充电枪(IC-CPD)的关键元器件及应用
随着新能源汽车的飞速发展,电动汽车随车充电枪(IC-CPD)的需求量也正
2023-06-30 15:19:02