打印

ade7758读3字节,第一个字节读的不对

[复制链接]
1239|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xddl|  楼主 | 2014-4-29 17:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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;
}

相关帖子

沙发
xddl|  楼主 | 2014-4-30 12:01 | 只看该作者
比如,读A相电压,实际值为0x0001C289,但有时读出来为0X0000C289,但是CHKSUM却都是对的

使用特权

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

本版积分规则

30

主题

89

帖子

1

粉丝