msp430g2553测频率以及测峰值.docx
《msp430g2553测频率以及测峰值.docx》由会员分享,可在线阅读,更多相关《msp430g2553测频率以及测峰值.docx(15页珍藏版)》请在冰豆网上搜索。
msp430g2553测频率以及测峰值
电子设计综合实验项目报告
项目名称:
MCU交流电压参数测量
小组成员:
林伊、武正浩
学号:
20111112、20111201
项目要求
题目:
交流电压参数的测量
要求:
用给定的MCU:
msp430g2553,制作交流电压参数测试设备
图表1
基本要求:
一、用给定运放LM324制作一放大器
a)增益大于:
20dB
b)带宽大于:
100KHz
二、用指定MCU和已制作的放大器制作频率计
a)测量范围:
10Hz~100KHz
b)显示:
3位以上
发挥部分:
一、用A/D测量已给电压的幅度,信号由已制作的放大器输入
a)测量范围:
输入信号越小越好
实现思路
放大:
首先分析题目要求,要实现放大20dB,频率1~100KHz的信号,通过公式20lg(Ad)得出Ad=10,即放大10倍
必须使用运放lm324实现,则需要知道该芯片的器件参数,即增益带宽积。
通过数据手册得知其增益带宽积为6.4MHz,除去放大倍数得知能够实现该信号的放大,通过设计放大电路并焊接即可,放大电路为反向比例放大电路,见Figure1
Figure1
频率:
实现频率的测量,这一块需使用到MCU,测量频率的方法有很多种,通过捕捉上升沿下降沿产生中断,也可以不产生中断,还可通过时钟计数。
其中通过捕捉上升沿下降沿的思路又分两种,1、检测上升沿后再检测下一个上升沿(检测下降沿后再检测下一个下降沿)2、检测上升沿后再检测下降沿(检测下降沿后再检测上升沿)。
这些思路对应不同的采集方法又可以细分,其中方案1对于测量高频信号有着较好的效果,方案2对于测低频的信号较好,前提是占空比为50%,若不为则变为测脉宽。
这次的题目我采用的是用时钟计数的方式,msp430g2553中含有2个时钟,timer0和timer1,每个时钟都有如下功能,选择时钟来源:
1、外部时钟(即外部输入的方波信号)2、ACLK3、smclk等。
其中ACLK为外部所焊晶振,频率为32768Hz。
由上述条件我使用timer0和timer1同时工作来进行频率的测量,首先外部晶振属于手表晶振,极易产生1s中断,我首先用timer1产生1s中断,再用timer0选择使用外部时钟源计数,也就是需要被我们计数的信号输入,这样每一次上升沿,timer0计数器就会加一。
这样每秒中断读取timer0中寄存器的值就可以得出精确度极高的频率,甚至都不需要换算。
此种方案简便易于实现,故选用。
流程图:
Figure2
方案选择完毕,考虑如何把正弦信号转换成方波信号输入MCU,此部分在考虑信号发生器只输出正电的时候,即正弦信号在0电位之上,我们可以完全不用设计任何外部电路,因为MCU内部有施密特触发器,可以将正弦输入变成方波,但是如果有负电压输入则会损坏MCU。
实际中由于LM324我们只允许单电源供电,且放大电路为反向比例放大电路,所以只放大了输入信号的负半周,并且将其搬到正半轴,所以输入到单片机的是只有正的电压,如图:
Figure3
所以不需要外部焊接电路实现波形转换,但是由于本课程是为北京电设做准备,本着此原则我组成员决定还是设计并焊接一个外部电路来实现波形转换。
波形转换有两种方法:
1、使用过零比较器2、使用施密特触发器。
由于本题目对输入信号的频率有要求,过零比较器涉及到运放,所以在频率上有限制,为保证频率不影响实现,我们选用数字的电路即施密特触发器,数字电路一般频率可以达到几十兆,所以肯定能够符合要求,见下图:
Figure4
A/D:
本题发挥部分要求采集正弦信号的峰值,所以涉及A/D转换部分,由于输入信号频率在10Hz~100KHz,由于采样定理,采样频率必须为被采样信号的两倍,虽然实际中最好为十倍,我们最后还是采用了两倍。
Msp430g2553此款芯片A/D采集过程若要稳定起码需要30个时钟,我的A/D模块选用时钟源smclk,其频率为8MHz,则8MHz除去30约为267KHz,其大于100KHz的两倍,基本满足要求,在之前采集频率的过程中我们有产生一个1s中断,A/D平常每采集一次便把采集的值与最大值比较,把最大值留下,1s选取一次最大值显示,并把之前最大值清除。
显示:
显示我们采用LCD1602,采用四条数据线,三条控制线,在保证MCU引脚够用的前提下进行显示。
代码
主程序:
#include
#include"LCD1602_Driver.h"
#include
unsignedintFRE=0;
unsignedcharflag1=0;
unsignedcharflag2=0;
unsignedintadc_sample=0;
unsignedintadc_max=0;
unsignedinttemp=0;
ucharLCDBuf1[6];
//ucharLCDBuf2[5];
ucharLCDBuf2[]={"HZ"};
ucharLCDBuf3[]={"MV"};
voidmain()
{
WDTCTL=WDTPW+WDTHOLD;
DCOCTL|=(DCO0+DCO1);
DCOCTL|=(MOD4+MOD3+MOD2+MOD1+MOD0);//微调DCOCLK
BCSCTL1|=(RSEL0+RSEL2+RSEL3);//14.8MSMCLK
IO_Init();
LCD_Init();
//测频初始
TA0CTL|=TASSEL_0+MC_1;
TA0CCR0=0xffff;
TA1CTL|=TASSEL_1+MC_1+TAIE;
TA1CCR0=32767;
TA1CCTL0|=CCIE;
P1DIR&=~BIT0;
P1SEL|=BIT0;
__bis_SR_register(GIE);
while
(1)
{
if(0==flag1)
{
;
}
else
{
flag1=0;
TA0CTL|=TACLR;
TA0CTL=TASSEL_0+MC_1;
TA1CTL=TASSEL_1+MC_1+TAIE;
}
while(0==flag1);
flag1=0;
//显示频率
for(inti=0;i<5;i++)
{
temp=FRE/(10000/(unsignedint)(pow(10,i)));
LCDBuf1[i]=temp+'0';
FRE=FRE%(10000/(unsignedint)(pow(10,i)));
}
LCDBuf1[5]=0;
LCD_Disp_string(0,0,LCDBuf1);
LCD_Disp_string(5,0,LCDBuf2);
//测幅初始
flag2=1;
TA1CTL=TASSEL_1+MC_1+TAIE;
TA1CCR0=32767;//打开时钟
//ADC10CTL0=SREF_0+ADC10SHT_2+MSC+ADC10ON+ADC10IE;
//ADC10CTL1=INCH_1+ADC10SSEL_3+CONSEQ_2;
//ADC10AE0=0x02;
//ADC10DTC0=ADC10B1;
//ADC10DTC1=0xC8;
//ADC10CTL0&=~ENC;//先关闭adc,待到BUSY位清零,每次都必须等待
//while(ADC10CTL1&BUSY);//WaitifADC10coreisactive
//ADC10SA=(unsignedint)adc_sample;//Databufferstart
//ADC10CTL0|=ENC+ADC10SC;
ADC10CTL0=SREF_0+ADC10SHT_2+MSC+ADC10ON;
ADC10CTL1=INCH_1+ADC10SSEL_3+CONSEQ_0;
ADC10AE0=0x02;
ADC10CTL0|=ADC10ON;
do{
ADC10CTL0|=ENC+ADC10SC;
while((ADC10CTL0&ADC10IFG)==0);
adc_sample=ADC10MEM;
if(adc_max{
adc_max=adc_sample;
}
}while(0==flag1);
adc_max=adc_max*(3300/1023);
//while(0==flag1);
flag2=0;
/*
//筛选
for(inti=0;i<200;i++)
{
if(adc_sample[i]>adc_max)
{
adc_max=adc_sample[i];
}
}
*/
//显示幅值
for(inti=0;i<5;i++)
{
temp=adc_max/(10000/(unsignedint)(pow(10,i)));
LCDBuf1[i]=temp+'0';
adc_max=adc_max%(10000/(unsignedint)(pow(10,i)));
}
LCDBuf1[5]=0;
LCD_Disp_string(0,1,LCDBuf1);
LCD_Disp_string(5,1,LCDBuf3);
adc_max=0;
}
}
//TimerA1interruptserviceroutine
#pragmavector=TIMER1_A0_VECTOR
__interruptvoidTimer1_A(void)
{
if(0==flag2)
{
TA0CTL=0;
TA1CTL=0;
TA1CTL|=TACLR;
FRE=TA0R;
flag1=1;
TA0CTL=TASSEL_0+MC_0;
TA1CTL=TASSEL_1+MC_0;
//TA0CTL|=TACLR;
//TA0CTL=TASSEL_0+MC_1;
//TA1CTL=TASSEL_1+MC_1+TAIE;
//测了一次还没开
}
else
{
TA1CTL=TASSEL_1+MC_0;
flag1=1;
}
}
//ADC10interruptserviceroutine
#pragmavector=ADC10_VECTOR
__interruptvoidADC10_ISR(void)
{
flag1=1;
ADC10CTL0&=~ENC;
}
lcd头文件
//#include"msp430g2553.h"
#defineSET_LCD_1602_EP2OUT|=0x04//P2.2
#defineCLR_LCD_1602_EP2OUT&=~0x04
#defineSET_LCD_1602_RSP2OUT|=0x01//P2.0
#defineCLR_LCD_1602_RSP2OUT&=~0x01
#defineSET_LCD_1602_RWP2OUT|=0x02//P2.1
#defineCLR_LCD_1602_RWP2OUT&=~0x02
#defineLCD_IO_OUTP1OUT
#defineLCD_IO_DIRP1DIR
#defineLCD_IO_INP1IN
#defineLCD_IO_SELP1SEL
#defineucharunsignedchar
#defineuintunsignedint
voidIO_Init(void);
voidLCD_Init(void);
voidLCD_Check_busy(void);//检测LCD是否在忙,即能否接收数据和指令
voidLCD_Write_Command(ucharcommand);
voidLCD_Write_Data(uchardat);
voidLCD_Set_xy(ucharx,uchary);
ucharLCD_Read_Sta(void);
ucharLCD_Read_Data(ucharx,uchary);
voidUser_def_char(ucharn,uchar*s);//输入用户自定义字符(5*8点阵字符),0~7共8个字符
voidLCD_Disp_char(ucharx,uchary,uchardat);
voidLCD_Disp_string(ucharx,uchary,uchar*s);
ucharlarge=0;//当large为1时,为5*8点阵;为0时,为5*10点阵
voidIO_Init(void)
{
LCD_IO_SEL&=~0xF0;
//LCD_IO_DIR|=0x07;
P2DIR|=0x07;
P2SEL&=~0x07;
}
voidLCD_Init(void)
{
LCD_Write_Command(0x28);
LCD_Write_Command(0x0F);
LCD_Write_Command(0x06);
LCD_Write_Command(0x01);
}
voidLCD_Check_busy(void)
{
ucharflag=0x80;
flag&=LCD_Read_Sta();
while(flag==0x80)
{
__delay_cycles(100);
flag&=LCD_Read_Sta();
}
}
voidLCD_Write_Command(ucharcommand)
{
LCD_Check_busy();
CLR_LCD_1602_RS;
CLR_LCD_1602_RW;
CLR_LCD_1602_E;
uchartemp;
temp=command&(0x3C);
if((temp==(0x26))||(temp==(0x2C))||(temp==(0x36))||(temp==(0x3C)))
large=0;//为5*10点阵
else
large=1;
LCD_IO_DIR|=0xF0;
LCD_IO_OUT=(command&(0XF0))+(LCD_IO_OUT&(0x0F));
SET_LCD_1602_E;
CLR_LCD_1602_E;
command<<=4;
LCD_IO_OUT=(command&(0XF0))+(LCD_IO_OUT&(0x0F));
SET_LCD_1602_E;
CLR_LCD_1602_E;
}
voidLCD_Write_Data(uchardat)
{
LCD_Check_busy();
SET_LCD_1602_RS;
CLR_LCD_1602_RW;
CLR_LCD_1602_E;
LCD_IO_DIR|=0xF0;
LCD_IO_OUT=(dat&(0XF0))+(LCD_IO_OUT&(0x0F));
SET_LCD_1602_E;
CLR_LCD_1602_E;
dat<<=4;
LCD_IO_OUT=(dat&(0XF0))+(LCD_IO_OUT&(0x0F));
SET_LCD_1602_E;
CLR_LCD_1602_E;
}
voidLCD_Set_xy(ucharx,uchary)
{
ucharaddress;
if(y==0)
address=0x80+x;
else
address=0xC0+x;
LCD_Write_Command(address);
}
ucharLCD_Read_Sta(void)
{
ucharsta;
CLR_LCD_1602_RS;//读入状态信息高四位数据
SET_LCD_1602_RW;
CLR_LCD_1602_E;
LCD_IO_DIR&=~0xF0;
SET_LCD_1602_E;
__delay_cycles(10);
sta=LCD_IO_IN;
CLR_LCD_1602_E;
SET_LCD_1602_E;//读入状态信息低四位数据
__delay_cycles(10);
uchartemp;
temp=LCD_IO_IN;
CLR_LCD_1602_E;
sta&=0xF0;
temp>>=4;
temp&=0x0F;
sta=sta+temp;
return(sta);
}
ucharLCD_Read_Data(ucharx,uchary)
{
uchardat;
LCD_Set_xy(x,y);//确定读取数据坐标
SET_LCD_1602_RS;//读取数据高四位
SET_LCD_1602_RW;
CLR_LCD_1602_E;
LCD_IO_DIR&=~0xF0;
SET_LCD_1602_E;
__delay_cycles(10);
dat=LCD_IO_IN;
CLR_LCD_1602_E;
SET_LCD_1602_E;//读取数据低四位
__delay_cycles(10);
uchartemp;
temp=LCD_IO_IN;
CLR_LCD_1602_E;
dat&=0xF0;
temp>>=4;
temp&=0x0F;
dat=dat+temp;
return(dat);
}
voidUser_def_char(ucharn,uchar*s)
{
inti;
charaddr=0x40;
n<<=3;
addr+=n;
for(i=0;i<8;i++,addr++)
{
LCD_Write_Command(addr);
LCD_Write_Data(*s);
s++;
}
}
voidLCD_Disp_char(ucharx,uchary,uchardat)
{
LCD_Set_xy(x,y);
LCD_Write_Data(dat);
}
voidLCD_Disp_string(ucharx,uchary,uchar*s)
{
LCD_Set_xy(x,y);
while(*s)
{
LCD_Write_Data(*s);
s++;
}
}
欢迎您的下载,
资料仅供参考!
致力为企业和个人提供合同协议,策划案计划书,学习资料等等
打造全网一站式需求