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;
}
|