基于STM32的ATT7022E电能计量芯片程序实现,包含硬件初始化、数据采集、校准算法及通信模块。代码基于HAL库开发,支持SPI接口通信,适用于三相电能计量场景。
一、硬件连接与配置
1. 硬件连接表
| STM32引脚 | ATT7022E引脚 | 功能说明 |
|---|---|---|
| PA4 | CS | 片选信号 |
| PA5 | SCK | SPI时钟 |
| PA6 | MISO | 主设备输入/从设备输出 |
| PA7 | MOSI | 主设备输出/从设备输入 |
| PB0 | RST | 硬件复位 |
| PB1 | INT | 中断信号 |
2. 系统时钟配置(STM32F103)
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
}
二、核心驱动代码
1. SPI通信模块
SPI_HandleTypeDef hspi1;
void MX_SPI1_Init(void)
{
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
HAL_SPI_Init(&hspi1);
}
// SPI读写函数
uint8_t SPI_WriteRead(uint8_t data)
{
HAL_StatusTypeDef status = HAL_SPI_TransmitReceive(&hspi1, &data, &data, 1, 1000);
return (status == HAL_OK) ? data : 0xFF;
}
2. ATT7022E驱动模块
#define ATT7022E_CS_PIN GPIO_PIN_4
#define ATT7022E_CS_PORT GPIOA
// 寄存器地址定义
#define REG_SYS_CTRL 0x00
#define REG_VOLTAGE_GAIN 0x0D
#define REG_CURRENT_GAIN 0x00
#define REG_ACTIVE_POWER 0x13
// 复位芯片
void ATT7022E_Reset(void)
{
HAL_GPIO_WritePin(ATT7022E_CS_PORT, ATT7022E_CS_PIN, GPIO_PIN_RESET);
HAL_Delay(10);
HAL_GPIO_WritePin(ATT7022E_CS_PORT, ATT7022E_CS_PIN, GPIO_PIN_SET);
HAL_Delay(100);
}
// 写入寄存器
HAL_StatusTypeDef ATT7022E_WriteReg(uint16_t regAddr, uint8_t *data, uint16_t size)
{
HAL_GPIO_WritePin(ATT7022E_CS_PORT, ATT7022E_CS_PIN, GPIO_PIN_RESET);
SPI_WriteRead((regAddr >> 8) & 0xFF);
SPI_WriteRead(regAddr & 0xFF);
for(uint16_t i=0; i<size; i++) {
SPI_WriteRead(data[i]);
}
HAL_GPIO_WritePin(ATT7022E_CS_PORT, ATT7022E_CS_PIN, GPIO_PIN_SET);
return HAL_OK;
}
// 读取寄存器
HAL_StatusTypeDef ATT7022E_ReadReg(uint16_t regAddr, uint8_t *data, uint16_t size)
{
HAL_GPIO_WritePin(ATT7022E_CS_PORT, ATT7022E_CS_PIN, GPIO_PIN_RESET);
SPI_WriteRead((regAddr >> 8) & 0xFF | 0x80); // 设置读模式
SPI_WriteRead(regAddr & 0xFF);
for(uint16_t i=0; i<size; i++) {
data[i] = SPI_WriteRead(0x00);
}
HAL_GPIO_WritePin(ATT7022E_CS_PORT, ATT7022E_CS_PIN, GPIO_PIN_SET);
return HAL_OK;
}
三、关键算法实现
1. 校准算法(零点校准)
void ATT7022E_Calibration(void)
{
uint8_t calData[4] = {0};
// 进入校准模式
ATT7022E_WriteReg(0x06, (uint8_t[]){0xA5, 0x5A}, 2);
HAL_Delay(100);
// 读取校准参数
ATT7022E_ReadReg(0x0600, calData, 4);
// 计算校准系数(示例)
float V_gain = (calData[0] << 8 | calData[1]) / 4096.0f;
float I_gain = (calData[2] << 8 | calData[3]) / 4096.0f;
// 更新校准参数
ATT7022E_WriteReg(0x0D, (uint8_t*)&V_gain, 4);
ATT7022E_WriteReg(0x10, (uint8_t*)&I_gain, 4);
}
2. 数据采集与转换
typedef struct {
float voltage; // 电压有效值 (V)
float current; // 电流有效值 (A)
float power; // 有功功率 (W)
} EnergyData;
EnergyData ATT7022E_GetData(void)
{
EnergyData data = {0};
uint8_t buffer[8] = {0};
// 读取电压电流数据
ATT7022E_ReadReg(0x0D, buffer, 8);
// 数据转换(32位补码格式)
int32_t V_raw = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
int32_t I_raw = (buffer[4] << 24) | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7];
// 转换为实际物理量
data.voltage = (V_raw * 0.001f) * 220.0f; // 假设额定电压220V
data.current = (I_raw * 0.0001f) * 5.0f; // 假设额定电流5A
data.power = data.voltage * data.current * 0.95f; // 功率因数0.95
return data;
}
四、完整应用示例
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_SPI1_Init();
// 硬件初始化
ATT7022E_Reset();
HAL_Delay(100);
// 校准流程
ATT7022E_Calibration();
while(1)
{
EnergyData data = ATT7022E_GetData();
// 显示数据(示例)
printf("Voltage: %.2f V\n", data.voltage);
printf("Current: %.2f A\n", data.current);
printf("Power: %.2f W\n", data.power);
HAL_Delay(1000);
}
}
五、调试与优化建议
-
通信调试
- 使用逻辑分析仪验证SPI时序(时钟频率建议≤1MHz)
- 检查片选信号是否稳定(低电平有效)
-
校准优化
- 校准前需等待芯片稳定(建议>30秒)
- 多点校准法:0%、50%、100%负载下分别校准
-
抗干扰措施
// 添加数字滤波 #define FILTER_DEPTH 5 static float voltageBuffer[FILTER_DEPTH] = {0}; float MovingAverageFilter(float newValue) { for(int i=0; i<FILTER_DEPTH-1; i++) { voltageBuffer[i] = voltageBuffer[i+1]; } voltageBuffer[FILTER_DEPTH-1] = newValue; return (voltageBuffer[0] + voltageBuffer[1] + voltageBuffer[2] + voltageBuffer[3] + voltageBuffer[4]) / FILTER_DEPTH; }
参考代码 基于STM32的电量计量芯片ATT7022E的程序 www.youwenfan.com/contentcnr/56439.html
六、扩展功能实现
1. RS485通信模块
void RS485_SendData(uint8_t *data, uint16_t len)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); // 使能发送
HAL_UART_Transmit(&huart1, data, len, 1000);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); // 切换回接收
}
2. Modbus协议封装
typedef struct {
uint8_t addr;
uint8_t func;
uint16_t regAddr;
uint16_t data;
} ModbusFrame;
void Modbus_BuildFrame(ModbusFrame *frame, uint8_t *buffer)
{
buffer[0] = frame->addr;
buffer[1] = frame->func;
buffer[2] = (frame->regAddr >> 8) & 0xFF;
buffer[3] = frame->regAddr & 0xFF;
buffer[4] = (frame->data >> 8) & 0xFF;
buffer[5] = frame->data & 0xFF;
buffer[6] = CalculateCRC(buffer, 7);
}
七、参考资料
- ATT7022E数据手册(重点章节:寄存器映射、校准流程)
- STM32F103参考手册(SPI章节)
- 《三相电能计量技术及应用》(王兆安著)