标题:
MSP430G2553测信号频率在LCD1602显示源代码
[打印本页]
作者:
CrankRong
时间:
2018-4-7 20:54
标题:
MSP430G2553测信号频率在LCD1602显示源代码
MSP430G2553测信号频率在LCD1602显示代码,自制,精度较好。
单片机源程序如下:
#include <msp430.h>
#include "stdint.h"
#include "LCD1602.h"
#include <math.h>
volatile double voltage = 0;
volatile double frequence = 0;
volatile uint8_t flag = 0;
volatile double virtual_fact_plus = 0.0;
volatile double virtual_fact = 0.0;
volatile uint16_t TAcnt = 0;
volatile uint16_t cnt = 0;
volatile uint16_t adcvalue = 0;
volatile uint16_t adcvalueMax = 0;
volatile uint16_t adcvalueMin = 0;
volatile uint32_t cap = 0;
volatile double virtual_ideal_sine = 0.0;
volatile double virtual_ideal_tri = 0.0;
volatile uint16_t num = 0;
volatile uint32_t timestamp = 0;
volatile uint32_t time = 0;
void PrintVoltage(double voltage);
/*函数声明*/
void InitSystemClock(void);
void InitADC(void);
void InitTimer_A1(void);
void GetVpp(void);
void GetFreq(void);
void GetVirtual(void);
void tell_Rec(void);
uint32_t GetCurrentTime(void);
void Enable_P1_3(void);
void InitUART(void);
void UARTSendString(uint8_t *pbuff,uint8_t num);
void PrintVoltage(double voltage);
void PrintFreq(double freq);
/*
* @fn: void InitSystemClock(void)
* @brief: 初始化系统时钟
* @para: none
* @return: none
* @comment:初始化系统时钟
*/
void InitSystemClock(void)
{
/*配置DCO为1MHz*/
DCOCTL = CALDCO_16MHZ;
BCSCTL1 = CALBC1_16MHZ;
/*配置SMCLK的时钟源为DCO*/
BCSCTL2 &= ~SELS;
/*SMCLK的分频系数置为1*/
BCSCTL2 &= ~(DIVS0 | DIVS1);
}
/*
* @fn: void InitADC(void)
* @brief: 初始化ADC
* @para: none
* @return: none
* @comment:初始化ADC
*/
void InitADC(void)
{
/*设置ADC时钟MCLK*/
ADC10CTL1 |= ADC10SSEL_2;
/*ADC 2分频*/
ADC10CTL1 |= ADC10DIV_0;
/*设置ADC基准源*/
ADC10CTL0 |= SREF_1;
/*设置ADC采样保持时间64CLK*/
ADC10CTL0 |= ADC10SHT_2;
/*设置ADC采样率200k*/
ADC10CTL0 &= ~ADC10SR;
/*ADC基准选择2.5V*/
ADC10CTL0 |= REF2_5V;
/*开启基准*/
ADC10CTL0 |= REFON;
/*选择ADC输入通道A0*/
ADC10CTL1 |= INCH_0;
/*允许A0模拟输入*/
ADC10AE0 |= BIT0;
/*开启ADC*/
ADC10CTL0 |= ADC10ON;
}
/*
* @fn: void InitTimer_A1(void)
* @brief 初始化Timer_A1进行计数
* @para: none
* @return: none
* @comment:初始化Timer_A1
*/
void InitTimer_A1(void)
{
/*设置时钟源为SMCLK*/
TA1CTL |= TASSEL_2;
/*设置工作模式为Up Mode*/
TA1CTL |= MC_1;
/*设置定时间隔*/
TA1CCR0 = 49999;// 50ms 1MHz 1/1MHz 1ns 50ms / 1ns = 50000 50000 - 1 = 49999
/*开启TAIFG中断*/
TA1CTL |= TAIE;
}
/*计算峰峰值*/
void GetVpp(void)
{
for(cnt = 0; cnt < 10000; cnt ++)
{
/*开始转换*/
ADC10CTL0 |= ADC10SC|ENC;
/*等待转换完成*/
while(ADC10CTL1&ADC10BUSY);
if(adcvalueMax < ADC10MEM)
adcvalueMax = ADC10MEM;
if(adcvalueMin > ADC10MEM)
adcvalueMin = ADC10MEM;
}
voltage = (adcvalueMax - adcvalueMin) * 2.5 / 1023;
}
/*计算波形频率*/
void GetFreq(void)
{
/*开始转换*/
ADC10CTL0 |= ADC10SC|ENC;
/*等待转换完成*/
while(ADC10CTL1&ADC10BUSY);
while(fabs((double)(adcvalueMax - ADC10MEM)) > 20)
{
/*开始转换*/
ADC10CTL0 |= ADC10SC|ENC;
/*等待转换完成*/
while(ADC10CTL1&ADC10BUSY);
}
timestamp = GetCurrentTime();
while(num < 1000)
{
while(fabs((double)(ADC10MEM - adcvalueMin)) > 100)
{
/*开始转换*/
ADC10CTL0 |= ADC10SC|ENC;
/*等待转换完成*/
while(ADC10CTL1&ADC10BUSY);
}
while(fabs((double)(adcvalueMax - ADC10MEM)) > 100)
{
/*开始转换*/
ADC10CTL0 |= ADC10SC|ENC;
/*等待转换完成*/
while(ADC10CTL1&ADC10BUSY);
}
num ++;
}
num = 0;
time = GetCurrentTime() - timestamp;
/*计算信号频率*/
frequence = 16000000000.0 / (float)(GetCurrentTime() - timestamp);
}
/*计算有效值*/
void GetVirtual(void)
{
virtual_fact_plus = 0.0;
for(cnt = 0; cnt < 10000; cnt ++)
{
/*开始转换*/
ADC10CTL0 |= ADC10SC|ENC;
/*等待转换完成*/
while(ADC10CTL1&ADC10BUSY);
virtual_fact_plus += pow((ADC10MEM * 2.5 / 1023), 2);
}
virtual_fact = sqrt(virtual_fact_plus / 10000);
}
/*判断方波*/
void tell_Rec(void)
{
for(cnt = 0; cnt < 10000; cnt ++)
{
/*开始转换*/
ADC10CTL0 |= ADC10SC|ENC;
/*等待转换完成*/
while(ADC10CTL1&ADC10BUSY);
if(fabs((double)(ADC10MEM - adcvalueMin)) < 100 || fabs((double)(adcvalueMax - ADC10MEM)) < 100)
num ++;
__delay_cycles(100);
}
if(num > 9800)
flag = 2; //方波
else if(2 == flag) flag = 0;
num = 0;
}
/*
* @fn: uint32_t GetCurrentTime(void)
* @brief: 得到当前计时器计数大小
* @para: none
* @return: currenttime = cnt * 50000 + TA1CCR2
* @comment:得到当前计时器计数大小
*/
uint32_t GetCurrentTime(void)
{
return((uint32_t)(TAcnt * 50000 + TA1R));
}
/*
* @fn: void Enable_P1_3(void)
* @brief: 使能P1.3口中断
* @para: none
* @return: none
* @comment:使能P1.3口中断
*/
void Enable_P1_3(void)
{
P1DIR &= ~BIT3;
/*使能P1.3口的上拉电阻*/
P1REN |= BIT3;
P1OUT |= BIT3;
/*打开P1.3口中断*/
P1IE |= BIT3;
/*设定为下降沿触发*/
P1IES |= BIT3;
/*清除中断标志位*/
P1IFG &= ~BIT3;
}
void InitUART(void)
{
/*复位USCI_Ax*/
UCA0CTL1 |= UCSWRST;
/*选择USCI_Ax为UART模式*/
UCA0CTL0 &= ~UCSYNC;
/*配置UART时钟源为SMCLK*/
UCA0CTL1 |= UCSSEL1;
/*配置波特率为9600@1MHz*/
UCA0BR0 = 0x68;
UCA0BR1 = 0x00;
UCA0MCTL = 0x31;
/*使能端口复用*/
P1SEL |= BIT1 + BIT2;
P1SEL2 |= BIT1 + BIT2;
/*清除复位位,使能UART*/
UCA0CTL1 &= ~UCSWRST;
}
/*
* @fn: void UARTSendString(uint8_t *pbuff,uint8_t num)
* @brief: 通过串口发送字符串
* @para: pbuff:指向要发送字符串的指针
* num:要发送的字符个数
* @return: none
* @comment:通过串口发送字符串
*/
void UARTSendString(uint8_t *pbuff,uint8_t num)
{
uint8_t cnt = 0;
for(cnt = 0;cnt < num;cnt ++)
{
while(UCA0STAT & UCBUSY);
UCA0TXBUF = *(pbuff + cnt);
}
}
/*
* @fn: void PrintFloat(float num)
* @brief: 通过串口发送电压,单位为V,保留两位小数
* @para: voltage:电压
* @return: none
* @comment:通过串口发送浮点数,可发送1位整数位+3位小数位
*/
void PrintVoltage(double voltage)
{
uint8_t charbuff[] = {0, '.', 0, 0, 0};
uint16_t temp = (uint16_t)(voltage * 1000);
charbuff[0] = (uint8_t)(temp / 1000) + '0';
charbuff[2] = (uint8_t)((temp % 1000) / 100) + '0';
charbuff[3] = (uint8_t)((temp % 100) / 10)+ '0';
charbuff[4] = (uint8_t)(temp % 10) + '0';
UARTSendString(charbuff, 5);
UARTSendString("V\n", 2);
}
/*
* @fn: void PrintFreq(float freq)
* @brief: 通过串口发送频率,单位为Hz,保留两位小数
* @para: freq:频率
* @return: none
* @comment:通过串口发送频率
*/
void PrintFreq(double freq)
{
uint32_t temp = (uint32_t)(freq);
uint8_t charbuff[] = {0, 0, 0, 0, 0};//最大999999.99Hz
int8_t cnt = 0;
for(cnt = 4; cnt >= 0; cnt --)
{
charbuff[cnt] = (uint8_t)(temp % 10) + '0';
temp /= 10;
}
UARTSendString("frequence = ", 12);
UARTSendString(charbuff, 2);
UARTSendString(".", 1);
UARTSendString(charbuff + 2, 3);
UARTSendString("kHz\n", 4);
}
/**
* main.c
*/
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
InitSystemClock();
InitADC();
InitTimer_A1(); //计数
InitUART();
delay_nms(10);
Print_Name();
Enable_P1_3();
__bis_SR_register(GIE);/*打开全局中断*/
while(1)
{
num = 0;
GetVpp();
if(fabs((double)(adcvalueMax - adcvalueMin)) < 50)
{
flag = 1; //直流
frequence = 0.0;
}
else if(1 == flag) flag = 0;
if(1 != flag)
{
GetFreq();
if(frequence < 0.1)
frequence = 150.0;
else frequence -= frequence * 135.0 / 10000.0;
TAcnt = 0;
}
GetVirtual();
tell_Rec();
if(2 != flag && 1 != flag)
{
virtual_ideal_sine = sqrt(pow((adcvalueMax + adcvalueMin) * 2.5 / 2046, 2) + (pow(voltage / 2, 2) / 2));
virtual_ideal_tri = sqrt((pow(adcvalueMax * 2.5 / 1023, 2) + pow(adcvalueMin * 2.5 / 1023, 2) + adcvalueMax * adcvalueMin * 6.25 / pow(1023, 2)) / 3);
if(fabs(virtual_fact - virtual_ideal_sine) < 0.02)
flag = 3; //正弦波
else if(fabs(virtual_fact - virtual_ideal_tri) < 0.02)
flag = 4;
else flag = 0;
}
/*switch(flag)
{
case 0:UARTSendString("unknown type\n", 13); break;
case 1:UARTSendString("Direct\n", 7); break;
case 2:UARTSendString("Rectangle\n", 10); break;
case 3:UARTSendString("Sine\n", 5); break;
case 4:UARTSendString("Triangle\n", 9); break;
default: break;
}
UARTSendString("Vpp = ", 6);
PrintVoltage(voltage);
PrintFreq(frequence);
PrintVoltage(virtual_fact);
delay_nms(1000);
*/
}
return 0;
}
#pragma vector = TIMER1_A1_VECTOR
__interrupt void Time_Tick(void)
{
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
Wave-Detect.rar
(92.52 KB, 下载次数: 71)
2018-4-7 20:53 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
ljt16
时间:
2018-4-20 02:57
这个把串口程序也加进去为什么build 工程时为什么会报错呢
作者:
ljt16
时间:
2018-4-20 03:57
这个是从msp430g2553p1.0输入吗,为什么串口发送数据显示不出来
作者:
李轩昂
时间:
2018-7-20 20:27
ljt16 发表于 2018-4-20 03:57
这个是从msp430g2553p1.0输入吗,为什么串口发送数据显示不出来
现在解决了吗
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1