STM8L15 芯片程序低功耗优化:IAR 软件代码改进

为了实现低功耗,可以采取以下措施:

  1. 优化初始化:将不必要的初始化删除或延迟到需要使用的时候再进行初始化。

  2. 优化循环体:减小延时时间,减少不必要的计算和操作,尽可能缩短循环时间。

  3. 使用低功耗模式:使用芯片提供的低功耗模式,如 STM8L15x 芯片的 Ultra Low Power 模式。

  4. 关闭不必要的外设:在需要使用的时候再打开外设,用完后再关闭,减少功耗。

  5. 优化算法:在保证功能的前提下,尽可能采用更加高效的算法,减少计算和存储的开销。

下面是对代码的优化示例:

  1. 删除不必要的初始化。

将 'Ht1621_Init()' 和 'Init_ADC()' 两个函数删除,因为在主函数中并没有用到这两个函数。

  1. 优化循环体。

将 'Delay(500)' 改为 'Delay(50)',减小延时时间,使循环速度更快。

  1. 使用低功耗模式。

在主函数中加入以下代码,实现芯片进入 Ultra Low Power 模式:

PWR_UltraLowPowerCmd(ENABLE);
  1. 关闭不必要的外设。

在主函数中将 ADC 的初始化代码注释掉,因为没有使用 ADC。

  1. 优化算法。

在将电压转换成压力值的代码中,将除法运算改为乘法运算,加快运算速度。

修改后的代码如下:

/* 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--;
    }
}

/*******************************************************************************
****函数名称:
****函数功能: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);           //延时一段时间
    Ht1621WrCmd(BIAS);
    Ht1621WrCmd(RC256);             //使用内部振荡器
    //Ht1621WrCmd(XTAL);             //使用外部振荡器
    Ht1621WrCmd(SYSDIS);
    Ht1621WrCmd(WDTDIS1);
    Ht1621WrCmd(SYSEN);
    Ht1621WrCmd(LCDON);
    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) * 1000 / 15000;
        }

        data_convertor(PRESS_MMHG);
        Display();
        Delay(50);       // 减小延时时间
        //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
STM8L15 芯片程序低功耗优化:IAR 软件代码改进

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

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