完整教程:STM32 BL0939驱动及应用程序详解

BL0939.h

#ifndef __IBL0903_H__
#define __IBL0903_H__

//只读寄存器  名称   地址          功能                     默认值
#define IA_FAST_RMS 0x00 //A 通道快速有效值,无符号        0x000000
#define IA_WAVE     0x01 //A 通道电流波形寄存器,有符号      0x000000
#define IB_WAVE     0x02//B 通道电流波形寄存器,有符号       0x000000
#define V_WAVE      0x03//电压波形寄存器,有符号           0x000000
#define IA_RMS      0x04//A 通道电流有效值寄存器,无符号      0x000000
#define IB_RMS      0x05//B 通道电流有效值寄存器,无符号      0x000000
#define V_RMS       0x06//电压有效值寄存器,无符号          0x000000
#define IB_FAST_RMS 0x07//B 通道快速有效值,无符号         0x000000
#define A_WATT      0x08//A 通道有功功率寄存器,有符号       0x000000
#define B_WATT      0x09//B 通道有功功率寄存器,有符号       0x000000
#define CFA_CNT     0x0A//A 通道有功电能脉冲计数,无符号      0x000000
#define CFB_CNT     0x0B//B 通道有功电能脉冲计数,无符号      0x000000
#define A_CORNER    0x0C//A 通道电流电压波形相角寄存器       0x0000      
#define B_CORNER    0x0D//B 通道电流电压波形相角寄存器       0x0000
#define TPS1        0x0E//B 通道电流电压波形相角寄存器       0x000
#define TPS2        0x0F//外部温度检测寄存器,无符号         0x000
//读写寄存器
#define A_F_RMS_CTL 0x10//A 通道快速有效值控制寄存器        0xFFFF
#define IA_RMSOS    0x13//电流 A 通道有效值小信号校正寄存器    0x00
#define IB_RMSOS    0x14//电流 B 通道有效值小信号校正寄存器    0x00
#define A_WATTOS    0x15//A 通道有功功率小信号校正寄存器      0x00
#define B_WATTOS    0x16//B 通道有功功率小信号校正寄存器      0x00
#define WA_CREEP    0x17//有功功率防潜寄存器                 0x0B
#define MODE        0x18//用户模式选择寄存器                 0x0000
#define SOFT_RESET  0x19//写入 0x5A5A5A时用户区寄存器复位      0x000000
#define USR_WRPROT  0x1A//写入 0x55后用户操作寄存器可以写入;  0x00
#define TPS_CTRL    0x1B//温度模式控制寄存器                 0x07FF
#define TPS2_A      0x1C//外部温度传感器增益系数校正寄存器      0x0000
#define TPS2_B      0x1D//外部温度传感器偏移系数校正寄存器      0x0000
#define B_F_RMS_CTL 0x1E//B 通道快速有效值控制寄存器        0xFFFF

#define RN_SENDMAX      10
#define RN_RECEMAX      10

typedef uint32_t  u32;
typedef uint16_t u16;
typedef uint8_t  u8;

typedef enum
{
    RET_POW_SUC = 0,
    RET_POW_FAL
} Error_code_t;

typedef struct//发送数据结构体
{
  u16 Len;//数据长度
  u8 Data[RN_SENDMAX];//发送数据缓存数组
  u16 HaveSenLen;//记录已经发送的字节数
}RN_SEND;

typedef struct//接收数据结构体
{
  u16 Len;
  u8 Data[RN_RECEMAX];
  u16 HaveReceLen;
}RN_RECE;

typedef struct
{
    uint64_t base_energy_pow;//通道电量基数
    u32 last_energy_pow;//上次读到的电量基数
}BL0939_Para_t;

  BL0939_Para_t m_para[CHECK_CHANNELS];
  void delay_nms(u32 n);
  void BL_Config(void);//硬件配置
  void BL_GPIOconfig(void);
  void BL_Send(void);//串口发送
  BOOL BL_Write(u8 wreg, u8 *pbuf, u16 uclen,u8 ch);
  BOOL BL_Read(u8 wreg,u8 ch);
  BOOL Block_Rece(void);//阻塞接收+超时处理
  BOOL Block_Send(void);//阻塞发送+超时处理
  Error_code_t WriteData(u8 wreg, u8 *data, u8 len, u8 ch);
  Error_code_t ReadData(u8 wreg, u8 *data, u8 len, u8 ch);
  BOOL BLCheckSum(u8 reg, u8 *data, u8 ch);
  Error_code_t read_ch_pow(float* POW, u8 ch);
  Error_code_t read_ch_cur(u16* Cur, u8 ch);
  Error_code_t read_ch_vol(u16* Vol, u8 ch);
  Error_code_t get_device_id(const u32 m_ch);
  Error_code_t read_ch_energy_pow(u32* Energy_Pow, u8 ch);
  Error_code_t write_ch_oilvl(u16 Over_Cur, u8 ch);
  Error_code_t soft_reset(u8 ch);
  Error_code_t Init(u8 ch);
  Error_code_t set_powercheck_ic( const u32 m_ch);
  u32 calculate_energy(u8 ch, u32 ele);
#endif

BL0939.c

#include "IBL0903.h"

static u8 BUS_ADDR[5] = {0x01,0x02,0x03,0x04,0x05};//5片bl0939的地址

RN_SEND RnSend = {0}; //发送结构体对象
RN_RECE RnRece = {0}; //接收结构体对象
volatile u8 SendFinsh = 0;
volatile u8 ReceFinsh = 0;

typedef struct
{
    u8 addr;
    u8 data[3];
}BL0903_req_t;

static BL0903_req_t config_req[] ={
  {MODE,{0x00,0x10,0x00}},//报警功能开启50hz 400ms/
  {TPS_CTRL,{0xff,0xff,0x00}},//开启A通道过流,漏电报警
  {A_F_RMS_CTL,{0xE6,0xF4,0x00}},//短路40A:0x3A77  80A:0x74E6
  {B_F_RMS_CTL,{0x62,0x84,0x00}},//漏电30mA
};


void main()
{
    BL_Config();//通信串口配置

    for(u8 i=1;i<11;i++)
    {//挨个配置芯片
        if(i%2)
            continue;//每个芯片双通道,只需要配置一次
        if(Init(i) == RET_POW_FAL)//芯片初始化
        {
            Dprintf(EN_LOG, TAG, "芯片 %d 初始化**失败**\r\n", i);
        }
        else
        {
            if(set_powercheck_ic(i) == RET_POW_FAL)
            {
                Dprintf(EN_LOG, TAG, "芯片 %d 配置**失败**\r\n", i);
            }
        }
    }

    //测试读取1通道的数据
    //读取电流
    u16 cur;
    read_ch_cur(&cur, 1);

    //读取电压
    u16 vol;
    read_ch_vol(&vol, 1)

    //读取功率
    float pow
    read_ch_pow(&pow, 1);
   
   //读取电量
   u32 ele;
   read_ch_energy_pow(&ele, 1);
}

/*******************************************************************************
 函 数 名: delay_nms
 功能描述: 延时nms
 入口参数: n:ms数
 出口参数: 无
********************************************************************************/
void delay_nms(u32 n)
{
    u32 t = 14000;
	while (n--)
	{
        while (t--);
    }		
}

//串口配置
void BL_Config(void)
{
    USART_DeInit(USART2);//复位串口
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    //时钟使能
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);  //GPIOD时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);//使能USART2
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);//使能重映射
    GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);//IO映射

    //USART2_TX  GPIOD.5
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;         //PD.5
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //频率50M
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   //复用推挽输出
    GPIO_Init(GPIOD, &GPIO_InitStructure);            //初始化GPIOA.2
    GPIO_SetBits(GPIOD, GPIO_Pin_5);
    //USART2_RX  GPIOD.6
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;             //PD6
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
    GPIO_Init(GPIOD, &GPIO_InitStructure);                //初始化GPIOA.3
    //USART2初始化配置
    USART_InitStructure.USART_BaudRate = 4800;                                      //波特率4800
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;                     //数据8位
    USART_InitStructure.USART_StopBits = USART_StopBits_1_5;                          //1.5位停止位
    USART_InitStructure.USART_Parity = USART_Parity_No;                           //无校验
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件数据流控制
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;                 //收发模式
    USART_Init(USART2, &USART_InitStructure);                                       //初始化UART2

    //USART2 NVIC初始化
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;        //子优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);
    USART_ClearFlag(USART2, USART_FLAG_TC);
    USART_ClearFlag(USART2, USART_FLAG_IDLE);
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //开启接收中断,RXNE读寄存器非空
    USART_ITConfig(USART2, USART_IT_IDLE, ENABLE); //使能接收一帧数据中断
    USART_ITConfig(USART2, USART_IT_TC, ENABLE);   //开启发送中断,TC发送完成    
    USART_Cmd(USART2, ENABLE);                     //使能串口2
}

//过载中断配置
void BL_GPIOconfig(void)
{//中断配置
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD,ENABLE);
    GPIOMode_TypeDef m_gpiotypedef = USE_HW_BL0939CH4 ? GPIO_Mode_IPD : GPIO_Mode_IPU;
    EXTITrigger_TypeDef m_extitypedef = USE_HW_BL0939CH4 ? EXTI_Trigger_Rising : EXTI_Trigger_Falling;
    //CF A通道过载 空闲高电平,过载低电平 PC1
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = m_gpiotypedef; //上拉输入
    GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化GPIOC1
    //B_LEAK B通道过载 空闲高电平,过载低电平 PD9
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_Init(GPIOD, &GPIO_InitStructure); //初始化GPIOD9
    //ZX 过零 PC2
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOC, &GPIO_InitStructure); //初始化GPIOC2
    
    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //使能复用功能时钟
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = m_extitypedef;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource1);
    EXTI_InitStructure.EXTI_Line = EXTI_Line1;
    EXTI_Init(&EXTI_InitStructure);
    
    //ZX 过零 PC2
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource2);
    EXTI_InitStructure.EXTI_Line = EXTI_Line2;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;//过零设为双边沿
    EXTI_Init(&EXTI_InitStructure);
    
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;        //响应优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;
    NVIC_Init(&NVIC_InitStructure);
    EXTI->IMR &= ~ (EXTI_Line2);//禁能过零中断
    
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;        //响应优先级
    NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
    NVIC_Init(&NVIC_InitStructure);   
    
    NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
    NVIC_Init(&NVIC_InitStructure);
}

//命令复位
Error_code_t soft_reset(u8 ch)
{//ch [0-9]
    static u8 reset_count = 0;
    u8 t_data[3] = {0x55,0x00,0x00};
    u8 reset[3] = {0x5A,0x5A,0x5A};
    BL_Write(USR_WRPROT, t_data, 3, ch+1);//写使能
    BL_Write(SOFT_RESET, reset, 3, ch+1);//写数据
    delay_nms(3);
    u8 r_data[3] ={0};
    if((ReadData(MODE, r_data, 3, ch+1) == RET_POW_SUC) && r_data[1]==0)
    {
        Dprintf(EN_LOG, TAG, "通道 %d 复位**成功**\r\n", ch+1);
    }
    else
    {
        if(++reset_count>3)
        {
            reset_count = 0;
            return RET_POW_FAL;
        }
        else
            return soft_reset(ch);
    }
    delay_nms(5);
    reset_count = 0;
    return RET_POW_SUC;
}

//芯片初始化
Error_code_t Init(u8 ch)
{    
    return ((get_device_id(m_ch) == RET_POW_SUC)?RET_POW_SUC:RET_POW_FAL);//读取id检验通信是否成功
}

//读取芯片id
Error_code_t get_device_id(const u32 ch)
{
    static u8 fail_count = 0;
    u8 id = 0;
    if((ReadData(WA_CREEP, &id, 1, ch) == RET_POW_SUC) && (id == 0x0B))
    {
        fail_count = 0;
        delay_nms(5);
    }
    else
    {//读取失败,重复读取
        if(++fail_count >= 3)
        {
            fail_count = 0;
            return RET_POW_FAL;
        }
        return get_device_id(ch);
    }
    return RET_POW_SUC;
}

//配置芯片寄存器
Error_code_t set_powercheck_ic( const u32 ch)
{
    u8 temp_addr = 0;    
    Dprintf(EN_LOG, TAG, "通道 %d 检测芯片初始化**成功**\r\n", ch);
    soft_reset(ch);
    for (u8 i = 0; i < (sizeof(config_req) / sizeof(BL0903_req_t)); i++)
    {
        temp_addr = config_req[i].addr;
        if(WriteData(temp_addr,config_req[i].data,3,ch) == RET_POW_FAL)
        {
            Dprintf(EN_LOG, TAG, "通道 %d 检测芯片初始化**失败**\r\n", ch);
            return RET_POW_FAL;
        }
        delay_nms(1);
    }
    BL_GPIOconfig();//中断配置
    return RET_POW_SUC;
}

//设置过载电流
Error_code_t write_ch_oilvl(u16 Over_Cur, u8 ch)
{
    u8 addr = (ch%2)?A_F_RMS_CTL:B_F_RMS_CTL;
    Over_Cur |= 0x8000;//周波刷新
    u8 data[2] = {Over_Cur&0xff,(Over_Cur>>8)};
    if(WriteData(addr, data, 2, ch) == RET_POW_FAL)
    {
        Dprintf(EN_LOG, TAG, "通道 %d 过流设置**失败**\r\n", ch);
        return RET_POW_FAL;
    }
    return RET_POW_SUC;
}

//往芯片写数据
Error_code_t WriteData(u8 wreg, u8 *data, u8 len, u8 ch)
{
    static u8 time_count = 0;
    u8 t_data[3] = {0x55,0x00,0x00};
    BL_Write(USR_WRPROT, t_data, 3, ch);//写使能
    BL_Write(wreg, data, len, ch);//写数据
    t_data[0] = 0;
    BL_Write(USR_WRPROT, t_data, 3, ch);//写禁能
    u8 r_data[3] ={0};
    ReadData(wreg, r_data, 3, ch);
    if(memcmp(data, r_data, len)!=0)
    {
        if(time_count++ >=3)
        {
            time_count = 0;
            return RET_POW_FAL;
        }
        return WriteData(wreg, data, len, ch);
    }
    time_count = 0;
    return RET_POW_SUC;
}

//从芯片读数据
Error_code_t ReadData(u8 wreg, u8 *data, u8 len, u8 ch)
{
    u8 temp_buf[4] = {0};
    if(BL_Read(wreg, ch) == TRUE)
    {//读指令发送成功
        if(Block_Rece() == TRUE)
        {//数据读取成功
            memcpy(temp_buf, RnRece.Data, 4);
            ReceFinsh = 0;
            RnRece.HaveReceLen = 0;            
            if(BLCheckSum(wreg, temp_buf, ch) == TRUE)
            {
                memcpy(data, temp_buf, len);
                return RET_POW_SUC;
            }
        }
    }
    ReceFinsh = 0;
    return RET_POW_FAL;
}

//串口写数据
BOOL BL_Write(u8 wReg, u8 *pBuf, u16 ucLen, u8 ch)
{
    memset(RnSend.Data, 0, sizeof(RnSend.Data)); //清空发送缓存数组
    u8 chksum = 0,num =0;
    u8 addr = BUS_ADDR[(ch-1)/2] | 0xA0;//写命令+从机地址
    chksum += addr;
    RnSend.Data[num++] = addr;
    chksum += wReg;
    RnSend.Data[num++] = wReg;
    for(u8 i=0; i<ucLen; i++)
    {
        RnSend.Data[num++] = pBuf[i];
        chksum += pBuf[i];
    }
    chksum = ~chksum;
    RnSend.Data[5] = chksum;
    RnSend.Len = 6;//从机地址 寄存器 三字节数据 校验
    RnSend.HaveSenLen = 1;
    BL_Send();
    return Block_Send();
}

//串口读数据
BOOL BL_Read(u8 wReg, u8 ch)
{
    memset(RnSend.Data, 0, sizeof(RnSend.Data)); //清空发送缓存数组
    memset(RnRece.Data, 0, sizeof(RnRece.Data)); //清空接收缓存数组
    RnSend.Data[0] = BUS_ADDR[(ch-1)/2] | 0x50;//读命令+从机地址
    RnSend.Data[1] = wReg;
    RnSend.Len = 2;
    RnSend.HaveSenLen = 1;
    BL_Send();
    return Block_Send();
}

//校验数据是否正确
BOOL BLCheckSum(u8 reg, u8 *data, u8 ch)
{
    u8 checksum = 0;
    u8 addr = 0x50 | BUS_ADDR[(ch-1)/2];
    checksum += addr;
    checksum += reg;
    for(u8 i=0; i<3; i++)
        checksum += data[i];
    checksum = ~checksum;
    return (checksum == data[3])?TRUE:FALSE;
}

//等待发送完成
BOOL Block_Send(void)
{
    u32 t = 0;
    while (!SendFinsh)
    {
        if (++t > 1400 * 1000) //14000 == 1ms
        {
            GPIO_SetBits(GPIOD, GPIO_Pin_5);
            return FALSE; //读取超时,说明芯片不正常
        }
    }    
    return TRUE;
}

//等待接收完成
BOOL Block_Rece(void)
{
    u32 t = 0;
    while (!ReceFinsh)
    {
        if (++t > 1400 * 1000) //14000 == 1ms
        {
            return FALSE; //读取超时,说明芯片不正常
        }
    }
    return TRUE;
}

//串口发送
void BL_Send()
{
    USART_ClearFlag(USART2, USART_FLAG_TC); //清除传输完成标志位,否则可能会丢失第1个字节的数据
                                            //此处第一次发送触发发送中断,后面字节都在中断服务程序发送,注意地址++避免首字节重复发送
    SendFinsh = 0;
    USART2->DR = RnSend.Data[0];
}

//读取电流值
//下面具体参数需按实际电路中的参数
Error_code_t read_ch_cur(u16 *Cur, u8 ch)
{
    u8 read_reg;
    read_reg = (ch%2)?IA_RMS:IB_RMS;
    u8 temp_cur[3] = {0};
    u8 RL = 2;
    float R5 = 10.2;
    u32 Rt = 2000;
    float ptf_cur = 0.0;
    if(ReadData(read_reg, temp_cur, 3, ch) == RET_POW_SUC)
    {
        ptf_cur = (float)(*(u32*)temp_cur * 1.218)/(324004*RL);
        Dprintf(EN_LOG,TAG,"通道 %d cur : %.3f \r\n",ch,ptf_cur);
        *Cur = (u16)ptf_cur;
        return RET_POW_SUC;
    }
    return RET_POW_FAL;
}

//读取功率
//下面参数需按照实际电路
Error_code_t read_ch_pow(float *Pow, u8 ch)
{
    u8 read_reg;    
    read_reg = (ch%2)?A_WATT:B_WATT;
    u8 temp_pow[3] = {0};
    u8 RL = 2;
    float R5 = 10.2;
    float R17 = 0.0239;
    u32 Rt = 2000;
    if(ReadData(read_reg, temp_pow, 3, ch) == RET_POW_SUC)
    {
        u32 t_pow = *(u32*)temp_pow;
        if(t_pow & 0x00800000)
        {//负数处理
            t_pow = ((~t_pow)&0x00FFFFFF)+1;
        }
        double divisor, dividend;
        divisor = 4046*RL*0.24*1000.0;
        dividend = t_pow * 1.483524 * 1000.24;
        *Pow = (float)(dividend/divisor);
        Dprintf(EN_LOG,TAG,"通道 %d pow : %.3f \r\n",ch,*Pow);
        return RET_POW_SUC;
    }
    return RET_POW_FAL;
}

//读取电压值
//计算公式按实际电路
Error_code_t read_ch_vol(u16 *Vol, u8 ch)
{   
    u8 temp_vol[3] = {0};
    u32 temp_reg = 0;
    if(ReadData(V_RMS, temp_vol, 3, ch) == RET_POW_SUC)
    {
        temp_reg = *(u32*)(temp_vol);
        *Vol = (u16)(((double)temp_reg * 1.218 * (float)(200*5+0.24))/(79931*240));
        Dprintf(EN_LOG,TAG,"通道 %d vol : %d \r\n",ch,*Vol);
        return RET_POW_SUC;
    }
    return RET_POW_FAL;
}

//读取用电量
Error_code_t read_ch_energy_pow(u32* Energy_Pow, u8 ch)
{
    u8 read_addr;
    read_addr = (ch%2)?CFA_CNT:CFB_CNT;
    u8 temp_energy[3] = {0};
    if(ReadData(read_addr, temp_energy, 3, ch) == RET_POW_SUC)
    {
        u32 t_energy = *(u32*)temp_energy;
        if(t_energy & 0x00800000)
        {//负数处理
            t_energy = ((~t_energy)&0x00FFFFFF)+1;
        }        
        m_para[ch-1].base_energy_pow += ((t_energy>m_para[ch-1].last_energy_pow)?(t_energy-m_para[ch-1].last_energy_pow):0);
        Dprintf(YELLOW,"","通道 %d 本次:%d 上次:%d 累计:%d\r\n",ch,t_energy,m_para[ch-1].last_energy_pow,m_para[ch-1].base_energy_pow);
        m_para[ch-1].last_energy_pow = t_energy;
        *Energy_Pow = t_energy;        
        return RET_POW_SUC;
    }
    return RET_POW_FAL;
}

//计算用电量
u32 IBL0903::calculate_energy(u8 ch, u32 ele)
{
    u8 RL = 2;
	float R5 = 10.2;
    float R17 = 0.0239;    
    u32 Rt = 2000;
    double energy;
	u32 rtn;
    energy = (double)(1638.4*256*1.218*1.218*1000.24)/(double)((uint64_t)3600000*4046*0.24*RL);//每个脉冲多少毫度
    rtn = (u32)(ele * energy);
    Dprintf(GREEN,"","通道%d 脉冲%d 毫度%d\r\n",ch,ele,rtn);
    return rtn;
}


/*************************************************************
**函数原型  USART2_IRQHandler
**功能描述  串口2中断处理函数
**入口参数  无
**出口参数  无
*************************************************************/
extern "C"
{
    void USART2_IRQHandler()
    {
        while (1)
        {
            if (USART2->SR & (1 << 5)) //接收一字节中断
            {
                USART2->SR &= ~(1 << 5);
                RnRece.Data[RnRece.HaveReceLen++] = USART2->DR;
            }
            else if (USART_GetITStatus(USART2, USART_IT_IDLE) != RESET) //接收一帧中断
            {
                USART_ReceiveData(USART2); //清除IDLE空闲标志位
                USART_ClearFlag(USART2, USART_FLAG_IDLE);
                ReceFinsh = 1;
            }
            else if (USART2->SR & (1 << 6)) //发送中断
            {
                USART2->SR &= ~(1 << 6);
                //if()判断发送的长度是否发送结束
                if (RnSend.HaveSenLen < RnSend.Len)
                {
                    USART2->DR = RnSend.Data[RnSend.HaveSenLen++];
                }
                else
                {
                    RnSend.HaveSenLen = 1;
                    SendFinsh = 1;
                }
            }
            else
            {
                break;
            }
        }
    }
}

作者:_Hello_WXY

物联沃分享整理
物联沃-IOTWORD物联网 » 完整教程:STM32 BL0939驱动及应用程序详解

发表评论