项目介绍
用于测量USB设备的电压、电流、功率等。在日常的硬件调试中,通过这个功率计,可以排查设备是否短路、数据线是否接触不良等问题,有按键切换功能。
量程:5~36V,0~8A
市场应用介绍
电子工程师使用,用于测量设备功耗。
项目设计思路
使用STM32G0驱动INA226,得到电流电压数据。
然后通过tft屏幕显示。
项目方案框图和原理图解释
设计中用到规定厂商的元器件介绍
1.STM32G031
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 引脚封装。
INA226 是一款分流/功率监视器,具有 I2C™或 SMBUS 兼容接口。 该器件 监视分流压降和总线电源 电压。 可编程校准值、转换时间和取平均值功能与内 部乘法器相结合,可实现电流值(单位为安培)和功率 值(单位为瓦)的直接读取。
INA226 可在 0V 至 36V 的共模总线电压范围内感测电 流,与电源电压无关。 该器件由一个 2.7V 至 5.5V 的 单电源供电,电源电流典型值为 330µA。 该器件的额 定工作温度范围为 –40°C 至 125°C,I2C 兼容接口上 具有多达 16 个可编程地址。
3.TLVH431
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);
}
}
功能展示及说明
设备正面
设备背面
第一个界面
旋转功能
第二个界面
第三个界面
连接板卡测试
对本大赛的心得体会(包括意见或建议),及整个设计过程中遇到的难点和解决方法
无