STM32_ADE7758驱动

发布者:数字驿站最新更新时间:2016-07-30 来源: eefocus关键字:STM32  ADE7758驱动 手机看文章 扫描二维码
随时随地手机看文章
  1. /*
  2.  * ade7758.c
  3.  *
  4.  * Created on: 2014年10月11日
  5.  * Author: Lzy
  6.  */
  7. //#include 
  8. #include "ade7758.h"
  9. #include "sys.h"
  10.  
  11. #define ADE_CS_PIN     PBout(12)
  12.  
  13. #define ADE_RCC RCC_APB2Periph_GPIOB
  14. #define ADE_GPIO GPIOB
  15. #define ADE_PIN (GPIO_Pin_12)
  16.  
  17.  
  18. unsigned char bWorkModel=0;//工作模式标志位 1:校准模式;0:正常工作模式;
  19. unsigned char bit_1s=0; //1s钟标志,在时钟中断函数中置位
  20.  
  21. static unsigned char divider = 1;//电能分频器,默认值为零,视在功率超出一定值时,自动将该值提高
  22. static unsigned int energy[9];//用于累加电能值 36
  23.  
  24. struct all_data working;//正常工作模式下存放的电参量 95
  25. static unsigned int vo_buffer[5][3];//用于电压的积分虑波 36
  26. static unsigned int io_buffer[5][3];//用于电流的积分虑波 36
  27.  
  28.  
  29. /**
  30.  * 功能:片选使能
  31.  */
  32. void ADE_CS(unsigned char cs)
  33. {
  34.     ADE_CS_PIN = cs;
  35.     delay_ms(1);
  36. }
  37.  
  38. /**
  39.  * 功能:延时函数 50us
  40.  */
  41. void ADE_udelay(void)
  42. {
  43.     delay_ms(1);
  44. }
  45.  
  46. /**
  47.  * 功能:通过SPI写入数据至芯片
  48.  * 入口参数:
  49.  *         buf -> 数据缓冲区
  50.  *         len -> 数据长度
  51.  */
  52. void ADE_SPIWrite(unsigned char *buf, unsigned char len)
  53. {
  54.     SPI2_Write(buf,len);
  55. }
  56.  
  57.  
  58. /**
  59.  * 功能:通过SPI读芯片数据
  60.  * 入口参数:len -> 数据长度
  61.  * 出口参数:    buf -> 数据缓冲区
  62.  *
  63.  */
  64. void ADE_SPIRead(unsigned char *buf, unsigned char len)
  65. {
  66.     SPI2_Read(buf,len);
  67. }
  68.  
  69. /**
  70.  * 功能:7758写数据函数
  71.  * 入口参数:
  72.  * type:目标寄存器的地址
  73.  * wdata:写进寄存器的内容
  74.  * databit:目标寄存器的宽度
  75.  * 出口参数:NULL
  76.  * 返回值:NULL
  77.  */
  78. void ADE_Write(unsigned char type,unsigned int wdata,unsigned char databit)
  79. {
  80.     unsigned char data[4];
  81.  
  82.     ADE_CS(0);
  83.     type = type | 0x80;
  84.  
  85.     data[0] = type;
  86.     ADE_SPIWrite(data, 1);
  87.     ADE_udelay();
  88.  
  89.     if(databit == 8)
  90.     {
  91.         data[0] = wdata;
  92.         ADE_SPIWrite(data, 1);
  93.     }
  94.     else if(databit == 16)
  95.     {
  96.         data[0] = (wdata&0xff00) >> 8; /*高8位*/
  97.         data[1] = (wdata&0x00ff); /*底8位*/
  98.         ADE_SPIWrite(data, 2);
  99.     }
  100.     else if(databit == 24)
  101.     {
  102.         data[0] = (wdata&0xff0000) >> 16; /*高8位*/
  103.         data[1] = (wdata&0xff00)>>8;
  104.         data[2] = (wdata&0xff);
  105.         ADE_SPIWrite(data, 3);
  106.     }
  107.     else
  108.         printf("ADE write databit Error:%d\n", databit);
  109.     ADE_CS(1);
  110. }
  111.  
  112. /**
  113.  * 功能:7758读寄存器函数
  114.  * 入口参数:
  115.  *          type:目标寄存器的地址
  116.  * databit:目标寄存器的宽度
  117.  * 出口参数:指定寄存器的内容
  118.  * 返回值:指定寄存器的内容
  119.  */
  120. unsigned int ADE_Read(unsigned char type,unsigned char databit)
  121. {
  122.     unsigned char data[4]={0,0,0,0};
  123.     unsigned int rtdata = 0;
  124.  
  125.     ADE_CS(0);
  126.     type = type & 0x7F;
  127.     data[0] = type;
  128.     ADE_SPIWrite(data, 1);
  129.     ADE_udelay();
  130.  
  131.     if(databit == 8)
  132.     {
  133.         ADE_SPIRead(data,1);
  134.         rtdata = data[0];
  135.     }
  136.     else if(databit == 12)
  137.     {
  138.         ADE_SPIRead(data,2);
  139.         rtdata = (data[0]&0x0f) << 8;
  140.         rtdata += data[1];
  141.     }
  142.     else if(databit == 16)
  143.     {
  144.         ADE_SPIRead(data,2);
  145.         rtdata = data[0] << 8;
  146.         rtdata += data[1];
  147.     }else if(databit == 24)
  148.     {
  149.         ADE_SPIRead(data,3);
  150.         rtdata = data[0] << 16;
  151.         rtdata += (data[1] << 8);
  152.         rtdata += data[2];
  153.     }
  154.     else
  155.         printf("ADE Read databit Error:%d\n", databit);
  156.     ADE_CS(1);
  157.     return(rtdata);
  158. }
  159.  
  160.  
  161. /**
  162.  * 功能:检测异常
  163.  */
  164. void ADE_AuCheck(void)
  165. {
  166.     unsigned char i;
  167.     unsigned int temp_data[5];//存放运算过程的中间变量
  168.     unsigned int temp_v,temp_i;
  169.  
  170.     //自动检测ADE7758是否出现异常
  171.     if( working.voltage[ 0 ] > ERR_VOLTAGE ||
  172.             working.voltage[ 1 ] > ERR_VOLTAGE ||
  173.             working.voltage[ 2 ] > ERR_VOLTAGE )
  174.     {
  175.         //        ADE_Check7758();
  176.         printf("ADE Error\n" );
  177.     }
  178.  
  179.     //自动设置分频器的大小
  180.     for( i = 0; i < 3 ; i++)
  181.     {
  182.         temp_v = working.voltage[ i ];
  183.         temp_i = working.current[ i ];
  184.         temp_data[i] = ( ( temp_v * temp_i ) / DIVI_VALUE ) & 0x000000ff;
  185.     }
  186.  
  187.     temp_data[3] = ( temp_data[0] > temp_data[1] )?
  188.             ( ( temp_data[0] > temp_data[2] )? temp_data[0] : temp_data[2] ) :
  189.             ( ( temp_data[1] > temp_data[2] )? temp_data[1] : temp_data[2] ) ;
  190.  
  191.     if( divider != (char)temp_data[3] )
  192.     {
  193.         //write to ade7758
  194.         divider = (char)temp_data[3] + 1;
  195.  
  196.         for(i = 0; i < 3; i++)
  197.             ADE_Write( ADD_WDIV + i, ( (int) divider << 8 ), 8 );
  198.     }
  199. }
  200.  
  201. /**
  202.  * 功能:每秒读取功率
  203.  */
  204. void ADE_ReadHR(void)
  205. {
  206.     unsigned char i;
  207.     unsigned int temp_data[9];//存放运算过程的中间变量
  208.  
  209.     //有功
  210.     temp_data[ADD_AWATTHR - 1 ] = ADE_Read(ADD_AWATTHR,16);
  211.     temp_data[ADD_BWATTHR - 1 ] = ADE_Read(ADD_BWATTHR,16);
  212.     temp_data[ADD_CWATTHR - 1 ] = ADE_Read(ADD_CWATTHR,16);
  213.     //无功
  214.     temp_data[ADD_AVARHR - 1 ] = ADE_Read(ADD_AVARHR,16);
  215.     temp_data[ADD_BVARHR - 1 ] = ADE_Read(ADD_BVARHR,16);
  216.     temp_data[ADD_CVARHR - 1 ] = ADE_Read(ADD_CVARHR,16);
  217.     //视在
  218.     temp_data[ADD_AVAHR - 1 ] = ADE_Read(ADD_AVAHR,16);
  219.     temp_data[ADD_BVAHR - 1 ] = ADE_Read(ADD_BVAHR,16);
  220.     temp_data[ADD_CVAHR - 1 ] = ADE_Read(ADD_CVAHR,16);
  221.  
  222.     for( i = 0; i < 9 ; i++)
  223.     {
  224.         if( temp_data[ i ] > 0x7fff )
  225.             temp_data[ i ] = 0xffff - temp_data[ i ] + 1;
  226.     }
  227.  
  228.     if( divider > 1)
  229.     {
  230.         for( i = 0; i < 9; i++)
  231.             temp_data[ i ] = temp_data[ i ] * divider;//乘上分频器的值
  232.     }
  233.  
  234.     //能量的计算
  235.     for( i = 0; i < 9; i++)
  236.         energy[i] += temp_data[i];//累加电能值,单位为 WS(瓦秒)
  237.  
  238.     //转换成千瓦时
  239.     for( i = 0; i < 3; i++)
  240.     {
  241.         working.watt_hour[i] += (energy[i] / 3600000);//转换成千瓦时
  242.         energy[i] = energy[i] % 3600000;
  243.     }
  244.  
  245.     working.watt_hour[3] = working.watt_hour[0] + working.watt_hour[1] + working.watt_hour[2];//总和
  246.  
  247.     //转换成千伏安时
  248.     for( i = 0; i < 3; i++)
  249.     {
  250.         working.va_hour[i] += (energy[ i+6 ] / 3600000);//转换成千瓦时
  251.         energy[ i+6 ] = energy[i+6] % 3600000;
  252.     }
  253.  
  254.     working.va_hour[3] = working.va_hour[0] + working.va_hour[1] + working.va_hour[2];//总和
  255.  
  256.     for( working.watt[ 3 ] = 0, i = 0; i < 3; i++ )
  257.     {
  258.         working.watt[ i ] = temp_data[ i ]/1000;//千瓦
  259.         working.watt[ 3 ] += working.watt[ i ];
  260.     }
  261.  
  262.     for( working.var[ 3 ] = 0, i = 0; i < 3; i++ )
  263.     {
  264.         working.var[ i ] = temp_data[ i +3 ]/1000;
  265.         working.var[ 3 ] += working.var[ i ];
  266.     }
  267.  
  268.     for( working.va[ 3 ] = 0, i = 0; i < 3; i++ )
  269.     {
  270.         working.va[ i ] = temp_data[ i + 6 ] /1000;//千伏安
  271.  
  272.         if(working.va[ i ] < working.watt[ i ])
  273.             working.va[ i ] = working.watt[ i ];
  274.  
  275.         working.va[ 3 ] += working.va[ i ];
  276.     }
  277.  
  278.  
  279. }
  280.  
  281. /**
  282.  * 功能:实时读取电流电压值
  283.  */
  284. void ADE_ReadVC(void)
  285. {
  286.     unsigned char i, j;
  287.  
  288.     for( i = 0; i < 3; i++)
  289.     {
  290.         working.voltage[ i ] = 0;
  291.         working.current[ i ] = 0;
  292.     }
  293.  
  294.     for( i = 0; i < 3; i++)
  295.     {
  296.         for( j = 0; j < 5; j++)
  297.         {
  298.             working.voltage[ i ] += vo_buffer[j][i];
  299.             working.current[ i ] += io_buffer[j][i];
  300.         }
  301.     }
  302.  
  303.     for( i = 0; i < 3; i++)
  304.     {
  305.         working.voltage[ i ] = working.voltage[ i ]/5;
  306.         working.current[ i ] = working.current[ i ]/5;
  307.     }
  308.  
  309.     //电压电流的三相平均值
  310.     working.voltage[ 3 ] = (working.voltage[ 0 ] + working.voltage[ 1 ] + working.voltage[ 2 ] ) / 3;
  311.     working.current[ 3 ] = (working.current[ 0 ] + working.current[ 1 ] + working.current[ 2 ] ) / 3;
  312.  
  313.     printf("voltage=%x current=%x\n",working.voltage[ 0 ], working.current[ 0 ]);
  314. }
  315.  
  316.  
  317. /**
  318.  * 功能:从ADE7758中取出三相电压电流功率等电参量
  319.  */
  320. void ADE_Update(void)
  321. {
  322.     static unsigned char sample_cycle = 0; //电压采样周期,5次取平均
  323.     static unsigned char bit_3s=0;
  324.     unsigned char j;
  325.  
  326.     if( !bWorkModel )    //正常工作模式
  327.     {
  328.         if( bit_1s )
  329.         {
  330.             bit_1s = 0;
  331.             ADE_ReadHR();
  332.  
  333.             if( (bit_3s++) >= 3 ) /*三秒检测一次异常*/
  334.             {
  335.                 //                ADE_AuCheck();
  336.                 bit_3s=0;
  337.             }
  338.         }
  339.  
  340.         for( j = 0; j < 3; j++)
  341.         {
  342.             vo_buffer[ sample_cycle ][j] = ADE_Read( ADD_AVRMS + j, 24 ) /*>> 12*/;//voltage
  343.             io_buffer[ sample_cycle ][j] = ADE_Read( ADD_AIRMS + j, 24 ) /*>> 13*/;//current
  344.         }
  345.  
  346.         if( sample_cycle == 4) /*读取5次取平均值*/
  347.             ADE_ReadVC();
  348.     }
  349.  
  350.     if( sample_cycle < 4 )
  351.         sample_cycle += 1;
  352.     else
  353.         sample_cycle = 0;
  354.  
  355. }
  356.  
  357. /**
  358.  * 测试硬件连接是否正确
  359.  */
  360. u8 ADE_TestHard(void)
  361. {
  362.     unsigned int rdata, wdata=0xaa5577;//AEHF=1,VAEHF=1,低8位无用
  363.     u8 ret=0;
  364.  
  365.     ADE_Write(ADD_MASK,wdata,24);
  366.     rdata = ADE_Read(ADD_MASK,24); // 验证通讯是否有问题
  367.  
  368.     if(rdata != wdata)
  369.         printf("ADE error\r\n");
  370.     else
  371.     {
  372.         ret = 1;
  373.         printf("ADE OK\r\n");
  374.     }
  375.  
  376.     return ret;
  377. }
  378.  
  379. /**
  380.  * 功能:7758初始化函数
  381.  */
  382. void ADE_Init(void)
  383. {
  384.     GPIO_InitTypeDef GPIO_InitStructure;
  385.  
  386.     RCC_APB2PeriphClockCmd(ADE_RCC, ENABLE);
  387.     GPIO_InitStructure.GPIO_Pin =ADE_PIN;
  388.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;          //推挽输出
  389.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         //IO口速度为50MHz
  390.     GPIO_Init(ADE_GPIO, &GPIO_InitStructure);
  391.     ADE_CS(1);
  392.  
  393.     if(ADE_TestHard())
  394.     {
  395.         ADE_Write(ADD_OPMODE, 0x44,8); //软件复位
  396.         ADE_udelay(); //添加延时 确保复位成功
  397.     }
  398. }
  399.  
  400.  
  401.  
  402. void ADE_thread_entry(void)
  403. {
  404.     SPI2_Init();
  405.     ADE_Init();
  406.  
  407.     while(1)
  408.     {
  409.         ADE_Update();
  410.         delay_ms( 50 ); /* 等待,让出cpu权限,切换到其他线程 */
  411.     }
  412. }
关键字:STM32  ADE7758驱动 引用地址:STM32_ADE7758驱动

上一篇:STM32查看系统时钟
下一篇:STM32 外部 SRAM

推荐阅读最新更新时间:2024-03-16 15:02

C语言宏定义的使用原理
使用STM32开发的朋友不知道是否有发现过这样的一些宏定义? 如下: #if defined (__CC_ARM) #pragma anon_unions #endif 看到上面的语句一开始确实搞不懂为什么要写这些东西,通过上网去查询,才搞明白这其中的使用原理。 上面的代码段我们可以看到两部分的内容: 1) __CC_ARM 2) #pragma anon_unions 这两个都有啥用呢? 待我一一道来! 1、__CC_ARM 是 ARM 编译中的宏选项 __CC_ARM 是一个编译器的选项,在ARM开发中根据开发环境的不同,有好几个可选的宏选项。
[单片机]
基于STM32的MDK程序启动
;//HeapSize(inBytes) 0x0-0xFFFFFFFF:8 ;// Heap_SizeEQU0x00000020;//定义堆空间大小 AREAHEAP,NOINIT,READWRITE,ALIGN=3;//定义一个数据段,8字节对齐 __heap_base Heap_MemSPACEHeap_Size;//保留Heap_Size的堆空间 __heap_limit;//标号,代表堆末尾地址,后面有用 PRESERVE8;//指示编译器8字节对齐 THUMB;//指示编译器为THUMB指令 ;VectorTableMappedtoAddress0atReset AREARESET,DATA,READONLY;//
[单片机]
STM32学习:ADC/DMA/USART
  学习STM32的ADC转换,在开发板上写程序调试。   四个任务:   1.AD以中断方式(单次)采集一路   2.AD以中断方式连续采集四路   3.AD以DMA方式采集一路,DMA深度为一级   4.AD以DMA方式采集四路,每路DMA深度为28级,并滤波,说明滤波原理。   总结:   第一个任务:ADC以中断方式采集一路ADC,通过配置ADC_InitStructure结构体中的ADC_ScanConvMode,它规定模数转换工作在扫描模式(多通道)还是单次模式(单通道),   ADC_InitStructure.ADC_ScanConvMode=DISABLE,为单通道单次模式。   ADC_ContinuousCo
[单片机]
STM32开发笔记8: STM32CubeF0介绍
单片机型号:STM32CubeF0 本文介绍 STM32CubeF0。 STM32CubeF0 gathers, in a single package, all the generic embedded software components required to develop an application on STM32F0 microcontrollers. In line with the STMCube™ initiative(首创), this set of components is highly portable, not only within STM32F0 Series but also
[单片机]
<font color='red'>STM32</font>开发笔记8: STM32CubeF0介绍
STM32之串口通信
实验目的: 实现利用串口1 不停的打印一个信息到电脑上,同时接收从串口发过来的数据,把发送过来的数据直接送回给电脑。 实验平台: 基于STM32F103C8T6的彩屏开发板 硬件接口: 注意:因为我的开发板上的串口和LED共用了PA9和PA10,所以在使用USART1时务必屏蔽LED,不然两者会互相影响而导致实现现象无法呈现。 相关寄存器: 1,串口时钟使能。串口作为STM32 的一个外设,其时钟由外设时钟使能寄存器控制,这 里我们使用的串口1 是在APB2ENR 寄存器的第14 位。 2,串口复位。串口1 的复位是通过配置APB2RSTR 寄存器的第14 位来实现的。。通
[单片机]
STM32时钟树解析
本人之前其实也用STM32做过一些小东西,但因为时钟的初始化一般是直接在SystemInit时钟系统初始化函数里直接配置为72MHz,所以对于STM32的时钟框图并没有怎么理会,今天刚好有空就重新看了一下并写一篇博客记录一下吧,以免以后又忘了。 STM32 有5个时钟源:HSI、HSE、LSI、LSE、PLL。 ①、HSI(High Speed Internal Clock signal)是高速内部时钟,RC振荡器,频率为8MHz,精度不高,受温度影响。  ②、HSE(High Speed External Clock signal)是高速外部时钟,为外接晶振提供的时钟,晶振频率范围为4MHz~16MHz,常用8MHz的外
[单片机]
<font color='red'>STM32</font>时钟树解析
stm32 运行时间测量与间隔执行
这个程序利用stm32普通定时器构成了执行时间测量功能和间隔执行函数功能,使用如下,两种功能复用,通过#define选择 //执行时间测试模式下 #define StopWatch //使用: #include Runtime.h Runtime_init(); while(1){ Runtime_start(); delay_ms(1); Runtime_stop(); delay_ms(1000); } //setInterval模式 #define setInterval setInterval(fun,1000);//传入回调,周期1.024*1000ms c文件
[单片机]
基于STM32中串口通信的实例分析
串口是串行接口(serial port)的简称,也称为串行通信接口或COM接口。串口通信是指采用串行通信协议(serial communication)在一条信号线上将数据一个比特一个比特地逐位进行传输的通信模式。串口按电气标准及协议来划分,包括RS-232-C、RS-422、RS485等。 在串行通信中,数据在1位宽的单条线路上进行传输,一个字节的数据要分为8次,由低位到高位按顺序一位一位的进行传送。串行通信的数据是逐位传输的,发送方发送的每一位都具有固定的时间间隔,这就要求接收方也要按照发送方同样的时间间隔来接收每一位。不仅如此,接收方还必须能够确定一个信息组的开始和结束。 常用的两种基本串行通信方式包括同步通信和异步通信
[单片机]
基于<font color='red'>STM32</font>中串口通信的实例分析
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved