大家好!第一次写东西,完全是当作自己的一个笔记来写的,笔法不成熟,有些凌乱。如果对一些小伙伴有所帮助的话是我的荣幸,也欢迎各位小伙伴指出其中的问题。
首先说一下,使用这款芯片呢是因为一个项目需求,之前一直使用的是ADE9078这款,但为了节约成本,而且项目需求是单相电就行,所以选取了ATT7053C这款芯片。一开始的时候,和钜泉光电那边的技术人员也沟通过,提供过一些demo程序,当对于我的开发项目没有太大的帮助。言归正传。
该项目使用的单片机是GD32系列的,没有选取ST是因为成本高、其次是供货不稳定。
说明:图示代码可能会有部分宏缺失,主要是做一个经验记录,如有需求,欢迎评论区交流。
管脚分配图:
PB12 | SPI1_NSS | 计量芯片ATT7053C SPI通讯 | 输出 | SPI片选信号 |
PB13 | SPI1_SCK | 输出 | SPI片时钟信号 | |
PB14 | SPI1_MISO | 输入 | SPI主输入从输出 | |
PB15 | SPI1_MOSI | 输出 | SPI主输出从输入 |
1、配置好基本驱动
参照GD32技术手册,配置好SPI以及GPIO口的基本驱动。
void Ade_SPI_Config_Init(void)
{
spi_parameter_struct spi_init_struct ;
/* SPI 初始化定义 */
spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX;//双线全双工
spi_init_struct.device_mode = SPI_MASTER; //SPI工作在主机模式
spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT; //数据帧大小8bit
spi_init_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE; //CKPL=1,CKPH=1
spi_init_struct.nss = SPI_NSS_SOFT; //软件控制片选信号nss
spi_init_struct.prescale = SPI_PSC_128; //分频
spi_init_struct.endian = SPI_ENDIAN_MSB; //数据传输从 MSB 位开始,高位在前
spi_init(PORT_ATT7053_SPI, &spi_init_struct);
spi_enable(PORT_ATT7053_SPI);
}
void Ade_SPI_Pin_GPIO_Init(void)
{
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_SPI1);
rcu_periph_clock_enable(RCU_AF);
gpio_init(PORT_ATT7053_SPIDIN, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, PIN_ATT7053_SPI_DIN);
gpio_init(PORT_ATT7053_SPICLK, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, PIN_ATT7053_SPI_CLK);
gpio_init(PORT_ATT7053_SPIDOUT,GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, PIN_ATT7053_SPI_DOUT);
gpio_init(PORT_ATT7053_SPICS, GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ, PIN_ATT7053_SPI_CS);
}
2、编写SPI数据传输函数,此部分请阅读多理解SPI传输时序图。
2.1 ATT7053C的SPI接口说明
SPI/UART:选择引脚通讯模式。0:选择UART功能 ;1:选择SPI功能。芯片内部上拉默认为SPI通信方式。
(1)SPIDI:ATT7053C的串行数据接收引脚。
(2)SPIDO:ATT7053C 的串行数据发送引脚。
(3)SPICLK:ATT7053C 的串行时钟引脚,决定数据移出或者移入SPI口的传输速度,上升沿放数据,下降沿取数据。SCLK上升沿时将ATT7053C 寄存器中的数据放置于DOUT上输出,SCLK下降沿时将DIN上的数据采样到ATT7053C中。
(4)SPICS:作为ATT7053C 的片选信号,低电平有效,用户可以通过SPICS引脚的高低来启动 / 终止一次SPI传输。对于三线SPI通讯模式,需要将SPICS一直拉低,按照固定的8bit通讯地址,24bit通讯数据这样的通讯帧方式来读/写ATT7053C 的计量寄存器。
2.2 ATT7053C的SPI通讯定义
(1)固定长度的数据传输(一共4个字节),即每次数据通讯都是1个字节命令和3个字节的数据。
(2)通讯中从机输出是以SCK上升沿输出数据,从机输入是从SCK下降沿采样数据,MSB在前,LSB在后。
(3)命令寄存器的接收会清0内部的SPI数据传输的数据寄存器。
(4)SPI通讯的帧结构:
命令寄存器:读写位+7位要访问的寄存器地址(接收主机的命令)
数据寄存器:3字节(24bit)(接收主机送来的数据)
2.3 ATT7053C的SPI 通讯波形
CS:片选(INPUT),允许访问控制线,CS发生下降沿跳变时表示SPI操作开始,CS发生上升沿跳变时表示SPI操作结束。
DIN:串行数据输入(INPUT),用于把数据传输到ATT7053C中。
DOUT:串行数据输出(OUTPUT),用于从ATT7053C 寄存器中读出数据。
SCLK:串行时钟(INPUT),控制数据移出或移入串行口的传输率。上升沿放数据,下降沿取数据。SCLK上升沿时将ATT7053C 寄存器中的数据放置于DOUT上输出,SCLK下降沿时将DIN上的数据采样到ATT7053C 中。
2.4 SPI传输函数代码
void Att_SPI_Transfer_Block(UINT8 *tx_p, UINT8 *rx_p, UINT8 Trans_number)
{
UINT8 i;
ENABLE_ATT7053_SPI_CS;//片选拉低
for(i=0;i<Trans_number;i++)
{
*rx_p=Att_SPI_TransferByte(*tx_p);
tx_p++;
rx_p++;
}
DISABLE_ATT7053_SPI_CS;//片选拉高
}
UINT8 Att_SPI_TransferByte(UINT8 TxData)
{
while(spi_i2s_flag_get(PORT_ATT7053_SPI, SPI_FLAG_TBE) == RESET);
/* 发送一个字节 */
spi_i2s_data_transmit(PORT_ATT7053_SPI, TxData);
/* 等待数据接收完毕 */
while(spi_i2s_flag_get(PORT_ATT7053_SPI, SPI_FLAG_RBNE) == RESET);
return spi_i2s_data_receive(PORT_ATT7053_SPI);
}
2.5 读寄存器接口函数代码
int ATT7053_Get( UINT8 addr, UINT8 *data, WORD len )
{
UINT8 byloop=0;
UINT8 byTxBuff[4], byRxBuff[4],*ptTxBuff=0,byTransNum=0;
if(len>4)
{
return -1;
}
byTxBuff[0] = addr | Att7053_readflag; //readflag为0,参考技术手册
ptTxBuff = &byTxBuff[1];
for(byloop=0;byloop<len;byloop++)
{
ptTxBuff[byloop] = 0;
}
byTransNum = sizeof(addr)+len;
Att_SPI_Transfer_Block(byTxBuff,byRxBuff,byTransNum);
ptTxBuff = &byRxBuff[1];
for(byloop=0;byloop<len;byloop++)
{
data[byloop] = ptTxBuff[byloop];
}
return 0;
}
2.6写寄存器接口函数代码
int ATT7053_Set( UINT8 addr, UINT8 *data, WORD len )
{
UINT8 byloop=0;
UINT8 byTxBuff[4], byRxBuff[4],*ptTxBuff=0,byTransNum=0;
if(len>4)
{
return -1;
}
byTxBuff[0] = addr | Att7053_writeflag;
ptTxBuff = &byTxBuff[1];
for(byloop=0;byloop<len;byloop++)
{
ptTxBuff[byloop] = data[byloop];//需要写入寄存器的数据
}
byTransNum = sizeof(addr)+len;
Att_SPI_Transfer_Block(byTxBuff,byRxBuff,byTransNum);
return 0;
}
2.7 ATT7053初始化
对其初始化时,可以去读取芯片的固有ID,来确认通讯是否OK。
地址 名称 字节长度 内容描述
1BH ChipID 3 ChipID,默认值为7053B0
1CH DeviceID 3 DeviceID,默认值为705321
void ATT7053_Init(void)
{
UINT8 data24[3];
UINT32 buf24,buf24BAK;
memset((void *)data24,0,sizeof(data24));
delay_ms(100);
//读芯片固有参数ChipID
ATT7053_Get(ADDR_ChipID, data24,sizeof( data24 ));
ArrayConvertToData24(&buf24, data24, sizeof(data24));//将数组data[3]中的3个字节的数据转换成24位的数据,
if(buf24 != ChipID)//如果读取错误,对芯片重启
{
printf("ATT7053 Read ChipID Error,True ID:%x",ChipID);
ATT7053_Rst();//重启
}
//读芯片固有参数DeviceID
ATT7053_Get(ADDR_DeviceID, data24,sizeof( data24 ));
ArrayConvertToData24(&buf24, data24, sizeof(data24));
if(buf24 != DeviceID)//如果读取错误,对芯片重启
{
printf("ATT7053 Read DeviceID Error,True ID:%x",DeviceID);
ATT7053_Rst();//重启
}
}
如果可以读到正确的参数,说明单片机与ATT7053的通讯时没有问题的。其次就是一些其他应用了,比如说读电压电流,如何将读数转换为需要显示的电压值,这时候需要去计算一个转换系数。再比如读取缓存波形,计算谐波等!
3、总结
以上是自己使用ATT7053的一些经验,可能是一些很浅显的知识,但也是自己摸索写出来的。在网上也找过一些相应的资料,但帮助比较少,并且大都是需要收费的。在此想感谢钜泉光电的技术人员,对问题有问必答。如果需要对这块计量芯片进行深入开发,可以和厂家的技术人员深度沟通。
说明:如需转载,请注明出处!