社区导航

 

搜索
查看: 1458|回复: 0

[讨论] 准大三 刚刚接触单片机 NUEDC F题 用MSP430 LAUNCHPAD 做一个正弦波的频率显示

[复制链接]

2

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2015-8-13 02:19 | 显示全部楼层 |阅读模式
输入正弦波在经过过零检测电路之后变成了脉冲波,然后怎么做呢? 赶鸭子上架,单片机刚刚开始学,就懂一点点,请各位大神不吝赐教

补充 在网上找到了这么一个例子 可惜图片太模糊,不知怎么接线


5.4.2 信号频率测量实验
1.实验准备
信号源、示波器、LaunchPad开发板一套。
2.实验目的
(1)学习频率测量的两种方法,了解两种方法的差别以及各自的优点;
(2)加深对单片机定时器的了解及应用;
(3)学会使用定时器的中断。
3.实验原理
本实验中,对信号频率的测量我们有两种方法:直接测频率和通过测周期计算频率。其中直接测量频率的方法适用于测量较高频率的信号;通过测周期计算频率适用于频率较低的信号。下面分别介绍两种测量频率方法的原理。
(1)通过测周期计算频率
通过测量周期计算频率适用于测量频率较低的信号。具体原理是运用TA模块的捕获功能,在第一个上升沿到来的时候,开始计数,到下一次上升沿到来的时候停止计数,通过计数个数计算出高电平的时间。这个时间就是测量周期,取测量周期的倒数就是待测频率。通过测量周期进行低频率信号的测量具有得天独厚的优势,试想如果想要通过计数的方法测量0.1HZ的方波频率,那就需要等待至少10s才能测量出带测信号的频率,这种灵敏度是不可容忍的。
(2)直接测频法
直接测频法有硬件测量和软件测量两种方式,但是无论是软件测量还是硬件测量都需要精准的1S钟定时中断,1S的定时中断常用TA模块产生。思路是:将DCO校准到1MHZ,DCO是1MHZ的实质含义是一个脉冲花费1us,如果有100万个脉冲到来则可认为到了1s。以下是1s定时的产生方法:将SMCLK(1MHZ)输入TA模块,对输入时钟进行4分频,那么输入的时钟就等效于250KHZ,将TA设置为增计数模式,TACCR0设置为10000,在TA溢出中断
242
中进行计数,计满25个意味着从TA输入了100万个时钟,等效于计满了1s。当秒定时产生以后,接下来就是在1s内对到来的脉冲数进行计数。计数有两种方式,硬件方式和软件方式。
(3)实验原理图
图5.4.1 实验原理图(太模糊了 而且图里似乎有一个DA芯片 430不是自带AD  DA 的么)
4.实验步骤
(1)根据电路图连接电路并减查电路是否正确;
(2)将下列例程编辑到仿真软件,编译并下载程序;
(3)用信号源产生不同频率的方波(正弦波、三角波)输入到电路中,并用示波器测量信号的频率,观察测量的结果是否正确;
(4)总结实验结果。
5.程序示例
(1)主程序
#include
#include "msp430g2553.h"
#include "CLK.h"
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // 停止看门狗
sys_Clock_Init(MCLK_1MHz); //设置DCO频率可以是 1、8、12、16 MHz
dac_Init(); //初始化DAC使用的
TA1_inittoDA();
out_v(1,5.0);
out_v(2,2.0);
}
(2)时钟程序
#include "clk.h"
void sys_Clock_Init(unsigned char FRQ)
{
BCSCTL2 = SELM_0 + DIVM_0 + DIVS_0;
if (CALBC1_16MHZ != 0xFF)
{
243
DCOCTL = 0x00;
switch(FRQ)
{
case 1: //1Mhz
{
BCSCTL1 = CALBC1_1MHZ; // Set range
DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation */
break;
}
case 8: //8Mhz
{
BCSCTL1 = CALBC1_8MHZ; // Set range
DCOCTL = CALDCO_8MHZ; // Set DCO step + modulation */
break;
}
case 12: //12Mhz
{
BCSCTL1 = CALBC1_12MHZ; // Set range
DCOCTL = CALDCO_12MHZ; // Set DCO step + modulation*/
break;
}
case 16: //16Mhz
{
BCSCTL1 = CALBC1_16MHZ; // Set range
DCOCTL = CALDCO_16MHZ; // Set DCO step + modulation*/
break;
}
default:break;
}
}
BCSCTL1 |= XT2OFF + DIVA_0;
BCSCTL3 = XT2S_0 + LFXT1S_2 + XCAP_1;
}
void delayus(unsigned int us)
{
unsigned int i;
for(i=0;i __delay_cycles(16);
}
(3)D/A程序
#include "DAC8552.h"
#include "sin_Tab.h"
#include "CLK.h"
244
#include "msp430g2553.h"
unsigned int frequency;
unsigned int time_us;
/*DAC8552——SPI初始化*/
void dac_Init(void)
{
P1OUT = 0x00;
P1DIR |= BIT5 +BIT7; //P1.4做SYNC
SYNC_H;
P1SEL = BIT5 + BIT7; //P1.5、7分别作SCLK和SIMO
P1SEL2 = BIT5 + BIT7;
P2DIR |= BIT5;
UCB0CTL1 |= UCSWRST; //禁止 USCI状态机
/* ~UCCKPH -- 数据在UCLK的第一个边沿变换,在下一个边沿捕获。
* ~UCCKPL -- 空闲状态为低——这两个就决定数据在下降沿写出
* UCMSB -- 最高位先出
* ~UC7BIT -- 8位数据
* UCMST -- 主机模式
* UCMODE_0 -- 3线制 SPI
* UCSYNC -- 同步模式*/
UCB0CTL0 = UCMSB + UCMST + UCMODE_0 + UCSYNC;//
UCB0CTL1 = UCSSEL_2 + UCSWRST;
UCB0BR0 = 1;
/* Enable USCI */
UCB0CTL1 &= ~UCSWRST; //启动USCI状态机
}
void out_v(char channl,float voltage)
{
unsigned int buf;
char high,low;
buf=(voltage/4.95)*65535;
low=buf&0xFF;
high=buf>>8;
switch(channl)
{
case 1:
{
245
SYNC_L; //选通拉低
UCB0TXBUF = 0X10; //向DA写入命令——通道A,立即转换
while (!(IFG2 & UCB0TXIFG));
UCB0TXBUF = high; //写入高8位
while (!(IFG2 & UCB0TXIFG));
UCB0TXBUF = low; //写入低8位
while (!(IFG2 & UCB0TXIFG));
SYNC_H; //选通拉高
}break;
case 2:
{
SYNC_L; //选通拉低
UCB0TXBUF = 0X24; //向DA写入命令——通道B,立即转换
while (!(IFG2 & UCB0TXIFG));
UCB0TXBUF = high; //写入高8位
while (!(IFG2 & UCB0TXIFG));
UCB0TXBUF = low; //写入低8位
while (!(IFG2 & UCB0TXIFG));
SYNC_H; //选通拉高
}break;
case 3:
{
TA1CCR2=(voltage/3.54)*2000;
}
}
}


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

关闭

站长推荐上一条 1/7 下一条

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

Archiver|手机版|小黑屋|电子工程世界 ( 京ICP证 060456 )

GMT+8, 2020-5-26 13:31 , Processed in 0.094051 second(s), 20 queries , Gzip On, MemCache On.

快速回复 返回顶部 返回列表