本帖最后由 gugogol 于 2018-3-28 18:41 编辑
过年前偶尔发现新唐的N76E003很火,我也买了个测试板回来试了一下,发现果然不错,现分享一下我用它来做交流电有效值的测量的测试程序。由于我是第一次使用C写代码(以前一直用汇编),大家不要见笑!代码我是直接在新唐的ADC例程上改过来的,测试正弦波的有效值用的是均方根测量法 ,采用半波测量,5V的交流信号通过二个10K的电阻分压后接入ADC端口。在测试时发现这芯片有一个美中不足的地方,ADC的参考源固定为电源电压,不像AVR单片机那样可选VDD/片内1.1V参考源/外部Vref参考源,这样使单片机的ADC在小信号测量的应用上欠缺精度调整的灵活性,当然对精度要求不高的,12位也足够了。
// File Function: N76E003 ADC demo code
//*********************************************************************************************************
**
#include "N76E003.h"
#include "SFR_Macro.h"
#include "Function_define.h"
#include "Common.h"
#include "Delay.h"
#include "math.h"
uint16_t ADCData;
uint16_t xdata ADCDatas[370];
uint8_t VOLT[6];
uint8_t FREQ[5];
uint16_t VOL ;
uint16_t i ;
uint8_t FREQData=206;
uint32_t SINData=0;
double VData=0;
uint32_t ADCDatat;
/*******************************************************************************
**void ADC_Data_Read(unsigned int *AD_Value)
**完成一次ADC转换
**入口参数:unsigned int *AD_Value
*AD_Value ->读取ADC采样数据指针
**输出:无
*******************************************************************************/
void ADC_Data_Read(uint16_t *AD_Value)
{
clr_ADCF;
set_ADCS; //
ADC start trig signal
while(ADCF == 0);
*AD_Value = ADC1_GetConversionValue(); //读取转换数据
}
/*******************************************************************************
**函数名称:void Uart_SendString(u8 *data , u8 strlen)
**功能:向串口发送多个字符
**输入参数:u8 *data , u8 strlen
**输出:无
*******************************************************************************/
void Uart_SendString(uint8_t *datas , uint8_t strlen)
{
unsigned char datalen;
InitialUART0_Timer1(115200);
for(datalen = 0 ; datalen < strlen ; datalen++)
{
Send_Data_To_UART0(datas[datalen]);
}
}
/**********************************
***功能:延时
************************************/
void Delay_short()
{
long int i;
for (i = 0; i < 5; i++) ; //5:30uS
}
/*******************************************************************************
**函数名称:void FREQ_Test(unsigned int *FREQ_T)
**功能:测量信号频率
**入口参数:unsigned int *FREQ_T
*FREQ_T ->读取频率数据指针
**输出:无
*******************************************************************************/
void FREQ_TEST(uint8_t *FREQ_T)
{
ADC_Data_Read(&ADCData);
Delay_short();
while(ADCData<20) //等待高电平
{
ADC_Data_Read(&ADCData);
Delay_short();
}
while(ADCData>1) //等待低电平
{
ADC_Data_Read(&ADCData);
Delay_short();
}
while(ADCData<20) //等待高电平
{
ADC_Data_Read(&ADCData);
Delay_short();
}
i=0;
while(ADCData > 20) //对高电平转换次数计数,用作判定频率
{
ADC_Data_Read(&ADCData); //ADC转换一次用时48uS
Delay_short();
i++;
}
if (i>191)
{ i=206;} //如果计数大于185则认为是50Hz,采样次数为206
else
{i=172;} //如果计数小于185则认为是60Hz,采样次数为172
*FREQ_T = i ;
}
/*******************************************************************************
**函数名称:void RMS_Test(double *RMS_T)
**功能:测量信号的均方根值
**入口参数:unsigned uint32_t *RMS_T
*RMS_T ->读取采样有效值指针
**输出:无
*******************************************************************************/
void RMS_Test( double *RMS_T)
{
//等待信号波形开端
while(ADCData<20) //等待高电平
{
ADC_Data_Read(&ADCData);
Delay_short();
}
while(ADCData>10) //等待低电平
{
ADC_Data_Read(&ADCData);
Delay_short();
}
while(ADCData<20) //等待高电平
{
ADC_Data_Read(&ADCData);
Delay_short();
}
//波形进入高电平开端,开始半波采样
i=0;
ADCDatas = ADCData ;
i++;
while(i < FREQData )
{
ADC_Data_Read(&ADCData); //转换一次ADC用时13.5uS
ADCDatas = ADCData ;
Delay_short(); //延时30US
i++ ;
}
i=0;
SINData=0;
while(i<FREQData)
{
//计算均方根值(有效值) **********************
ADCDatat = ADCDatas;
SINData += ADCDatat * ADCDatat ; //平方和
i++;
}
SINData = SINData / FREQData ; //平方和平均
*RMS_T = sqrt ( (double)(SINData) ); //开方
// VData = VData / 21.33 ; //比例调整
}
//**********************************************
/******************************************************************************
The main C function. Program execution starts
here after stack initialization.
******************************************************************************/
void main (void)
{
InitialUART0_Timer1(115200);
Enable_ADC_AIN0; // Enable AIN0 P1.7 as ADC
input, Find in "Function_define.h" - "ADC INIT"
while(1)
{
FREQ_TEST(&FREQData); //测试信号频率
//*************************************************************** //**********************************************
/******************************************************************************
The main C function. Program execution starts
here after stack initialization.
******************************************************************************/
void main (void)
{
InitialUART0_Timer1(115200);
Enable_ADC_AIN0; // Enable AIN0 P1.7 as ADC input, Find in "Function_define.h" - "ADC INIT"
P14_PushPull_Mode ; //设置模拟串口1的发送端口
P15_PushPull_Mode ; //设置模拟串口2的发送端口
while(1)
{
FREQ_TEST(&FREQData); //测试信号频率
RMS_Test( & VData ); //测试信号有效值
VData = VData / 21.33 ; //比例调整
VOL = (uint32_t)(VData); //数据类型强制转换
//**********************************************
FREQ[2] = FREQData % 10 + '0'; //ASCII转换
FREQ[1] = FREQData % 100 / 10 + '0';
FREQ[0] = FREQData / 100 % 10 + '0';
FREQ[3] = 0x30;
FREQ[4] = 0x30;
Uart_SendString(FREQ , 5);
Uart_SendString(" " , 1); //
VOLT[3] = VOL % 10 + '0'; //ASCII
VOLT[2] = VOL % 100 / 10 + '0';
VOLT[1] = VOL / 100 % 10 + '0';
VOLT[0] = VOL / 1000 + '0';
VOLT[4] = 0x0d; //换行
VOLT[5] = 0x0a;
Uart_SendString(VOLT , 6);
Timer0_Delay1ms(1000) ;
}
}
|