- /*
- * ade7758.c
- *
- * Created on: 2014年10月11日
- * Author: Lzy
- */
- //#include
- #include "ade7758.h"
- #include "sys.h"
- #define ADE_CS_PIN PBout(12)
- #define ADE_RCC RCC_APB2Periph_GPIOB
- #define ADE_GPIO GPIOB
- #define ADE_PIN (GPIO_Pin_12)
- unsigned char bWorkModel=0;//工作模式标志位 1:校准模式;0:正常工作模式;
- unsigned char bit_1s=0; //1s钟标志,在时钟中断函数中置位
- static unsigned char divider = 1;//电能分频器,默认值为零,视在功率超出一定值时,自动将该值提高
- static unsigned int energy[9];//用于累加电能值 36
- struct all_data working;//正常工作模式下存放的电参量 95
- static unsigned int vo_buffer[5][3];//用于电压的积分虑波 36
- static unsigned int io_buffer[5][3];//用于电流的积分虑波 36
- /**
- * 功能:片选使能
- */
- void ADE_CS(unsigned char cs)
- {
- ADE_CS_PIN = cs;
- delay_ms(1);
- }
- /**
- * 功能:延时函数 50us
- */
- void ADE_udelay(void)
- {
- delay_ms(1);
- }
- /**
- * 功能:通过SPI写入数据至芯片
- * 入口参数:
- * buf -> 数据缓冲区
- * len -> 数据长度
- */
- void ADE_SPIWrite(unsigned char *buf, unsigned char len)
- {
- SPI2_Write(buf,len);
- }
- /**
- * 功能:通过SPI读芯片数据
- * 入口参数:len -> 数据长度
- * 出口参数: buf -> 数据缓冲区
- *
- */
- void ADE_SPIRead(unsigned char *buf, unsigned char len)
- {
- SPI2_Read(buf,len);
- }
- /**
- * 功能:7758写数据函数
- * 入口参数:
- * type:目标寄存器的地址
- * wdata:写进寄存器的内容
- * databit:目标寄存器的宽度
- * 出口参数:NULL
- * 返回值:NULL
- */
- void ADE_Write(unsigned char type,unsigned int wdata,unsigned char databit)
- {
- unsigned char data[4];
- ADE_CS(0);
- type = type | 0x80;
- data[0] = type;
- ADE_SPIWrite(data, 1);
- ADE_udelay();
- if(databit == 8)
- {
- data[0] = wdata;
- ADE_SPIWrite(data, 1);
- }
- else if(databit == 16)
- {
- data[0] = (wdata&0xff00) >> 8; /*高8位*/
- data[1] = (wdata&0x00ff); /*底8位*/
- ADE_SPIWrite(data, 2);
- }
- else if(databit == 24)
- {
- data[0] = (wdata&0xff0000) >> 16; /*高8位*/
- data[1] = (wdata&0xff00)>>8;
- data[2] = (wdata&0xff);
- ADE_SPIWrite(data, 3);
- }
- else
- printf("ADE write databit Error:%d\n", databit);
- ADE_CS(1);
- }
- /**
- * 功能:7758读寄存器函数
- * 入口参数:
- * type:目标寄存器的地址
- * databit:目标寄存器的宽度
- * 出口参数:指定寄存器的内容
- * 返回值:指定寄存器的内容
- */
- unsigned int ADE_Read(unsigned char type,unsigned char databit)
- {
- unsigned char data[4]={0,0,0,0};
- unsigned int rtdata = 0;
- ADE_CS(0);
- type = type & 0x7F;
- data[0] = type;
- ADE_SPIWrite(data, 1);
- ADE_udelay();
- if(databit == 8)
- {
- ADE_SPIRead(data,1);
- rtdata = data[0];
- }
- else if(databit == 12)
- {
- ADE_SPIRead(data,2);
- rtdata = (data[0]&0x0f) << 8;
- rtdata += data[1];
- }
- else if(databit == 16)
- {
- ADE_SPIRead(data,2);
- rtdata = data[0] << 8;
- rtdata += data[1];
- }else if(databit == 24)
- {
- ADE_SPIRead(data,3);
- rtdata = data[0] << 16;
- rtdata += (data[1] << 8);
- rtdata += data[2];
- }
- else
- printf("ADE Read databit Error:%d\n", databit);
- ADE_CS(1);
- return(rtdata);
- }
- /**
- * 功能:检测异常
- */
- void ADE_AuCheck(void)
- {
- unsigned char i;
- unsigned int temp_data[5];//存放运算过程的中间变量
- unsigned int temp_v,temp_i;
- //自动检测ADE7758是否出现异常
- if( working.voltage[ 0 ] > ERR_VOLTAGE ||
- working.voltage[ 1 ] > ERR_VOLTAGE ||
- working.voltage[ 2 ] > ERR_VOLTAGE )
- {
- // ADE_Check7758();
- printf("ADE Error\n" );
- }
- //自动设置分频器的大小
- for( i = 0; i < 3 ; i++)
- {
- temp_v = working.voltage[ i ];
- temp_i = working.current[ i ];
- temp_data[i] = ( ( temp_v * temp_i ) / DIVI_VALUE ) & 0x000000ff;
- }
- temp_data[3] = ( temp_data[0] > temp_data[1] )?
- ( ( temp_data[0] > temp_data[2] )? temp_data[0] : temp_data[2] ) :
- ( ( temp_data[1] > temp_data[2] )? temp_data[1] : temp_data[2] ) ;
- if( divider != (char)temp_data[3] )
- {
- //write to ade7758
- divider = (char)temp_data[3] + 1;
- for(i = 0; i < 3; i++)
- ADE_Write( ADD_WDIV + i, ( (int) divider << 8 ), 8 );
- }
- }
- /**
- * 功能:每秒读取功率
- */
- void ADE_ReadHR(void)
- {
- unsigned char i;
- unsigned int temp_data[9];//存放运算过程的中间变量
- //有功
- temp_data[ADD_AWATTHR - 1 ] = ADE_Read(ADD_AWATTHR,16);
- temp_data[ADD_BWATTHR - 1 ] = ADE_Read(ADD_BWATTHR,16);
- temp_data[ADD_CWATTHR - 1 ] = ADE_Read(ADD_CWATTHR,16);
- //无功
- temp_data[ADD_AVARHR - 1 ] = ADE_Read(ADD_AVARHR,16);
- temp_data[ADD_BVARHR - 1 ] = ADE_Read(ADD_BVARHR,16);
- temp_data[ADD_CVARHR - 1 ] = ADE_Read(ADD_CVARHR,16);
- //视在
- temp_data[ADD_AVAHR - 1 ] = ADE_Read(ADD_AVAHR,16);
- temp_data[ADD_BVAHR - 1 ] = ADE_Read(ADD_BVAHR,16);
- temp_data[ADD_CVAHR - 1 ] = ADE_Read(ADD_CVAHR,16);
- for( i = 0; i < 9 ; i++)
- {
- if( temp_data[ i ] > 0x7fff )
- temp_data[ i ] = 0xffff - temp_data[ i ] + 1;
- }
- if( divider > 1)
- {
- for( i = 0; i < 9; i++)
- temp_data[ i ] = temp_data[ i ] * divider;//乘上分频器的值
- }
- //能量的计算
- for( i = 0; i < 9; i++)
- energy[i] += temp_data[i];//累加电能值,单位为 WS(瓦秒)
- //转换成千瓦时
- for( i = 0; i < 3; i++)
- {
- working.watt_hour[i] += (energy[i] / 3600000);//转换成千瓦时
- energy[i] = energy[i] % 3600000;
- }
- working.watt_hour[3] = working.watt_hour[0] + working.watt_hour[1] + working.watt_hour[2];//总和
- //转换成千伏安时
- for( i = 0; i < 3; i++)
- {
- working.va_hour[i] += (energy[ i+6 ] / 3600000);//转换成千瓦时
- energy[ i+6 ] = energy[i+6] % 3600000;
- }
- working.va_hour[3] = working.va_hour[0] + working.va_hour[1] + working.va_hour[2];//总和
- for( working.watt[ 3 ] = 0, i = 0; i < 3; i++ )
- {
- working.watt[ i ] = temp_data[ i ]/1000;//千瓦
- working.watt[ 3 ] += working.watt[ i ];
- }
- for( working.var[ 3 ] = 0, i = 0; i < 3; i++ )
- {
- working.var[ i ] = temp_data[ i +3 ]/1000;
- working.var[ 3 ] += working.var[ i ];
- }
- for( working.va[ 3 ] = 0, i = 0; i < 3; i++ )
- {
- working.va[ i ] = temp_data[ i + 6 ] /1000;//千伏安
- if(working.va[ i ] < working.watt[ i ])
- working.va[ i ] = working.watt[ i ];
- working.va[ 3 ] += working.va[ i ];
- }
- }
- /**
- * 功能:实时读取电流电压值
- */
- void ADE_ReadVC(void)
- {
- unsigned char i, j;
- for( i = 0; i < 3; i++)
- {
- working.voltage[ i ] = 0;
- working.current[ i ] = 0;
- }
- for( i = 0; i < 3; i++)
- {
- for( j = 0; j < 5; j++)
- {
- working.voltage[ i ] += vo_buffer[j][i];
- working.current[ i ] += io_buffer[j][i];
- }
- }
- for( i = 0; i < 3; i++)
- {
- working.voltage[ i ] = working.voltage[ i ]/5;
- working.current[ i ] = working.current[ i ]/5;
- }
- //电压电流的三相平均值
- working.voltage[ 3 ] = (working.voltage[ 0 ] + working.voltage[ 1 ] + working.voltage[ 2 ] ) / 3;
- working.current[ 3 ] = (working.current[ 0 ] + working.current[ 1 ] + working.current[ 2 ] ) / 3;
- printf("voltage=%x current=%x\n",working.voltage[ 0 ], working.current[ 0 ]);
- }
- /**
- * 功能:从ADE7758中取出三相电压电流功率等电参量
- */
- void ADE_Update(void)
- {
- static unsigned char sample_cycle = 0; //电压采样周期,5次取平均
- static unsigned char bit_3s=0;
- unsigned char j;
- if( !bWorkModel ) //正常工作模式
- {
- if( bit_1s )
- {
- bit_1s = 0;
- ADE_ReadHR();
- if( (bit_3s++) >= 3 ) /*三秒检测一次异常*/
- {
- // ADE_AuCheck();
- bit_3s=0;
- }
- }
- for( j = 0; j < 3; j++)
- {
- vo_buffer[ sample_cycle ][j] = ADE_Read( ADD_AVRMS + j, 24 ) /*>> 12*/;//voltage
- io_buffer[ sample_cycle ][j] = ADE_Read( ADD_AIRMS + j, 24 ) /*>> 13*/;//current
- }
- if( sample_cycle == 4) /*读取5次取平均值*/
- ADE_ReadVC();
- }
- if( sample_cycle < 4 )
- sample_cycle += 1;
- else
- sample_cycle = 0;
- }
- /**
- * 测试硬件连接是否正确
- */
- u8 ADE_TestHard(void)
- {
- unsigned int rdata, wdata=0xaa5577;//AEHF=1,VAEHF=1,低8位无用
- u8 ret=0;
- ADE_Write(ADD_MASK,wdata,24);
- rdata = ADE_Read(ADD_MASK,24); // 验证通讯是否有问题
- if(rdata != wdata)
- printf("ADE error\r\n");
- else
- {
- ret = 1;
- printf("ADE OK\r\n");
- }
- return ret;
- }
- /**
- * 功能:7758初始化函数
- */
- void ADE_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd(ADE_RCC, ENABLE);
- GPIO_InitStructure.GPIO_Pin =ADE_PIN;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
- GPIO_Init(ADE_GPIO, &GPIO_InitStructure);
- ADE_CS(1);
- if(ADE_TestHard())
- {
- ADE_Write(ADD_OPMODE, 0x44,8); //软件复位
- ADE_udelay(); //添加延时 确保复位成功
- }
- }
- void ADE_thread_entry(void)
- {
- SPI2_Init();
- ADE_Init();
- while(1)
- {
- ADE_Update();
- delay_ms( 50 ); /* 等待,让出cpu权限,切换到其他线程 */
- }
- }
上一篇:STM32查看系统时钟
下一篇:STM32 外部 SRAM
推荐阅读最新更新时间:2024-03-16 15:02
设计资源 培训 开发板 精华推荐
- 围观Vishay新出炉超低ESR T55系列“萌宠们”,有惊喜!
- 电源情报站 MPS小程序干货推荐,下载有好礼!
- 【有奖直播】 聚焦语音识别核心技术,走进Microchip Timberwolf™音频处理器研讨会
- 为何矢量网络分析仪喊话:多端口测试,是时候放弃开关矩阵了
- EEWORLD社区月度奖励,赠E金币!
- TI有奖直播|如何进行更加快速、简单且成本更低的AI 摄像头应用的开发
- 有奖直播|魏德米勒 OMNIMATE® 联接技术的创新发展
- 直播已结束|如何通过【TI MSPM0 固件示例】及【常用电机驱动器方案和拓扑】,在10分钟内旋转电机
- e络盟限时福利|《e选》产品低至5折起,下单百元返现中!
- 大比拼!DIY数字湿度计