一、硬件电路

这里以C相电压采集为例,来快速了解RN8302B的使用

\\I_{R40}=220V/220k=1mA \\U_{R43}=1mA*250\Omega =250mV \\U_{R46}=U_{R43}=250mV \\(U_{R46}-U_{R52})/20k=(U_{R52}-U_{R57})/10k \\ \because U_{R52}=0 \\ \therefore V_{CP}=U_{R57}=-U_{R46}/2=-125mV

 

 二、 配置工作

1、准备好printf工程,参考之前的教程

STM32CubeIDE实现printf重定向输出到串口_飞由于度的博客-CSDN博客STM32CubeIDE之printf重定向及串口https://blog.csdn.net/qq_35629563/article/details/126665838

2、配置RN8302B通信引脚

①SPI引脚

具体原因参考《RN8302B 用户手册》:

1)1.1 芯片特性

2) 5.4 SPI 写时序

 CPOL表示SCK空闲时间的状态,从时序图里可以看出CPOL=LOW

CPHA表示在第一边沿还是第二边沿进行数据交换,从时序图里可以看出CPOL=2 Edge

 ②控制引脚

将PB12配置为GPIO_Output模式,PC6配置为GPIO_Input模式

 ③呼吸灯

这里我是用的是PC1作为呼吸灯,其实不论使用哪个引脚控制的呼吸灯,只需将其重命名为LED1即可

3、引脚重命名

然后右击引脚分别重命名(注意顺序:先左击配置模式,再右击重命名)

最终结果

生成代码

三、代码编写

1、rn8302b.h

#ifndef _SPI_H_
#define _SPI_H_

#include "main.h"
#include "stdio.h"

//---------------------- RN8302计量寄存器地址定义---------------------------------------------------//
#define UC_CMD      0x0009//4//C相电压有效值
#define UC_BYTE     4

#define SYSSR_CMD   0x018A//系统状态寄存器
#define SYSSR_BYTE  2

#define DeviceID_CMD   0x018f//RN8302B Device ID
#define DeviceID_BYTE  3

#define SPI_CS_HIGH() 	HAL_GPIO_WritePin( RN_NSS_GPIO_Port , RN_NSS_Pin, GPIO_PIN_SET )
#define SPI_CS_LOW() 	HAL_GPIO_WritePin( RN_NSS_GPIO_Port , RN_NSS_Pin, GPIO_PIN_RESET )


void ReadAmmeterData(void);

#endif

2、rn8302b.c

/****************SPI 采用端口模拟**********************************/
#include "rn8302b.h"
#include "spi.h"


/*****************SPI 写单字节**************************/
void Write_SPI_OneByte(uint8_t TxData)
{
	uint8_t Rxdata;
	HAL_SPI_TransmitReceive(&hspi2,&TxData,&Rxdata,1, 1000);
	return ;
}
/*****************SPI 读单字节**************************/
uint8_t Read_SPI_OneByte(void)
{
	uint8_t Rxdata;
	uint8_t TxData=0;
	HAL_SPI_TransmitReceive(&hspi2,&TxData,&Rxdata,1, 1000);
	return Rxdata;
}
/************************* READ_RN8302*************************************************/
uint32_t READ_SPI(uint16_t Address,uint8_t Data_len)
{
	uint8_t i, DTemp,CheckSumR;
	uint32_t drData;

	SPI_CS_LOW();    // 开启SPI传输

	DTemp = (uint8_t)(Address&0x00FF);//ADDR[7:0]
	CheckSumR = DTemp;
	Write_SPI_OneByte(DTemp);
	DTemp = (((uint8_t)(Address >> 4)) & 0xf0) ;//CMD=R/W+AD[10:8]+BL[1:0]+2’h0(MSB+LSB)
	CheckSumR += DTemp;
	Write_SPI_OneByte(DTemp);

	HAL_Delay(5);
	drData = 0x00000000;//Read 24bit

	for(i=0;i<Data_len;i++)//先发高字节,后发低字节
	{
		DTemp = Read_SPI_OneByte();
		drData = drData<<8;
		drData += DTemp;
		CheckSumR += DTemp;
	}

	CheckSumR = ~CheckSumR;//校验和算法: ADDR+CMD+DATA 单字节求和取反。

	if (CheckSumR != Read_SPI_OneByte())//比较校验和
	{
		drData = 0xFFFFFFFF;
	}

	SPI_CS_HIGH();	  //关闭SPI传输
	HAL_Delay(2);
	return drData;
}
/**************************Write RN8302******************************/
void Write_SPI(uint16_t Address, uint32_t dwData,uint8_t Date_len)
{
	uint8_t i,CheckSumR, DTemp;

	SPI_CS_LOW();	 //开启SPI传输

	DTemp = (uint8_t)(Address&0x00FF);//
	CheckSumR = DTemp;
	Write_SPI_OneByte(DTemp);//写地址
	DTemp = (((uint8_t)(Address >> 4)) & 0xf0)+0x80 ;
	CheckSumR += DTemp;
	Write_SPI_OneByte(DTemp);//写命令


	for (i =0 ;i < Date_len;i++)//先发高字节,后发低字节
	{
		DTemp = (uint8_t)(dwData>>(Date_len-1-i)*8);
		Write_SPI_OneByte(DTemp);//写命令
		CheckSumR += DTemp;
	}

	CheckSumR = ~CheckSumR;//校验和算法: ADDR+CMD+DATA 单字节求和取反。

	Write_SPI_OneByte(CheckSumR);//写命令

	SPI_CS_HIGH();	    //结束传输
	HAL_Delay(2);
}

void ReadAmmeterData(void)
{
	uint32_t temp = 0;

	temp = READ_SPI(DeviceID_CMD,DeviceID_BYTE);//芯片ID//supposed to be 0x00830200(hex)
	printf("Device_ID=%x(hex)\r\n",(int)temp);
	if(temp != 0x00830200) //读ID
	{
		printf("===================== \r\n");
		printf("Device_ID!=0x00830200 \r\n");
		printf("===================== \r\n");
		return;
	}

	temp = READ_SPI(SYSSR_CMD,SYSSR_BYTE);//系统状态
	printf("SYSSR=%x(hex)\r\n",(int)temp);
	HAL_Delay(1000);
	
	temp = READ_SPI(UC_CMD,UC_BYTE);//读取电压有效值
	printf(" UC 寄存器有效值=%8X\r\n",(int)temp);
	printf(" UC 引脚处有效值=%8.2f\r\n",(float)(temp/167772));
	printf(" UC 端口处有效值=%8.2f\r\n",(float)(temp/167772*1.76));
}

 167772的来源

RN8302B 用户手册》的3.2.2 有效值寄存器 提到

1-4 类有效值是四字节寄存器,为 28 位( bit0-bit27 )有符号数,采用补码格式, bit27 为符号位, bit28-bit31 bit27 相同总为零。这四类有效值参数更新的周期为 250ms

 4.2.2 标准电压电流和有功功率值计算  提到

U理论=INT[(Vu/800)*2^27]

其中U理论寄存器里的值(2^27/800=167772),Vu连接到RN8302B引脚上的电压值

1.76的来源

见本文《一、硬件电路》(1.76=220V/125mV=1.76V/mV)

假如寄存器里的值是0x14E 2C74:

U理论=寄存器里的值0x14E 2C74=21900404

Vu=21900404*800/2^27=17520323200/2^27≈130.53mV

130.53mV*1.76V/mV=229.7328V≈229.7V

3、main.c

USER CODE BEGIN Includes下添加以下代码

#include <stdio.h>
#include <string.h>

#include "rn8302b.h"

uint8_t t=0;

USER CODE BEGIN 3下添加以下代码

	  ReadAmmeterData();
	  HAL_Delay(3000);
	  HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
	  printf("%d\r\n",++t);

四、实验结果

全部代码与RN8302B的手册

https://download.csdn.net/download/qq_35629563/86512618icon-default.png?t=N7T8https://download.csdn.net/download/qq_35629563/86512618

Logo

智屏生态联盟致力于大屏生态发展,利用大屏快应用技术降低开发者开发、发布大屏应用门槛

更多推荐