FastBond2阶段2-基于STM32G0的功率计
基于STM32G0的功率计框图设计,能够进行电流电压测量,有按键切换功能。
标签
FastBond2
STM32G0
功率计
星辰i
更新2023-10-07
1075

项目介绍

用于测量USB设备的电压、电流、功率等。在日常的硬件调试中,通过这个功率计,可以排查设备是否短路、数据线是否接触不良等问题,有按键切换功能。

量程:5~36V,0~8A


市场应用介绍

电子工程师使用,用于测量设备功耗。


项目设计思路

使用STM32G0驱动INA226,得到电流电压数据。

然后通过tft屏幕显示。


项目方案框图和原理图解释

Fpga8BaP6bNdsIv5AzlCy-2rVxOp

FnvVL4X_WmmjQ3hnZQwVCjVm0dZv

 

设计中用到规定厂商的元器件介绍

1.STM32G031

en.obn_STM32G0x1_line_LN2048.jpg

STM32G031x4/x6/x8主流微控制器基于高性能Arm Cortex-M0+ 32位RISC内核,工作频率高达64 MHz。它们具有高集成度,适用于消费、工业和家电领域的广泛应用,并为物联网 (IoT) 解决方案做好准备。

这些器件集成了存储器保护单元 (MPU)、高速嵌入式存储器(8 KB SRAM 和高达 64 KB 的闪存程序存储器,具有读保护、写保护、专有代码保护和安全区域)、DMA、广泛的系统功能、增强型 I/O 和外设。这些器件提供标准通信接口(两个I2Cs,两个 SPI / 一个 I2S和两个USART)、一个12-bit ADC (2.5 MSps)、一个内部基准电压缓冲器、一个低功耗RTC、一个以高达两倍CPU频率运行的高级控制PWM定时器、四个通用16位定时器、一个32位通用定时器、两个低功耗16位定时器、两个看门狗定时器和一个SysTick定时器。

这些器件可在 -40 至 125°C 的环境温度和 1.7 V 至 3.6 V 的电源电压下工作。 优化的动态功耗与一套全面的节能模式、低功耗定时器和低功耗UART相结合,允许设计低功耗应用。

VBAT直接电池输入允许保持RTC和备份寄存器供电。

这些器件采用 8 至 48 引脚封装。

 
2.INA226

INA226 是一款分流/功率监视器,具有 I2C™或 SMBUS 兼容接口。 该器件 监视分流压降和总线电源 电压。 可编程校准值、转换时间和取平均值功能与内 部乘法器相结合,可实现电流值(单位为安培)和功率 值(单位为瓦)的直接读取。

INA226 可在 0V 至 36V 的共模总线电压范围内感测电 流,与电源电压无关。 该器件由一个 2.7V 至 5.5V 的 单电源供电,电源电流典型值为 330µA。 该器件的额 定工作温度范围为 –40°C 至 125°C,I2C 兼容接口上 具有多达 16 个可编程地址。

 

3.TLVH431

fbd_slvs555m.gif

TLVH431 和 TLVH432 器件是低电压 3 端子可调节电压基准,在适用的工业和商业级温度范围内具有额定热稳定性。可以通过两个外部电阻器将输出电压设置为介于 VREF (1.24V) 和 18V 之间的任何值(请参阅)。这些器件具有比广泛使用的 TL431 和 TL1431 并联稳压器基准电压更低的工作电压 (1.24V)。

与光耦合器配合使用时,TLVH431 和 TLVH432 器件是适用于 3V 至 3.3V 开关模式电源的隔离式反馈电路中的理想电压基准。它们的输出阻抗典型值均为 0.25Ω。有源输出电路提供非常快速的导通特性,因此 TLVH431 和 TLVH432 器件非常适合替代许多应用中的低压齐纳二极管,包括板载稳压和可调节电源。

TLVH432 器件与 TLVH431 器件相同,但 3 引脚 SOT-23 和 SOT-89 封装的引脚排列不同。


PCB绘制打板介绍及遇到的问题和解决方法


关键代码及说明

屏幕初始化

void LCD_Init(void)
{
	
	
    LCD_RES_Clr();//复位
    HAL_Delay(100);
    LCD_RES_Set();
    HAL_Delay(100);

    //LCD_BLK_Set();//打开背光
    HAL_Delay(100);
	
	LCD_WR_REG(0x11);     //Sleep out
	HAL_Delay(120);                //Delay 120ms
	LCD_WR_REG(0xB1);     //Normal mode
	LCD_WR_DATA8(0x05);   
	LCD_WR_DATA8(0x3C);   
	LCD_WR_DATA8(0x3C);   
	LCD_WR_REG(0xB2);     //Idle mode
	LCD_WR_DATA8(0x05);   
	LCD_WR_DATA8(0x3C);   
	LCD_WR_DATA8(0x3C);   
	LCD_WR_REG(0xB3);     //Partial mode
	LCD_WR_DATA8(0x05);   
	LCD_WR_DATA8(0x3C);   
	LCD_WR_DATA8(0x3C);   
	LCD_WR_DATA8(0x05);   
	LCD_WR_DATA8(0x3C);   
	LCD_WR_DATA8(0x3C);   
	LCD_WR_REG(0xB4);     //Dot inversion
	LCD_WR_DATA8(0x03);   
	LCD_WR_REG(0xC0);     //AVDD GVDD
	LCD_WR_DATA8(0xAB);   
	LCD_WR_DATA8(0x0B);   
	LCD_WR_DATA8(0x04);   
	LCD_WR_REG(0xC1);     //VGH VGL
	LCD_WR_DATA8(0xC5);   //C0
	LCD_WR_REG(0xC2);     //Normal Mode
	LCD_WR_DATA8(0x0D);   
	LCD_WR_DATA8(0x00);   
	LCD_WR_REG(0xC3);     //Idle
	LCD_WR_DATA8(0x8D);   
	LCD_WR_DATA8(0x6A);   
	LCD_WR_REG(0xC4);     //Partial+Full
	LCD_WR_DATA8(0x8D);   
	LCD_WR_DATA8(0xEE);   
	LCD_WR_REG(0xC5);     //VCOM
	LCD_WR_DATA8(0x0F);   
	LCD_WR_REG(0xE0);     //positive gamma
	LCD_WR_DATA8(0x07);   
	LCD_WR_DATA8(0x0E);   
	LCD_WR_DATA8(0x08);   
	LCD_WR_DATA8(0x07);   
	LCD_WR_DATA8(0x10);   
	LCD_WR_DATA8(0x07);   
	LCD_WR_DATA8(0x02);   
	LCD_WR_DATA8(0x07);   
	LCD_WR_DATA8(0x09);   
	LCD_WR_DATA8(0x0F);   
	LCD_WR_DATA8(0x25);   
	LCD_WR_DATA8(0x36);   
	LCD_WR_DATA8(0x00);   
	LCD_WR_DATA8(0x08);   
	LCD_WR_DATA8(0x04);   
	LCD_WR_DATA8(0x10);   
	LCD_WR_REG(0xE1);     //negative gamma
	LCD_WR_DATA8(0x0A);   
	LCD_WR_DATA8(0x0D);   
	LCD_WR_DATA8(0x08);   
	LCD_WR_DATA8(0x07);   
	LCD_WR_DATA8(0x0F);   
	LCD_WR_DATA8(0x07);   
	LCD_WR_DATA8(0x02);   
	LCD_WR_DATA8(0x07);   
	LCD_WR_DATA8(0x09);   
	LCD_WR_DATA8(0x0F);   
	LCD_WR_DATA8(0x25);   
	LCD_WR_DATA8(0x35);   
	LCD_WR_DATA8(0x00);   
	LCD_WR_DATA8(0x09);   
	LCD_WR_DATA8(0x04);   
	LCD_WR_DATA8(0x10);
		 
    LCD_WR_REG(0x36);
	if(USE_HORIZONTAL==0)LCD_WR_DATA8(0x08);
	else if(USE_HORIZONTAL==1)LCD_WR_DATA8(0xC8);
	else if(USE_HORIZONTAL==2)LCD_WR_DATA8(0x78);
	else LCD_WR_DATA8(0xA8);   
	LCD_WR_REG(0xFC);    
	LCD_WR_DATA8(0x80);  
		
	LCD_WR_REG(0x3A);     
	LCD_WR_DATA8(0x05);   
	LCD_WR_REG(0x36);
	if(USE_HORIZONTAL==0)LCD_WR_DATA8(0x08);
	else if(USE_HORIZONTAL==1)LCD_WR_DATA8(0xC8);
	else if(USE_HORIZONTAL==2)LCD_WR_DATA8(0x78);
	else LCD_WR_DATA8(0xA8);   
    
	LCD_WR_REG(0x21);     //Display inversion
//	LCD_WR_REG(0x29);     //Display on
    
    u16 i,j; 
	LCD_Address_Set(0,0,LCD_W-1,LCD_H-1);//设置显示范围
	for(i=0;i<LCD_H;i++)
	{													   	 	
		for(j=0;j<LCD_W;j++)
		{
			LCD_WR_DATA8(0);
            LCD_WR_DATA8(0);
		}
	}

    LCD_WR_REG(0x29);     //Display on
}

 

屏幕驱动

#include "lcd.h"
#include "lcd_init.h"
#include "lcdfont.h"



/******************************************************************************
      函数说明:在指定区域填充颜色
      入口数据:xsta,ysta   起始坐标
                xend,yend   终止坐标
								color       要填充的颜色
      返回值:  无
******************************************************************************/
void LCD_Fill(u16 xsta,u16 ysta,u16 xend,u16 yend,u16 color)
{          
	u16 i,j; 
	LCD_Address_Set(xsta,ysta,xend-1,yend-1);//设置显示范围
	for(i=ysta;i<yend;i++)
	{													   	 	
		for(j=xsta;j<xend;j++)
		{
			LCD_WR_DATA(color);
		}
	} 					  	    
}

/******************************************************************************
      函数说明:在指定位置画点
      入口数据:x,y 画点坐标
                color 点的颜色
      返回值:  无
******************************************************************************/
void LCD_DrawPoint(u16 x,u16 y,u16 color)
{
	LCD_Address_Set(x,y,x,y);//设置光标位置 
	LCD_WR_DATA(color);
} 


/******************************************************************************
      函数说明:画线
      入口数据:x1,y1   起始坐标
                x2,y2   终止坐标
                color   线的颜色
      返回值:  无
******************************************************************************/
void LCD_DrawLine(u16 x1,u16 y1,u16 x2,u16 y2,u16 color)
{
	u16 t; 
	int xerr=0,yerr=0,delta_x,delta_y,distance;
	int incx,incy,uRow,uCol;
	delta_x=x2-x1; //计算坐标增量 
	delta_y=y2-y1;
	uRow=x1;//画线起点坐标
	uCol=y1;
	if(delta_x>0)incx=1; //设置单步方向 
	else if (delta_x==0)incx=0;//垂直线 
	else {incx=-1;delta_x=-delta_x;}
	if(delta_y>0)incy=1;
	else if (delta_y==0)incy=0;//水平线 
	else {incy=-1;delta_y=-delta_y;}
	if(delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴 
	else distance=delta_y;
	for(t=0;t<distance+1;t++)
	{
		LCD_DrawPoint(uRow,uCol,color);//画点
		xerr+=delta_x;
		yerr+=delta_y;
		if(xerr>distance)
		{
			xerr-=distance;
			uRow+=incx;
		}
		if(yerr>distance)
		{
			yerr-=distance;
			uCol+=incy;
		}
	}
}


/******************************************************************************
      函数说明:画矩形
      入口数据:x1,y1   起始坐标
                x2,y2   终止坐标
                color   矩形的颜色
      返回值:  无
******************************************************************************/
void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2,u16 color)
{
	LCD_DrawLine(x1,y1,x2,y1,color);
	LCD_DrawLine(x1,y1,x1,y2,color);
	LCD_DrawLine(x1,y2,x2,y2,color);
	LCD_DrawLine(x2,y1,x2,y2,color);
}


/******************************************************************************
      函数说明:画圆
      入口数据:x0,y0   圆心坐标
                r       半径
                color   圆的颜色
      返回值:  无
******************************************************************************/
void Draw_Circle(u16 x0,u16 y0,u8 r,u16 color)
{
	int a,b;
	a=0;b=r;	  
	while(a<=b)
	{
		LCD_DrawPoint(x0-b,y0-a,color);             //3           
		LCD_DrawPoint(x0+b,y0-a,color);             //0           
		LCD_DrawPoint(x0-a,y0+b,color);             //1                
		LCD_DrawPoint(x0-a,y0-b,color);             //2             
		LCD_DrawPoint(x0+b,y0+a,color);             //4               
		LCD_DrawPoint(x0+a,y0-b,color);             //5
		LCD_DrawPoint(x0+a,y0+b,color);             //6 
		LCD_DrawPoint(x0-b,y0+a,color);             //7
		a++;
		if((a*a+b*b)>(r*r))//判断要画的点是否过远
		{
			b--;
		}
	}
}

/******************************************************************************
      函数说明:显示汉字串
      入口数据:x,y显示坐标
                *s 要显示的汉字串
                fc 字的颜色
                bc 字的背景色
                sizey 字号 可选 16 24 32
                mode:  0非叠加模式  1叠加模式
      返回值:  无
******************************************************************************/
void LCD_ShowChinese(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode)
{
	while(*s!=0)
	{
		if(sizey==12) LCD_ShowChinese12x12(x,y,s,fc,bc,sizey,mode);
		else if(sizey==16) LCD_ShowChinese16x16(x,y,s,fc,bc,sizey,mode);
		else if(sizey==24) LCD_ShowChinese24x24(x,y,s,fc,bc,sizey,mode);
		else if(sizey==32) LCD_ShowChinese32x32(x,y,s,fc,bc,sizey,mode);
		else return;
		s+=2;
		x+=sizey;
	}
}

/******************************************************************************
      函数说明:显示单个12x12汉字
      入口数据:x,y显示坐标
                *s 要显示的汉字
                fc 字的颜色
                bc 字的背景色
                sizey 字号
                mode:  0非叠加模式  1叠加模式
      返回值:  无
******************************************************************************/
void LCD_ShowChinese12x12(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode)
{
	u8 i,j,m=0;
	u16 k;
	u16 HZnum;//汉字数目
	u16 TypefaceNum;//一个字符所占字节大小
	u16 x0=x;
	TypefaceNum=(sizey/8+((sizey%8)?1:0))*sizey;
	                         
	HZnum=sizeof(tfont12)/sizeof(typFNT_GB12);	//统计汉字数目
	for(k=0;k<HZnum;k++) 
	{
		if((tfont12[k].Index[0]==*(s))&&(tfont12[k].Index[1]==*(s+1)))
		{ 	
			LCD_Address_Set(x,y,x+sizey-1,y+sizey-1);
			for(i=0;i<TypefaceNum;i++)
			{
				for(j=0;j<8;j++)
				{	
					if(!mode)//非叠加方式
					{
						if(tfont12[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc);
						else LCD_WR_DATA(bc);
						m++;
						if(m%sizey==0)
						{
							m=0;
							break;
						}
					}
					else//叠加方式
					{
						if(tfont12[k].Msk[i]&(0x01<<j))	LCD_DrawPoint(x,y,fc);//画一个点
						x++;
						if((x-x0)==sizey)
						{
							x=x0;
							y++;
							break;
						}
					}
				}
			}
		}				  	
		continue;  //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
	}
} 

/******************************************************************************
      函数说明:显示单个16x16汉字
      入口数据:x,y显示坐标
                *s 要显示的汉字
                fc 字的颜色
                bc 字的背景色
                sizey 字号
                mode:  0非叠加模式  1叠加模式
      返回值:  无
******************************************************************************/
void LCD_ShowChinese16x16(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode)
{
	u8 i,j,m=0;
	u16 k;
	u16 HZnum;//汉字数目
	u16 TypefaceNum;//一个字符所占字节大小
	u16 x0=x;
  TypefaceNum=(sizey/8+((sizey%8)?1:0))*sizey;
	HZnum=sizeof(tfont16)/sizeof(typFNT_GB16);	//统计汉字数目
	for(k=0;k<HZnum;k++) 
	{
		if ((tfont16[k].Index[0]==*(s))&&(tfont16[k].Index[1]==*(s+1)))
		{ 	
			LCD_Address_Set(x,y,x+sizey-1,y+sizey-1);
			for(i=0;i<TypefaceNum;i++)
			{
				for(j=0;j<8;j++)
				{	
					if(!mode)//非叠加方式
					{
						if(tfont16[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc);
						else LCD_WR_DATA(bc);
						m++;
						if(m%sizey==0)
						{
							m=0;
							break;
						}
					}
					else//叠加方式
					{
						if(tfont16[k].Msk[i]&(0x01<<j))	LCD_DrawPoint(x,y,fc);//画一个点
						x++;
						if((x-x0)==sizey)
						{
							x=x0;
							y++;
							break;
						}
					}
				}
			}
		}				  	
		continue;  //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
	}
} 


/******************************************************************************
      函数说明:显示单个24x24汉字
      入口数据:x,y显示坐标
                *s 要显示的汉字
                fc 字的颜色
                bc 字的背景色
                sizey 字号
                mode:  0非叠加模式  1叠加模式
      返回值:  无
******************************************************************************/
void LCD_ShowChinese24x24(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode)
{
	u8 i,j,m=0;
	u16 k;
	u16 HZnum;//汉字数目
	u16 TypefaceNum;//一个字符所占字节大小
	u16 x0=x;
	TypefaceNum=(sizey/8+((sizey%8)?1:0))*sizey;
	HZnum=sizeof(tfont24)/sizeof(typFNT_GB24);	//统计汉字数目
	for(k=0;k<HZnum;k++) 
	{
		if ((tfont24[k].Index[0]==*(s))&&(tfont24[k].Index[1]==*(s+1)))
		{ 	
			LCD_Address_Set(x,y,x+sizey-1,y+sizey-1);
			for(i=0;i<TypefaceNum;i++)
			{
				for(j=0;j<8;j++)
				{	
					if(!mode)//非叠加方式
					{
						if(tfont24[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc);
						else LCD_WR_DATA(bc);
						m++;
						if(m%sizey==0)
						{
							m=0;
							break;
						}
					}
					else//叠加方式
					{
						if(tfont24[k].Msk[i]&(0x01<<j))	LCD_DrawPoint(x,y,fc);//画一个点
						x++;
						if((x-x0)==sizey)
						{
							x=x0;
							y++;
							break;
						}
					}
				}
			}
		}				  	
		continue;  //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
	}
} 

/******************************************************************************
      函数说明:显示单个32x32汉字
      入口数据:x,y显示坐标
                *s 要显示的汉字
                fc 字的颜色
                bc 字的背景色
                sizey 字号
                mode:  0非叠加模式  1叠加模式
      返回值:  无
******************************************************************************/
void LCD_ShowChinese32x32(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode)
{
	u8 i,j,m=0;
	u16 k;
	u16 HZnum;//汉字数目
	u16 TypefaceNum;//一个字符所占字节大小
	u16 x0=x;
	TypefaceNum=(sizey/8+((sizey%8)?1:0))*sizey;
	HZnum=sizeof(tfont32)/sizeof(typFNT_GB32);	//统计汉字数目
	for(k=0;k<HZnum;k++) 
	{
		if ((tfont32[k].Index[0]==*(s))&&(tfont32[k].Index[1]==*(s+1)))
		{ 	
			LCD_Address_Set(x,y,x+sizey-1,y+sizey-1);
			for(i=0;i<TypefaceNum;i++)
			{
				for(j=0;j<8;j++)
				{	
					if(!mode)//非叠加方式
					{
						if(tfont32[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc);
						else LCD_WR_DATA(bc);
						m++;
						if(m%sizey==0)
						{
							m=0;
							break;
						}
					}
					else//叠加方式
					{
						if(tfont32[k].Msk[i]&(0x01<<j))	LCD_DrawPoint(x,y,fc);//画一个点
						x++;
						if((x-x0)==sizey)
						{
							x=x0;
							y++;
							break;
						}
					}
				}
			}
		}				  	
		continue;  //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
	}
}


/******************************************************************************
      函数说明:显示单个字符
      入口数据:x,y显示坐标
                num 要显示的字符
                fc 字的颜色
                bc 字的背景色
                sizey 字号
                mode:  0非叠加模式  1叠加模式
      返回值:  无
******************************************************************************/
void LCD_ShowChar(u16 x,u16 y,u8 num,u16 fc,u16 bc,u8 sizey,u8 mode)
{
	u8 temp,sizex,t,m=0;
	u16 i,TypefaceNum;//一个字符所占字节大小
	u16 x0=x;
	sizex=sizey/2;
	TypefaceNum=(sizex/8+((sizex%8)?1:0))*sizey;
	num=num-' ';    //得到偏移后的值
	LCD_Address_Set(x,y,x+sizex-1,y+sizey-1);  //设置光标位置 
	for(i=0;i<TypefaceNum;i++)
	{ 
		if(sizey==12)temp=ascii_1206[num][i];		       //调用6x12字体
		else if(sizey==16)temp=ascii_1608[num][i];		 //调用8x16字体
		else if(sizey==24)temp=ascii_2412[num][i];		 //调用12x24字体
		else if(sizey==32)temp=ascii_3216[num][i];		 //调用16x32字体
		else return;
		for(t=0;t<8;t++)
		{
			if(!mode)//非叠加模式
			{
				if(temp&(0x01<<t))LCD_WR_DATA(fc);
				else LCD_WR_DATA(bc);
				m++;
				if(m%sizex==0)
				{
					m=0;
					break;
				}
			}
			else//叠加模式
			{
				if(temp&(0x01<<t))LCD_DrawPoint(x,y,fc);//画一个点
				x++;
				if((x-x0)==sizex)
				{
					x=x0;
					y++;
					break;
				}
			}
		}
	}   	 	  
}


/******************************************************************************
      函数说明:显示字符串
      入口数据:x,y显示坐标
                *p 要显示的字符串
                fc 字的颜色
                bc 字的背景色
                sizey 字号
                mode:  0非叠加模式  1叠加模式
      返回值:  无
******************************************************************************/
void LCD_ShowString(u16 x,u16 y,const u8 *p,u16 fc,u16 bc,u8 sizey,u8 mode)
{         
	while(*p!='\0')
	{       
		LCD_ShowChar(x,y,*p,fc,bc,sizey,mode);
		x+=sizey/2;
		p++;
	}  
}


/******************************************************************************
      函数说明:显示数字
      入口数据:m底数,n指数
      返回值:  无
******************************************************************************/
u32 mypow(u8 m,u8 n)
{
	u32 result=1;	 
	while(n--)result*=m;
	return result;
}


/******************************************************************************
      函数说明:显示整数变量
      入口数据:x,y显示坐标
                num 要显示整数变量
                len 要显示的位数
                fc 字的颜色
                bc 字的背景色
                sizey 字号
      返回值:  无
******************************************************************************/
void LCD_ShowIntNum(u16 x,u16 y,u16 num,u8 len,u16 fc,u16 bc,u8 sizey)
{         	
	u8 t,temp;
	u8 sizex=sizey/2;
	for(t=0;t<len;t++)
	{
		temp=(num/mypow(10,len-t-1))%10;
	 	LCD_ShowChar(x+t*sizex,y,temp+48,fc,bc,sizey,0);
	}
} 


/******************************************************************************
      函数说明:显示两位小数变量
      入口数据:x,y显示坐标
                num 要显示小数变量
                len 要显示的位数
                fc 字的颜色
                bc 字的背景色
                sizey 字号
      返回值:  无
******************************************************************************/
void LCD_ShowFloatNum1(u16 x,u16 y,float num,u8 len,u16 fc,u16 bc,u8 sizey)
{         	
	u8 t,temp,sizex;
	u16 num1;
	sizex=sizey/2;
	num1=num*100;
	for(t=0;t<len;t++)
	{
		temp=(num1/mypow(10,len-t-1))%10;
		if(t==(len-2))
		{
			LCD_ShowChar(x+(len-2)*sizex,y,'.',fc,bc,sizey,0);
			t++;
			len+=1;
		}
	 	LCD_ShowChar(x+t*sizex,y,temp+48,fc,bc,sizey,0);
	}
}

void  LCD_ShowFloatNum(u16 x,u16 y,float num,u8 len,u16 fc,u16 bc,u8 sizey)
{         	
	u8 t,temp,sizex;
	u16 num1;
	sizex=sizey/2;
	num1=num*1000;
	for(t=0;t<len;t++)
	{
		temp=(num1/mypow(10,len-t-1))%10;
		if(t==(len-3))
		{
			LCD_ShowChar(x+(len-3)*sizex,y,'.',fc,bc,sizey,0);
			t++;
			len+=1;
		}
	 	LCD_ShowChar(x+t*sizex,y,temp+48,fc,bc,sizey,0);
	}
}
void  LCD_ShowFloatNum4(u16 x,u16 y,float num,u8 len,u16 fc,u16 bc,u8 sizey)
{         	
	u8 t,temp,sizex;
	u16 num1;
	sizex=sizey/2;
	num1=num*10000;
	for(t=0;t<len;t++)
	{
		temp=(num1/mypow(10,len-t-1))%10;
		if(t==(len-3))
		{
			LCD_ShowChar(x+(len-4)*sizex,y,'.',fc,bc,sizey,0);
			t++;
			len+=1;
		}
	 	LCD_ShowChar(x+t*sizex,y,temp+48,fc,bc,sizey,0);
	}
}

/******************************************************************************
      函数说明:显示图片
      入口数据:x,y起点坐标
                length 图片长度
                width  图片宽度
                pic[]  图片数组    
      返回值:  无
******************************************************************************/
void LCD_ShowPicture(u16 x,u16 y,u16 length,u16 width,const u8 pic[])
{
	u16 i,j;
	u32 k=0;
	LCD_Address_Set(x,y,x+length-1,y+width-1);
	for(i=0;i<length;i++)
	{
		for(j=0;j<width;j++)
		{
			LCD_WR_DATA8(pic[k*2]);
			LCD_WR_DATA8(pic[k*2+1]);
			k++;
		}
	}			
}

void LCD_Clear()
{          
	u16 i,j; 
	LCD_Address_Set(0,0,LCD_W-1,LCD_H-1);//设置显示范围
	for(i=0;i<LCD_H;i++)
	{													   	 	
		for(j=0;j<LCD_W;j++)
		{
			LCD_WR_DATA(0);
		}
	} 					  	    
}

 

INA226驱动

#include "ina226.h"
#include "i2c.h"

static HAL_StatusTypeDef INA226_write(uint16_t MemAddress, uint16_t value)
{
	uint8_t data[2] = {(uint8_t)(value>>8), (uint8_t)(value & 0xff)};
	return HAL_I2C_Mem_Write(&hi2c2, INA226_ADDRESS, MemAddress, I2C_MEMADD_SIZE_8BIT, data, 2, 0xff);
}

static HAL_StatusTypeDef INA226_read(uint16_t MemAddress, uint8_t *data)
{
	return HAL_I2C_Mem_Read(&hi2c2, INA226_ADDRESS, MemAddress, I2C_MEMADD_SIZE_8BIT, data, 2, 0xff);
}

void INA226_Init(void)
{
    
    /*
	* 设置转换时间8.244ms,求平均值次数16,设置模式为分流和总线连续模式
	* 总数据转换时间 = 8.244*16 = 131.9ms 
	*/
    INA226_write(INA226_REG_CONFIG, 0x45ff);
    /*
	* 分流电阻最大电压 = 32768 * 0.0000025V = 0.08192V
	* 设置分流电压转电流转换参数:电阻0.01R,分辨率0.2mA
	* 公式1
	* Current_LSB = 预期最大电流 / 2^15
	* Current_LSB = 5 / 32768 = 0.000152A ,选0.2ma
	* 公式2
	* CAL = 0.00512/(Current_LSB*R)
	* CAL = 0.00512/(0.0002*0.01)=2560 = 0x0a00
	*/
	INA226_write(INA226_REG_CALIB, 0x0a00);
}

float INA226_Get_BusVoltage(void)
{
	uint8_t data0[2];
	uint16_t data1;
	float BusVoltage;
	INA226_read(INA226_REG_BUSV, data0);
	data1 = ((data0[0]<<8) | (data0[1]));// >> 3;
	BusVoltage = (float)data1 * 0.00125f;// * 4 / 1000;
	return BusVoltage;
}

float INA226_Get_Power(void)
{
	uint8_t data0[2];
	uint16_t data1;
	float Power;
	INA226_read(INA226_REG_POWER, data0);
	data1 = (data0[0]<<8) | (data0[1]);
	Power = (float)data1 * 0.005f;// * 20 * 0.000244140625;
	return Power;
}

float INA226_Get_Current(void)
{
	uint8_t data0[2];
	uint16_t data1;
	float Current;
	INA226_read(INA226_REG_CURRENT, data0);
	data1 = (data0[0]<<8) | (data0[1]);
    
    if(data1 >= 0x8000)	data1 = 0;
	Current = data1 * 0.0002f;/*电流的LSB = 0.2mA,由用户配置*/
	return Current;
}

 

显示部分

void display()
{
    if(Page_One==1)
    {
        if(m)
        {
            LCD_Fill(0,0,LCD_W,LCD_H,BLACK);
            m=m-1;
        }

        LCD_ShowString(16,0,"U:",BROWN,BLACK,24,1);//显示字符串
        LCD_ShowFloatNum(42,0, INA226_Get_BusVoltage(),5, BROWN ,BLACK,24);
        LCD_ShowChar(122,0,'V',BROWN,BLACK,24,1);

        LCD_ShowString(16,26,"I:",BLUE,BLACK,24,1);//显示字符串
        LCD_ShowFloatNum(42,26,INA226_Get_Current(),5,BLUE ,BLACK,24);
        LCD_ShowChar(122,26,'A',BLUE,BLACK,24,1);

        LCD_ShowString(16,52,"P:",LIGHTGREEN,BLACK,24,1);//显示字符串
        LCD_ShowFloatNum(42,52,INA226_Get_Power(),5,LIGHTGREEN,BLACK,24);
        LCD_ShowChar(122,52,'W',LIGHTGREEN,BLACK,24,1);
    }
    else if( Page_One==2)
    {
        if(m)
        {
            LCD_Fill(0,0,LCD_W,LCD_H,BLACK);
            m=m-1;
        }

        LCD_ShowChinese(0,0,"最大功率",BROWN,BLACK,16,1);
        LCD_ShowChar(64,0,':',BROWN,BLACK,16,1);
        LCD_ShowFloatNum(80,0,Power_Max,5,BROWN,BLACK,16);
        LCD_ShowChar(136,0,'W',BROWN,BLACK,16,1);

        LCD_ShowChinese(0,20,"开机时间", LGRAY,BLACK,16,1);
        LCD_ShowChar(64,20,':',LGRAY,BLACK,16,1);
        LCD_ShowIntNum(80,20,hour,2,LGRAY,BLACK,16);
        LCD_ShowChar(96,20,':',LGRAY,BLACK,16,1);
        LCD_ShowIntNum(104,20,mintue,2,LGRAY,BLACK,16);
        LCD_ShowChar(120,20,':',LGRAY,BLACK,16,1);
        LCD_ShowIntNum(128,20,sec,2,LGRAY,BLACK,16);

        LCD_ShowChinese(0,40,"充电容量",LIGHTGREEN,BLACK,16,1);
        LCD_ShowChar(64,40,':',LIGHTGREEN,BLACK,16,1);
        LCD_ShowIntNum(80,40,mAH,5,LIGHTGREEN,BLACK,16);
        LCD_ShowString(120,40,"mAH",LIGHTGREEN,BLACK,16,1);//显示字符串

        LCD_ShowChinese(0,60,"最大温度",LGRAYBLUE,BLACK,16,1);
        LCD_ShowChar(64,60,':',LGRAYBLUE,BLACK,16,1);
        LCD_ShowFloatNum1(80,60,Temperature_Max,4,LGRAYBLUE,BLACK,16);
        LCD_ShowChar(128,60-3,'o',LGRAYBLUE,BLACK,12,1); 
        LCD_ShowChar(128+7,60,'C',LGRAYBLUE,BLACK,16,1);
    }
    else if( Page_One==3)
    {
        if(m)
        {
            LCD_Fill(0,0,LCD_W,LCD_H,BLACK);
            m=m-1;
        }

        LCD_ShowFloatNum(0,0, INA226_Get_BusVoltage(),5, BROWN ,BLACK,24);
        LCD_ShowChar(72,0,'V',BROWN,BLACK,24,1);
        LCD_ShowFloatNum(0,26,INA226_Get_Current(),5,BLUE ,BLACK,24);
        LCD_ShowChar(72,26,'A',BLUE,BLACK,24,1);
        LCD_ShowFloatNum(0,52,INA226_Get_Power(),5,LIGHTGREEN,BLACK,24);
        LCD_ShowChar(72,52,'W',LIGHTGREEN,BLACK,24,1);

        LCD_DrawLine(90,0,90,80,LGRAY);

        LCD_ShowIntNum(96,0,mAH,5,LIGHTGREEN,BLACK,16);
        LCD_ShowString(136,0,"mAH",LIGHTGREEN,BLACK,16,1);//显示字符串
        LCD_ShowIntNum(96,20,mwh,5,LBBLUE,BLACK,16);
        LCD_ShowString(136,20,"mWH",LBBLUE,BLACK,16,1);//显示字符串

        LCD_ShowIntNum(96,40,hour,2,LGRAY,BLACK,16);
        LCD_ShowChar(112,40,':',LGRAY,BLACK,16,1);
        LCD_ShowIntNum(120,40,mintue,2,LGRAY,BLACK,16);
        LCD_ShowChar(136,40,':',LGRAY,BLACK,16,1);
        LCD_ShowIntNum(144,40,sec,2,LGRAY,BLACK,16);

        LCD_ShowFloatNum1(96,60,Get_Temperature(),4,LGRAYBLUE,BLACK,16);
        LCD_ShowChar(144,60-3,'o',LGRAYBLUE,BLACK,12,1); 
        LCD_ShowChar(144+7,60,'C',LGRAYBLUE,BLACK,16,1);
    }

    if(Page_Two)
    {
        if(m)
        {
            LCD_Fill(0,0,LCD_W,LCD_H,BLACK);
            m=m-1;
        }

        LCD_WR_REG(0x36);
        LCD_WR_DATA8(0xA8);
    }
    else
    {
        if(m)
        {
            LCD_Fill(0,0,LCD_W,LCD_H,BLACK);
            m=m-1;
        }
        LCD_WR_REG(0x36);
        LCD_WR_DATA8(0x78);
    }
}


功能展示及说明

设备正面

FkILWlHd2F-nVcs8FPy3U7eFDpip

设备背面

Fu93gO3mF1VL_85QYm1vZA3I1tuq

第一个界面

FrmW6k19fRVWiw_bQXR2ffIDyI3T

旋转功能

FsrPo55HTyVTV6e0RSJ3e0-AWJSC

第二个界面

Fgyb164anj416d1JN_sV-uMpZsU9

第三个界面

FrFVXUyJLttS3hVNMSXSLxhQlngN

连接板卡测试

Fm_Q6PRqT3GoQ1C5eVF99i-RBbzI


对本大赛的心得体会(包括意见或建议),及整个设计过程中遇到的难点和解决方法

软硬件
电路图
附件下载
功率计.zip
PCB
代码.zip
团队介绍
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号