打印
[STM32F1]

STM32的HLW8032电量采集系统源程序

[复制链接]
705|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
elsaflower|  楼主 | 2024-2-25 22:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式


#include "stm32f10x.h"
#include <stdbool.h>
#include <stdio.h>
#include "usart3.h"
#include "delay.h"
#include "usart.h"
#include "LED.h"
#include "timer.h"
#include "string.h"
#include "oled.h"
#include "myiic.h"

void Data_Processing(void);

u8 link=0;

u8 k=0;
u16 old_reg=0,len=0;
double V=0,C=0,P=0,E_con=0;
int main(void)
{      
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);         //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
        delay_init();        //延时初始
        LED_Init();        //LED初始化
        uart_init(9600);//串口1初始化
        usart3_init(4800);//HLW8032模块接线方式3.3V--3.3;G--G;T--PB11;P不接
      
        IIC_Init();//如果不接0.96寸显示屏,这句需要删掉
    OLED_Init();//0.96寸接线方式VCC--3.3;GND--G;SCL--PB12;SDA--PB13//如果不接0.96寸显示屏,这句需要删掉
        OLED_P8x16Str(35,0,(unsigned char *)"Knight20");//如果不接0.96寸显示屏,这句需要删掉
      
        delay_ms(20);//延时      
      
        printf("Init OK\r\n");
        while(1)
        {               

                if(USART3_RX_STA&0X8000)//接收到HLW8032一次数据了
                {      
                        len=USART3_RX_STA&0x3fff;//得到此次接收到的数据长度
                        Data_Processing();
                        USART3_RX_STA=0;                           //启动下一次接收      
                }
                 delay_ms(50);
                LED0=!LED0;//STM32系统板自带的指示灯
        }
}

void Data_Processing(void)//电能数据解析
{
        u32 VP_REG=0,V_REG=0,CP_REG=0,C_REG=0,PP_REG=0,P_REG=0,PF_COUNT=0,PF=0,dat_sum=0;
        u8 dat[200];
        u8 i=0;
        if(USART3_RX_BUF[0]!=0xaa&&len==24)//芯片误差修正功能正常,参数正常
        {
                for(i=2;i<23;i++)
                {
                        dat_sum=dat_sum+USART3_RX_BUF[i];//计算校验和
                }
                if(dat_sum%256==USART3_RX_BUF[23])//检查校验位是否正确
                {
                        VP_REG=USART3_RX_BUF[2]*65536+USART3_RX_BUF[3]*256+USART3_RX_BUF[4];//计算电压参数寄存器
                        V_REG=USART3_RX_BUF[5]*65536+USART3_RX_BUF[6]*256+USART3_RX_BUF[7];//计算电压寄存器
                        V=(VP_REG/V_REG)*1.88;//计算电压值,1.88为电压系数,根据所采用的分压电阻大小来确定
                        //printf("U:%0.2fV; ",V);
                       
                        CP_REG=USART3_RX_BUF[8]*65536+USART3_RX_BUF[9]*256+USART3_RX_BUF[10];//计算电流参数寄存器
                        C_REG=USART3_RX_BUF[11]*65536+USART3_RX_BUF[12]*256+USART3_RX_BUF[13];//计算电流寄存器
                        C=((CP_REG*100)/C_REG)/100.0;//计算电流值
                        //printf("I:%2.3fA; ",C);
                    sprintf((char *)dat,"U:%0.2fV  I:%2.2fA ",V,C);
                        OLED_P6x8Str(0,3,dat);//如果不接0.96寸显示屏,这句需要删掉
                        printf((char *)dat);
                        if(USART3_RX_BUF[0]>0xf0)//判断实时功率是否未溢出
                        {
                                printf("NO Device!");
                                OLED_P6x8Str(30,4,"NO Device");//如果不接0.96寸显示屏,这句需要删掉
                                P=0;
                        }
                        else
                        {
                                PP_REG=USART3_RX_BUF[14]*65536+USART3_RX_BUF[15]*256+USART3_RX_BUF[16];//计算功率参数寄存
                                P_REG=USART3_RX_BUF[17]*65536+USART3_RX_BUF[18]*256+USART3_RX_BUF[19];//计算功率寄存器
                                P=(PP_REG/P_REG)*1.88*1;//计算有效功率
                                sprintf((char *)dat,"P:%0.2fW   ",P);
                                OLED_P6x8Str(30,4,dat);//如果不接0.96寸显示屏,这句需要删掉
                                printf((char *)dat);
                        }      
                        if((USART3_RX_BUF[20]&0x80)!=old_reg)//判断数据更新寄存器最高位有没有翻转
                        {
                                k++;
                                old_reg=USART3_RX_BUF[20]&0x80;
                        }
                        PF=(k*65536)+(USART3_RX_BUF[21]*256)+USART3_RX_BUF[22];//计算已用电量脉冲数
                        PF_COUNT=((100000*3600)/(PP_REG*1.88))*10000;//计算1度电对应的脉冲数量
                        E_con=((PF*10000)/PF_COUNT)/10000.0;//计算已用电量
                        sprintf((char *)dat,"E:%0.4lf kW.h  ",E_con);
                        OLED_P6x8Str(10,5,dat);//如果不接0.96寸显示屏,这句需要删掉
                        printf((char *)dat);
                        printf("\r\n");
                        delay_ms(100);
                        memset((void *)USART3_RX_BUF,0,sizeof(USART3_RX_BUF));//清空缓存
                }
               
        }
}


使用特权

评论回复
沙发
tpgf| | 2024-3-4 09:21 | 只看该作者
这个电量采集系统能承受的电压是多少呢

使用特权

评论回复
板凳
wakayi| | 2024-3-4 10:06 | 只看该作者
感觉这个程序的结构应该就是适用于实时性不高的场合

使用特权

评论回复
地板
wowu| | 2024-3-4 10:39 | 只看该作者
数据处理的程序是不是过于复杂了  呢

使用特权

评论回复
5
xiaoqizi| | 2024-3-4 22:54 | 只看该作者
如果是使用中断而不是轮询的处理方式就更好了

使用特权

评论回复
6
renzheshengui| | 2024-3-4 23:26 | 只看该作者
使用的是串口通讯方式的电量采集模块吗

使用特权

评论回复
7
paotangsan| | 2024-3-4 23:58 | 只看该作者
硬件上外部采集器件都是什么呢

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

21

主题

1127

帖子

0

粉丝