月光如盐 发表于 2024-3-14 08:57:05

8H3K64S2单片机制作OLED12832, USB电压电流容量表

本设计为了方便的观察手机及其他设备充电时所输出的电流电压大小,
可进行功耗、充电时间、及充电容量的计算。
参数:输入电压:5-25v,输入电流0-3A


设计说明:
采用8H3K64S2单片机的12位adc进行电压及电流


的采样,用0.91英寸的OLED屏幕来进行显示。
用嘉立创eda进行设计。先看成品如下(具体见附件哈哈):


原理图:


PCB图:




代码部分截图(具体见附件):

#include "STC8xxxx.H"
#include "oled.h"
#include "bmp.h"
#include      "config.h"
#include      "adc.h"
#include      "gpio.h"
#include      "delay.h"

#define N 8      //ADC采样使用递推平均滤波算法,采样次数
                u8      i;
      u16      j;
         u32 sum=0;//数值和
                u32 sum1=0;//数值和
                u16 cut=0;//采样次数
         u16 cu=0;//平均数
                        u16 ca=0;//平均数
                         u16 u1=0;
   u16 u2=0;
    u16 u3=0;
   u16 a1=0;
   u16 a2=0;
   u16 a3=0;


/*************      功能说明      **************

本例程基于STC8H8K64U为主控芯片的实验箱8进行编写测试,STC8G、STC8H系列芯片可通用参考.

本程序演示多路ADC查询采样,通过串口2发送给上位机,波特率115200,N,8,1。

下载时, 选择时钟 22.1184MHz (可以在配置文件"config.h"中修改).

******************************************/


/*************      本地常量声明      **************/
unsigned intADC_Buf;                //采样数组mA
unsigned char num,ADCcount=0,ADCcount2=0;      //ADC采样次数变量

/*************      本地变量声明      **************/


/*************      本地函数声明      **************/


/*************外部函数和变量声明 *****************/


/******************* IO配置函数 *******************/
void      GPIO_config(void)
{
      GPIO_InitTypeDef      GPIO_InitStructure;                //结构定义
      //AD口设置为输入口
      GPIO_InitStructure.Pin= GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;                //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
      GPIO_InitStructure.Mode = GPIO_HighZ;      //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
      GPIO_Inilize(GPIO_P1,&GPIO_InitStructure);      //初始化

      GPIO_InitStructure.Pin= GPIO_Pin_6 | GPIO_Pin_7;                //指定要初始化的IO, GPIO_Pin_0 ~ GPIO_Pin_7
      GPIO_InitStructure.Mode = GPIO_PullUp;      //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
      GPIO_Inilize(GPIO_P4,&GPIO_InitStructure);      //初始化
}

/******************* AD配置函数 *******************/
void      ADC_config(void)
{
      ADC_InitTypeDef                ADC_InitStructure;                //结构定义
      ADC_InitStructure.ADC_SMPduty   = 31;                //ADC 模拟信号采样时间控制, 0~31(注意: SMPDUTY 一定不能设置小于 10)
      ADC_InitStructure.ADC_CsSetup   = 0;                //ADC 通道选择时间控制 0(默认),1
      ADC_InitStructure.ADC_CsHold    = 1;                //ADC 通道选择保持时间控制 0,1(默认),2,3
      ADC_InitStructure.ADC_Speed   = ADC_SPEED_2X1T;                //设置 ADC 工作时钟频率      ADC_SPEED_2X1T~ADC_SPEED_2X16T
      ADC_InitStructure.ADC_Power   = ENABLE;                              //ADC功率允许/关闭      ENABLE,DISABLE
      ADC_InitStructure.ADC_AdjResult = ADC_RIGHT_JUSTIFIED;      //ADC结果调整,      ADC_LEFT_JUSTIFIED,ADC_RIGHT_JUSTIFIED
      ADC_InitStructure.ADC_Priority    = Priority_0;                        //指定中断优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
      ADC_InitStructure.ADC_Interrupt = DISABLE;                        //中断允许      ENABLE,DISABLE
      ADC_Inilize(&ADC_InitStructure);                                        //初始化
      ADC_PowerControl(ENABLE);                                                      //单独的ADC电源操作函数, ENABLE或DISABLE
}
void      ADCCL(void)
{


      if(cut<20000)
      {                  
      Get_ADCResult(1);//电流
      Get_ADCResult(2); //电压
      sum1+=Get_ADCResult(1);
      sum+=Get_ADCResult(2);

      cut++;
      
      }
      if(cut>=20000)
          {
         cu=sum/20000;
         ca=sum1/20000;
         sum=0;
         sum1=0;
         cut=0;
            cu=cu*0.902077193; //ADC平均值转化成电压值
                //      OLED_ShowNum(0,2,cu,7,16);
                   u1=cu/100;      //
                         OLED_ShowNum(0,0,u1,2,16);//整数部分电压值
                   u2=cu%100/10;
                        OLED_ShowNum(20,0,u2,1,16);         //小数部分1位电压值                  
                        u3=cu%1000;                                       
                        OLED_ShowNum(28,0,u3,1,16);         ////小数部分2位电压值
               
                         ca=ca*0.20143615924092;      //ADC平均值转化成mA电流值
                         a1=ca/100;      //
                         OLED_ShowNum(75,0,a1,2,16);//整数部分电流值
                   a2=ca%100/10;
                        OLED_ShowNum(95,0,a2,1,16);         //小数部分1位电电流值                  
                        a3=ca%1000;                                       
                        OLED_ShowNum(103,0,a3,1,16);         ////小数部分2位电流值
                //      OLED_ShowNum(75,2,ca,4,16);
          }      
         
                        
               

               



}

/**********************************************/
void main(void)
{
//      u8      i;
//      u16      j;
      
      GPIO_config();

      ADC_config();
      EA = 1;
      P3M1 = 0x00;
      P3M0 = 0x00;
      OLED_Init();//初始化OLED
      OLED_ColorTurn(0);//0正常显示,1 反色显示
   OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示
          OLED_Clear();
      OLED_ShowString(17,0,".",16);
                OLED_ShowString(40,0,"V",16);
                OLED_ShowString(112,0,"A",16);
                OLED_ShowString(91,0,".",16);
      
      while (1)
      {
         
//                OLED_ShowString(0,2,"T:",16);
//                OLED_ShowString(16,2,"00:00",16);
//                OLED_ShowString(70,2,"5000",16);
//                OLED_ShowString(102,2,"mAh",16);
                        ADCCL();
               
                //      delay_ms(250);

               
               
      
      }
}




soma 发表于 2024-3-18 20:15:38

2个USB直连USB通讯和单片机无关就可以实现快充了。这方法不错啊

dnajx 发表于 2024-3-19 14:33:59

有时间模仿一下试试

qthfyunfei 发表于 2024-5-4 17:25:20

屏的驱动芯片是什么? 也想做一个

ageway 发表于 2024-5-7 08:53:12

{:4_250:}

alex 发表于 2024-5-7 10:32:46

标记标记,有空了学习一下{:4_165:}

Yim_Hom 发表于 2024-5-11 21:12:57

有空得学习,好棒。印象中立创开源的有一个桃源客也做过类似的,都很厉害。

ulvtkb126 发表于 2024-6-20 16:29:46

标记标记,有空了学习一下

xxxevery 发表于 2024-6-20 20:05:26

不错,支持一下

haiyang201 发表于 2024-6-25 08:58:12

学习学习,有时间高一个试试
页: [1] 2
查看完整版本: 8H3K64S2单片机制作OLED12832, USB电压电流容量表