打印
[STM32F1]

stm32f101c8操作ADE7758

[复制链接]
2285|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xddl|  楼主 | 2014-4-29 17:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
stm32f101c8操作ADE7758,读电压,第一个字节总读不对,但是CHKSUM却是对的,为什么?


#include "stm32f10x.h"
#include "ade7758.h"


#define ADE_SELECT()                GPIO_ResetBits(GPIOB, GPIO_Pin_12);Delay(50);        /* CS = L */
#define ADE_DESELECT()                Delay(400); GPIO_SetBits(GPIOB, GPIO_Pin_12);          /* CS = H */

static void Delay(u32 Nus)
{
     u32 t = 8*Nus;
     while(--t);
}
/***********************************************
**注意事项:ADE7758使用了SPI2接口
***********************************************/
void ADE_SPI_Config(void)
{
     SPI_InitTypeDef  SPI_InitStructure;
     GPIO_InitTypeDef GPIO_InitStructure;

     RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

     /* SCK, MISO and MOSI  B13=CLK,B14=MISO,B15=MOSI*/
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
     GPIO_Init(GPIOB, &GPIO_InitStructure);
     /*  PB.12 作片选*/
         GPIO_SetBits(GPIOB, GPIO_Pin_12);//预置为高
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
     GPIO_Init(GPIOB, &GPIO_InitStructure);

     /* SPI2 configuration CPOL=0,CPHA=1 (针对ADE7758时序)*/
         SPI_Cmd(SPI2, DISABLE);                                                                                                 //必须先禁能,才能改变MODE
     SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;                //两线全双工
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                                                        //主
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                                                //8位
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                                                                //CPOL=0 时钟悬空低
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;                                                        //CPHA=1 数据捕获第2个
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft ;                                                                //软件NSS
     SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;        //128分频
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                                                //高位在前
    SPI_InitStructure.SPI_CRCPolynomial = 0;                                                                //??
     
         SPI_Init(SPI2, &SPI_InitStructure);
//    SPI_SSOutputCmd(SPI2, ENABLE); //使能NSS脚可用
    SPI_Cmd(SPI2, ENABLE);

}
unsigned char SPI2_ReadWriteByte(unsigned char TxData)
{   
     unsigned long retry = 0;
     
     while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位  
     {
         retry++;   
         if(retry > 90000)
             return 0;
     }
     SPI2->DR = TxData;
     //SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个数据
   
     retry = 0;
     while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位  
     {
         retry++;
         if(retry > 90000)
             return 0;
     }
     return(SPI2->DR);
     //return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据
}


/*
*******************************************************************************
**函数名称: void ADE7758_WR( uint8 REG_ADDR,uint32 data,uint8 cnt )        **
**函数描述:ADE7758写操作                                             **
**参    数: REG_ADDR---寄存器地址                                **
**          data-------待写入的数据                                        **
**          cnt--------寄存器宽度(字节数)                                  **
**返    回:        无                                        **
*******************************************************************************
*/
static void ADE7758_WR(unsigned char REG_ADDR, unsigned long data, int cnt)
{
     ADE_SELECT();
     
     SPI2_ReadWriteByte(REG_ADDR|0x80);                   //写地址

    switch(cnt)                                //写数据
    {
         case 1:
             SPI2_ReadWriteByte( (unsigned char)(data) );         //发送一个字节数据
        break;
         case 2:
             SPI2_ReadWriteByte( (unsigned char)(data>>8) );      //发送两个字节数据,高节字在前
            SPI2_ReadWriteByte( (unsigned char)(data) );
         break;
         case 3:
             SPI2_ReadWriteByte( (unsigned char)(data>>16) );     //发送三个字节数据,高节字在前
            SPI2_ReadWriteByte( (unsigned char)(data>>8) );
             SPI2_ReadWriteByte( (unsigned char)(data) );
         break;
         default:
         break;
      }
     ADE_DESELECT();
}

/*
*******************************************************************************
**函数名称: uint32 ADE7758_RD( uint8 REG_ADDR,uint8 cnt )                   **
**函数描述:ADE7758读操作                                              **
**参    数: REG_ADDR---寄存器地址                                 **
**          cnt--------寄存器宽度(字节数)                                   **
**返    回: data-------寄存器的值                                  **
*******************************************************************************
*/
static unsigned long ADE7758_RD(unsigned char REG_ADDR, int cnt)
{
     unsigned long data;

     ADE_SELECT();
     
     SPI2_ReadWriteByte(REG_ADDR);                         //读地址
    Delay(400);
     switch(cnt)                                 //读数据
    {
         case 1:
             data = SPI2_ReadWriteByte(0x00);                  //接收一个字节数据
        break;
         case 2:
             data = SPI2_ReadWriteByte(0x00);                  //接收两个字节数据,高节字在前
            data <<= 8;
             data |= SPI2_ReadWriteByte(0x00);
         break;
         case 3:
             data = SPI2_ReadWriteByte(0x00);                 //接收三个字节数据,高节字在前
            data <<= 8;
             data |= SPI2_ReadWriteByte(0x00);
             data <<= 8;
             data |= SPI2_ReadWriteByte(0x00);
         break;
         default:
         break;
     }
     ADE_DESELECT();
     return data;
}
/*
*******************************************************************************
**函数名称: void ADE7758_CFG( uint8 CSn )                                    **
**函数描述: ADE7758初始化程序                                                **
**返    回:        无                                                        **
*******************************************************************************
*/
void ADE7758_CFG(void)
{
     //寄存器初始化配置代码
    ADE7758_WR(OPMODE,0x40,1);      //软件复位
    Delay(150);                      //大于18us的延时
        
     ADE7758_WR(LCYCMODE,0x78,1);          //写周期循模式寄存器        17H为0x78
     ADE7758_WR(GAIN,0x00,1);              //写PGA增益寄存器           23H为0x00

     ADE7758_WR(AVRMSOS,0x00,2);           //写A相电压有效值校正寄存器 33H为0x00
     ADE7758_WR(BVRMSOS,0x00,2);           //写B相电压有效值校正寄存器 34H为0x00
     ADE7758_WR(CVRMSOS,0x00,2);           //写C相电压有效值校正寄存器 35H为0x00

     ADE7758_WR(AIRMSOS,0x00,2);           //写A相电流有效值校正寄存器 36H为0x00
     ADE7758_WR(BIRMSOS,0x00,2);           //写B相电流有效值校正寄存器 37H为0x00
     ADE7758_WR(CIRMSOS,0x00,2);           //写C相电流有效值校正寄存器 38H为0x00
}

static int chksum(const unsigned char chk, const unsigned long num)
{
     unsigned char sum = 0;
     
     for(int i = 0; i < 24; i++)
     {
         sum += ((num >> i)&0x01);
     }
     
     if(sum == chk)
         return(1);
     else
         return(0);
}

void read_voltage_current(unsigned long * vol, unsigned long * cur)
{
     unsigned char cksum;
     unsigned long tmp;

     tmp = 0; cksum = 0;
     tmp = ADE7758_RD(AIRMS, 3);         // A相电流
    cksum = ADE7758_RD(CHKSUM, 1);
     if(chksum(cksum,tmp))
         cur[0] = tmp;
     
     tmp = 0; cksum = 0;
     tmp = ADE7758_RD(BIRMS, 3);         // B相电流
    cksum = ADE7758_RD(CHKSUM, 1);
     if(chksum(cksum,tmp))
         cur[1] = tmp;
     
     tmp = 0; cksum = 0;
     tmp = ADE7758_RD(CIRMS, 3);         // C相电流
    cksum = ADE7758_RD(CHKSUM, 1);
     if(chksum(cksum,tmp))
         cur[2] = tmp;
     
     tmp = 0; cksum = 0;
     tmp = ADE7758_RD(AVRMS, 3);         // A相电压
    cksum = ADE7758_RD(CHKSUM, 1);
     if(chksum(cksum,tmp))
         vol[0] = tmp;
     
     tmp = 0; cksum = 0;
     tmp = ADE7758_RD(BVRMS, 3);         // B相电压
    cksum = ADE7758_RD(CHKSUM, 1);
     if(chksum(cksum,tmp))
         vol[1] = tmp;
     
     tmp = 0; cksum = 0;
     tmp = ADE7758_RD(CVRMS, 3);         // C相电压
    cksum = ADE7758_RD(CHKSUM, 1);
     if(chksum(cksum,tmp))
         vol[2] = tmp;
}
沙发
mmuuss586| | 2014-4-29 17:34 | 只看该作者
没用过ADI电能测量芯片。
可以问下世健的技术支持,他们应该有参考程序。

使用特权

评论回复
板凳
xddl|  楼主 | 2014-4-29 19:15 | 只看该作者
能提供一下具体的联系方式不?

使用特权

评论回复
地板
shouqiang_zhang| | 2015-1-20 21:44 | 只看该作者
xddl 发表于 2014-4-29 19:15
能提供一下具体的联系方式不?

楼主的程序调好了没有? 我用STM32 的SPI2操作AD7794, 弄了几天了,还没有头绪, 你的程序可以参考下吗? 谢谢.

使用特权

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

本版积分规则

30

主题

89

帖子

1

粉丝