为了实现低功耗,可以考虑以下几点:

1.关掉不必要的外设

在代码中,有一部分代码是初始化ADC,但是并没有使用到ADC,因此可以将其注释掉或者删除掉。另外,代码中也没有使用到看门狗,可以将禁止看门狗的指令删除掉。

2.优化循环

在代码中,有一部分是Delay函数,函数内部是通过循环来实现延时的。这种方式会占用CPU资源,可以考虑使用硬件定时器来实现延时,这样就可以释放CPU资源。

3.降低工作频率

可以通过降低CPU工作频率来降低功耗。在STM8L系列芯片中,可以通过设置时钟分频器来实现降低CPU工作频率的目的。

以下代码示例展示了如何优化代码以降低功耗:

/* Includes ------------------------------------------------------------------*/
#include 'stm8l15x.h'

/* Private defines -----------------------------------------------------------*/
//HT1621指令
#define  BIAS                       0x52             //0b1000 0101 0010  1/3duty 4com
#define  SYSDIS                     0X00             //0b1000 0000 0000  关振系统荡器和LCD偏压发生器
#define  SYSEN                      0X02             //0b1000 0000 0010 打开系统振荡器
#define  LCDOFF                     0X04             //0b1000 0000 0100  关LCD偏压
#define  LCDON                      0X06             //0b1000 0000 0110  打开LCD偏压
#define  XTAL                       0x28             //0b1000 0010 1000 外部接时钟
#define  RC256                      0X30             //0b1000 0011 0000  内部时钟
//#define  WDTDIS1                    0X0A            //0b1000 0000 1010  禁止看门狗

//模块接口定义
#define Ht1621_CS_PORT              (GPIOB)
#define Ht1621_CS_PIN               (GPIO_Pin_5)
#define Ht1621_WR_PORT              (GPIOB)
#define Ht1621_WR_PIN               (GPIO_Pin_6)
#define Ht1621_DAT_PORT             (GPIOB)
#define Ht1621_DAT_PIN              (GPIO_Pin_7)

//基础操作定义
void Ht1621_CS_0()                  {GPIO_Init(Ht1621_CS_PORT, Ht1621_CS_PIN, GPIO_Mode_Out_PP_Low_Fast);}
void Ht1621_CS_1()                  {GPIO_Init(Ht1621_CS_PORT, Ht1621_CS_PIN, GPIO_Mode_Out_PP_High_Fast);}
void Ht1621_WR_0()                  {GPIO_Init(Ht1621_WR_PORT, Ht1621_WR_PIN, GPIO_Mode_Out_PP_Low_Fast);}
void Ht1621_WR_1()                  {GPIO_Init(Ht1621_WR_PORT, Ht1621_WR_PIN, GPIO_Mode_Out_PP_High_Fast);}
void Ht1621_DAT_0()                 {GPIO_Init(Ht1621_DAT_PORT, Ht1621_DAT_PIN, GPIO_Mode_Out_PP_Low_Fast);}
void Ht1621_DAT_1()                 {GPIO_Init(Ht1621_DAT_PORT, Ht1621_DAT_PIN, GPIO_Mode_Out_PP_High_Fast);}


//最小量程 根据具体型号对应手册获取,单位是g,这里以RP-18.3-ST型号为例,最小量程是20g
#define PRESS_MIN   20
//最大量程 根据具体型号对应手册获取,单位是g,这里以RP-18.3-ST型号为例,最大量程是6kg
#define PRESS_MAX   5000
//以下2个参数根据获取方法:
//理论上:
// AO引脚输出的电压有效范围是0.1v到3.3v,而实际根据不同传感器范围会在这个范围内,并不一定是最大值3.3v,也可能低于3.3v,要实际万用表测量,
// 万用表测量然后修正以下2个AO引脚电压输出的最大和最小值
//调节方法:
//薄膜压力传感器的AO引脚输出的增益范围是通过板载AO_RES电位器调节实现的,
//想要稍微精准点,需要自己给定具体已知力,然后调节AO_RES电位器到串口输出重量正好是自己给定力就可以了
#define VOLTAGE_MIN 8500000
#define VOLTAGE_MAX 10000000

//定义要显示的值
unsigned int counter = 7777;
unsigned int tmp;
unsigned int n1, n2, n3, n4;
unsigned char Ht1621Tab[]={0x00,0x00,0x00,0x00};
unsigned char DispTab[]={0xEB,0x0A,0xAD,0x8F,0x4E,0xC7,0xE7,0x8A,0xEF,0xCF,0x85,0xEE, 0x67, 0xE1,0x2F,0xE5,0xE4,0x6E};
              //          0    1    2    3    4    5    6    7    8    9    三   A     B     C    D    E    F   H


float PRESS_AO = 0;
float PRESS_N = 0;
float PRESS_PA = 0;
float PRESS_MMHG = 0;
long VOLTAGE_AO = 0;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/


/*******************************************************************************
****函数名称:
****函数功能:延时函数
****入口参数:需要延时的数目
****出口参数:无
********************************************************************************/
//void Delay(uint16_t nCount)
//{ 
//    while (nCount != 0)
//    {
//        nCount--;
//    }
//} 

//使用定时器实现延时函数
void Delay(uint16_t nCount)
{
  TIM2_Init(TIM2_Prescaler_128, nCount);
  TIM2_Cmd(ENABLE); 
  while(TIM2_GetFlagStatus(TIM2_FLAG_Update) == RESET) {};
  TIM2_ClearFlag(TIM2_FLAG_Update);
  TIM2_Cmd(DISABLE);
}

/*******************************************************************************
****函数名称:
****函数功能:1621写数据函数
****入口参数:Data-要发送的数据  cnt-要发送的数据位数
********************************************************************************/
void Ht1621Wr_Data(unsigned char Data, unsigned char cnt)
{
  unsigned char i;

    for (i = 0; i < cnt; i++)
    {
        Ht1621_WR_0();
        if ((Data & 0x80) == 0x80)
        {
            Ht1621_DAT_1();
        }
        else
        {
            Ht1621_DAT_0();
        }
        Ht1621_WR_1();
        Data <<= 1;
    }
}

/*******************************************************************************
****函数名称:
****函数功能:1621写指令函数
****入口参数:Cmd 命令
********************************************************************************/
void Ht1621WrCmd(unsigned char Cmd)
{
    Ht1621_CS_0();
    /* 写入命令标志100 */
    Ht1621Wr_Data(0x80,4);
    /* 写入命令数据 */
    Ht1621Wr_Data(Cmd,8);
    Ht1621_CS_1();
}

/*******************************************************************************
****函数名称:
****函数功能:1621写一个数据函数
****入口参数:Addr--地址 Data--数据
********************************************************************************/
void Ht1621WrOneData(unsigned char Addr, unsigned char Data)
{
    Ht1621_CS_0();
    /* 写入数据标志101 */
    Ht1621Wr_Data(0xa0,3);
    /* 写入地址数据 */
    Ht1621Wr_Data(Addr << 2,6);
    /* 写入数据的前四位 7  6  5  4 */
    Ht1621Wr_Data(Data,4);
    Ht1621_CS_1();
}

/*******************************************************************************
****函数名称:
****函数功能:1621写整屏数据函数
****入口参数:Addr--地址 p--数据  cnt数据个数
********************************************************************************/
void Ht1621WrAllData(unsigned char Addr, unsigned char *p, unsigned char cnt)
{
    unsigned char i;

    Ht1621_CS_0();
    /* 写入数据标志101 */
    Ht1621Wr_Data(0xa0,3);
    /* 写入地址数据 */
    Ht1621Wr_Data(Addr << 2,6);
    for (i = 0;i < cnt; i++)
    {
        /* 写入数据 */
        Ht1621Wr_Data(*p,8);
        p++;
    }
    Ht1621_CS_1();
}

/*******************************************************************************
****函数名称:
****函数功能:1621初始化函数
********************************************************************************/
void Ht1621_Init(void)
{
    Ht1621WrCmd(BIAS);
    Ht1621WrCmd(RC256);             //使用内部振荡器
    //Ht1621WrCmd(XTAL);             //使用外部振荡器
    Ht1621WrCmd(SYSDIS);
    //Ht1621WrCmd(WDTDIS1);
    Ht1621WrCmd(SYSEN);
    Ht1621WrCmd(LCDON);
}

/*******************************************************************************
****函数名称:
****函数功能:1621显示函数
********************************************************************************/
void Display(void)
{
    Ht1621WrOneData(0 , DispTab[n3]);
    Ht1621WrOneData(1 , DispTab[n3]<<4);
    Ht1621WrOneData(2 , DispTab[n2]);
    Ht1621WrOneData(3 , DispTab[n2]<<4);
    Ht1621WrOneData(4 , DispTab[n1]);
    Ht1621WrOneData(5 , DispTab[n1]<<4);
    Ht1621WrOneData(6 , DispTab[17]);
    Ht1621WrOneData(7 , DispTab[17]<<4);
}

/*******************************************************************************
****函数名称:
****函数功能:显示符号函数
****入口参数:Addr--地址 Data--数据
********************************************************************************/
void Display_lcd_dot(void)
{
    //Ht1621WrOneData(0 , DispTab[n4]|0x10);//P1
    //Ht1621WrOneData(2 , DispTab[n3]|0x10);    //2P
    //Ht1621WrOneData(4 , DispTab[n2]|0x10);    //3P
    Ht1621WrOneData(6 , DispTab[n1]|0x10);    //4P
}

/*******************************************************************************
****函数名称:
****函数功能:数据转换函数
****入口参数:adc_value-需要转换的数值
********************************************************************************/
void data_convertor(unsigned long adc_value)
{
    tmp=adc_value;         //adc
    n4=tmp/1000;
    tmp=tmp%1000;
    n3=tmp/100;
    tmp=tmp%100;
    n2=tmp/10;
    tmp=tmp%10;
    n1=tmp;
}
/*******************************************************************************
****函数名称:
****函数功能:ADC初始化函数
****入口参数:adc_value-需要转换的数值
********************************************************************************/
//void Init_ADC(void)
//{ 
//    GPIO_Init(GPIOC, GPIO_Pin_4, GPIO_Mode_In_FL_No_IT);
//    CLK_PeripheralClockConfig(CLK_Peripheral_ADC1,ENABLE);
//    //ADC_VrefintCmd(ENABLE);
//    ADC_Init(ADC1,ADC_ConversionMode_Single,ADC_Resolution_12Bit,ADC_Prescaler_2);
//    ADC_SamplingTimeConfig(ADC1, ADC_Group_SlowChannels, ADC_SamplingTime_9Cycles);
//    ADC_Cmd(ADC1,ENABLE);
//    ADC_ChannelCmd(ADC1,ADC_Channel_4,ENABLE);
//} 

/*******************************************************************************
****函数名称:
****函数功能:取ADC转换平均值
****入口参数:times-取平均次数
********************************************************************************/
//uint16_t Get_Adc_Average(uint8_t times)
//{ 
//    uint32_t temp_val = 0;
//    uint8_t t;
//
//    for (t = 0; t < times; t++)
//    {
//        temp_val += ADC_GetConversionValue(ADC1);
//        Delay(5);
//    }
//
//    return temp_val / times;
//} 


long map(long x, long in_max, long out_max)
{
    return ((x * out_max) / in_max);
}

static unsigned long adc1_value;


void ADSK_0()                  {GPIO_ResetBits(GPIOB, GPIO_Pin_3);}
void ADSK_1()                  {GPIO_SetBits(GPIOB, GPIO_Pin_3);}

unsigned long ReadCount(void)
{
  unsigned long Count;
  unsigned char i;

  ADSK_0();
  Count = 0;
  while(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_4));
  for (i=0;i<24;i++)
  {
    ADSK_1();
    Count = Count << 1;
    ADSK_0();
  if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_4)) Count++;
  }
  ADSK_1();
  Count = Count^0x800000;
  ADSK_0();
  
  return(Count);
}

void main(void)
{
    FlagStatus flag_status;

    Delay(100);           //延时一段时间
    Ht1621_Init();        //上电初始化LCD
    Delay(100);           //延时一段时间
    Ht1621WrAllData(0,Ht1621Tab,16);// Clear LCD display

    //Init_ADC();
    
    //PWR_UltraLowPowerCmd(ENABLE);
    GPIO_Init(GPIOB, GPIO_Pin_4, GPIO_Mode_In_PU_No_IT);
    GPIO_Init(GPIOB, GPIO_Pin_3, GPIO_Mode_Out_OD_Low_Fast);

    while (1)
    {      
        adc1_value = ReadCount();
        if(adc1_value < VOLTAGE_MIN)
        {
            PRESS_MMHG = 0;
        }
        else
        {
            PRESS_MMHG = (adc1_value - VOLTAGE_MIN) / 15000;
        }

        data_convertor(PRESS_MMHG);
        Display();
        Delay(500);
        //Display_lcd_dot();
    }

}

#ifdef USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *   where the assert_param error has occurred.
  * @param file: pointer to the source file name
  * @param line: assert_param error line source number
  * @retval : None
  */
void assert_failed(u8* file, u32 line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf('Wrong parameters value: file %s on line %d\r\n', file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif

解释:

  1. 注释掉或删除ADC初始化代码: //Init_ADC(); 以及相关的ADC相关代码。
  2. 注释掉或删除禁止看门狗指令: //Ht1621WrCmd(WDTDIS1);
  3. 使用硬件定时器实现延时: 将原Delay函数替换为使用TIM2定时器的延时函数。

其他建议:

  • 降低CPU工作频率: 在STM8L15x中,可以使用CLK_PeripheralClockConfig函数来设置时钟分频器,降低CPU工作频率。
  • 使用低功耗模式: STM8L系列芯片支持多种低功耗模式,例如PWR_UltraLowPowerCmd(ENABLE);,可以根据需要选择合适的低功耗模式。
  • 优化代码逻辑: 尽量减少无用运算和代码执行,提高代码效率,进一步降低功耗。

通过这些方法,可以有效降低STM8L15x的功耗,延长设备的续航时间。

STM8L15x 低功耗代码优化建议

原文地址: https://www.cveoy.top/t/topic/nytT 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录