STM8L15 芯片程序低功耗优化:IAR 软件代码改进
STM8L15 芯片程序低功耗优化:IAR 软件代码改进
为了实现低功耗,可以采取以下措施:
-
优化初始化:将不必要的初始化删除或延迟到需要使用的时候再进行初始化。
-
优化循环体:减小延时时间,减少不必要的计算和操作,尽可能缩短循环时间。
-
使用低功耗模式:使用芯片提供的低功耗模式,如 STM8L15x 芯片的 Ultra Low Power 模式。
-
关闭不必要的外设:在需要使用的时候再打开外设,用完后再关闭,减少功耗。
-
优化算法:在保证功能的前提下,尽可能采用更加高效的算法,减少计算和存储的开销。
下面是对代码的优化示例:
- 删除不必要的初始化。
将 'Ht1621_Init()' 和 'Init_ADC()' 两个函数删除,因为在主函数中并没有用到这两个函数。
- 优化循环体。
将 'Delay(500)' 改为 'Delay(50)',减小延时时间,使循环速度更快。
- 使用低功耗模式。
在主函数中加入以下代码,实现芯片进入 Ultra Low Power 模式:
PWR_UltraLowPowerCmd(ENABLE);
- 关闭不必要的外设。
在主函数中将 ADC 的初始化代码注释掉,因为没有使用 ADC。
- 优化算法。
在将电压转换成压力值的代码中,将除法运算改为乘法运算,加快运算速度。
修改后的代码如下:
/* 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
原文地址: https://www.cveoy.top/t/topic/nyue 著作权归作者所有。请勿转载和采集!