stm32+bl0939驱动、应用程序(完整)

本文详细介绍了如何在STM32微控制器上驱动BL0939芯片,包括提供的头文件BL0939.h和源文件BL0939.c,展示了完整的驱动程序和应用实例,帮助开发者理解和实现相关功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
            }
        }
    }
}
说明: 除非特别声明,所有程序均使用VC++6.0 MFC编写。 所有程序均为练手用,放弃一切权利,同时不承担任何责任。 显式遵照 GPL v3.0标准。 QuoteCorrection 20110722 1119.7z 处理 清风徐来 水波不兴 邮件使用,将 西文 "" 转换为 “” 原理:ASC 转 UNICODE(修改) 转 ASC。 处理文件夹。 CSourceCodeEdit X4括号判断末行 20110721 1216.7z C语言源代码格式化。 处理文件夹。 PLT2KMLX14解决最后一行的问题 20110721 0931.7z PLT2KML 改CString完工 20120731 1632.7z PLT2KML 20110811 1047 处理单文件.7z PLT2KML 20120813 1815 处理子目录.7z PLT2KML 20120831 0934 处理子目录.7z WPT2KMLx4解决空行末行 20110721 0948.7z WPT2KML 改CString完工 20120731 1700.7z WPT2KML 全部改CString慢 改strcat慢 20120801 1338.7z WPT2KML 全部改CString慢 改strcat慢 20120801 1559.7z WPT2KML 完成 20120802 1718.7z WPTPLT2KMLx12PLTWPT初步 20110721 1006.7z WPTPLT2KML 基本完工 20120801 1618.7z WPTPLT2KML 删除原始PLTWPT文件 20120802 0908.7z WPTPLT2KML 修正WPT 20120802 1725.7z OZI格式的轨迹文件转KML格式的轨迹文件。 原理:ASC(转换) 转 UNICODE 转 UTF-8。 处理子目录 WPT完成CFile改造成CreateFile SubtitleENCN 20110726 1924.7z 剔除中英文字幕中的中文。 原理:ASC 转 UNICODE(剔除中文) 回转ASC。 StringArrayBuildX10排版完成 20110728 0853.7z UNICODE 0-65535 中汉字的拼音。 从 CnToSpell.java 中提取的拼音。 StringArrayX6汉字转拼音 20110729 1418 拼音库需要修正.7z 汉字转拼音 原理:ASC 转 UNICODE(汉字转拼音) 回转ASC。 TXTEditEnterX1单文件排版 20110729 1902.7z 排版用 原理:ASC 转 UNICODE(排版) 回转ASC(替换掉原来的文件)。 doyouhikeList 磨房报名人员ID格式化后发悄悄话 20110729 1856.7z 磨房报名人员ID格式化后发悄悄话 原理:ASC 转 UNICODE(排版) 回转ASC(替换掉原来的文件)。 DOC2TXTEdit 20110919 1753.7z 处理PDF的文件转TXT后的换行问题。==末尾是空格不用处理的。 原理:ASC 转 UNICODE(行的结尾只要不是汉字就换行) 回转ASC。 PLTClear 清除PLT文件夹的名 20111006 1912.7z 处理 GPX转PLT之后, OziExplorer Track Point File Version 2.1 WGS 84 Altitude is in Feet Reserved 3 0,2,255, $$$$$$ ,0,0,2,8421376 文件名会显示在 GM 做的地图里。清除掉 原理:ASC 转 UNICODE(修改) 转 ASC。 处理文件夹。 AngleBracketsSubtitle 20111006 1935.7z 处理 清除字幕中的字体、颜色标记。 原理:ASC 转 UNICODE(修改) 转 ASC。 处理文件夹。 UTF82ANSI 20111006 2008.7z 处理 将 UTF-8 格式的 字幕(或者文件) 转 ANSI 格式。 原理:UTF-8 2 UNICODE 2 ANSI。 处理文件夹。 GPX2KML 20120102 1630.7z 处理 将 UTF-8 格式的 字幕(或者文件) 转 ANSI 格式。 原理:查找坐标点, 然后由ANSI 2 UNICODE 2 UTF-8。 处理文件夹。 <trkpt lat="36.409595000" lon="114.187676000"> <ele>258.000000</ele> <time>2011-03-08T08:20:31Z</time> <speed>3.666667</speed> </trkpt> FileFolderGenerate 20120112 1514.7z 文件夹生成函数CreateDirectory的测试。 功能:在指定目录下生成256个文件夹,每个文件夹内生成256个32K的文本文件,内容为“A”。 FileGenerate 20111121 1641.7z 功能: 猜想:对于“8.3格式文件”的文件名,(也许是出于向后兼容的目的),操作系统总是尝试以“大写”的文件名保存,小写的文件名或者扩展名也用大写表示,然后在“文件登记项”的32B的第13个字节(偏移量为0x0C)标识。于是检验大小写文件名对可创建的文件数量的影响。 还是将电脑的最后一个分区格式化为 FAT32 格式。(为了保证一般性,不是在“根目录下”检验的,相信也同样适合于根目录。) 然后使用如下四种读写文件的方法进行测试, 1、C语言函数fopen(),UNICODE版本是 _wfopen()。 2、C++ fstream 3、mfc CFile、CStdioFile类 4、采用WinCE的API CreateFile 其中每种方式都检测9种情况: 文件名大写.扩展名大写(B1)、文件名大写.扩展名小写(B2)、文件名大写.扩展名混写(B3) 文件名小写.扩展名大写(B4)、文件名小写.扩展名小写(B5)、文件名小写.扩展名混写(B6) 文件名混写.扩展名大写(B7)、文件名混写.扩展名小写(B8)、文件名混写.扩展名混写(B9) shuangseqiu 20120226 1931.7z shuangseqiu 双色球 20120802 1728.7z shuangseqiu 清注释完成20120810 1049.7z 功能: 寻找双色球的蓝球的间隔规律。 单文件处理。 CreateFile读取文件并进行处理。 CreateFile写入文件,以供分析之用。 FileNumber 20111028 2219.7z 功能: 给文件编号。(文件有遗漏。) CreateFile读取文件。 CFile写入文件。(==修正为CreateFile) !!!!KMLPointReverse 20111006 2205.7z !!!!KMLPointReverse 20120831 0951.7z 功能: 编辑KML格式的GPS轨迹的时候,将轨迹点前后倒置! CSourceCodeEnter 20120229 1759.7z 由 CSourceCodeEdit X4括号判断末行 20110721 1216.7z 简单修正而得!加入了对“#”的处理。(很多编辑器、很多人喜欢用回车而不喜欢用换行符号!) C语言源代码格式化。 处理文件夹。 CSourceCodeEnterFile 20120611 0914.7z 处理文件 CSourceCodeEnterFile WriteFile 20120713 0930.7z CSourceCodeEnterFile WriteFile TRUNCATE_EXISTING 20120718 0938.7z Comma2Enter 20120614 1626.7z 将????分隔的文本文件改为回车换行分隔。 处理文件。 rgb32bmpFile 640x480 20120713 1331.7z 640x480转BMP文件 处理单文件 RGB32BMP 20120713 1347.7z 640x480转BMP文件 处理文件夹 EXTnamebig2small 扩展名更改-外部申请内存块 b2s s2b 20120718 1344.7z 文件名扩展的大写←→小写转换。 递归调用处理子目录 YUYV2BMP 20120723 1109 算法1.7z YUYV的数据转换成RGB的数据成功 递归调用处理子目录 BrowseDirectoryTree 20120718 1026.7z ListAllFileInDrectory 20120723 1317.7z 子目录浏览 nst2kml 20120802 1925.7z 处理子目录 AddQuote 20120810 1016.7z a → 'a'; 处理单文件 kmlA2Space 20120813 1124.7z kmlA2Space 20120813 2345.7z 功能:将Ourxmaps生成的以0x0A分隔的KML文件转化为空格分隔的KML文件 UTF8 转 UNICODE 转 ANSI之后进行处理,处理完之后,ANSI 转 UNICODE 转 UTF-8 保存。 处理子目录 A2DA 20120831 0939.7z DA2A 20120831 0939.7z 功能:单文件处理,WINDOWS/LINUX下的回车换行的处理。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Hello_WXY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值