找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1567|回复: 1
打印 上一主题 下一主题
收起左侧

MSP430频率显示仪

[复制链接]
跳转到指定楼层
楼主
ID:520780 发表于 2019-4-24 20:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <msp430x14x.h>
#include "config.h"
uint k=0,flag=0,overflow = 0;                      //溢出次数
ulong fre,period_star=0,period=0,freH =0,temp=0;//频率值,中间变量
float freL;
float multi=0;
uchar unitL[]="Hz",unitH[]="kHz",a[];                                         //存放字符
uchar *x={'\0'},*unit={'\0'};
int i,point,len=0;                 

//*************************************************************************
//        初始化IO口子程序
//*************************************************************************
void Port_Init()
{

  LCD_DATASEL = 0X00;                               //(P4)LCD的D7-D0端口普通IO模式,输出模式
  LCD_DATADIR = 0XFF;                              

  LCD_CONSEL  = 0X00;                               //(P5)LCD的控制管脚普通IO模式
  LCD_CONDIR |= BIT0 + BIT1 + BIT5 + BIT6 + BIT7;   //(P5)LCD控制管脚0(PSB)、1(RST)、5(RS)、6(RW)、7(EC)置1输出模式

  PSB_SET;                                          //LCD串并脚PSB置高,并口方式
  RST_SET;                                            //LCD复位脚RST置高,复位

  LED8DIR = 0xff;                                   //设置LED指示灯
  LED8 = 0xFF;
}



//***********************************************************************
//        显示屏命令写入函数
//***********************************************************************
void LCD_write_com(unsigned char com)
{       
  RS_CLR;                                           //LCD的RS和RW置0,在EN下降沿时,指令从端口写入
  RW_CLR;
  EN_SET;
  LCD_DATAPORT = com;
  delay_ms(5);
  EN_CLR;
}


//***********************************************************************
//        显示屏数据写入函数
//***********************************************************************
void LCD_write_data(unsigned char data)
{
  RS_SET;                                           //LCD的RS置1,RW置0,在EN下降沿时,数据从端口写入
  RW_CLR;
  EN_SET;
  LCD_DATAPORT = data;
  delay_ms(5);
  EN_CLR;
}


//***********************************************************************
//        显示屏清空显示
//***********************************************************************
void LCD_clear(void)
{
  LCD_write_com(0x01);
  delay_ms(5);
}


//***********************************************************************
//函数名称:DisplayCgrom(uchar hz)显示CGROM里的汉字
//***********************************************************************
void DisplayCgrom(uchar addr,uchar *hz)
{
  LCD_write_com(addr);                               //写入地址
  delay_ms(5);
  while(*hz != '\0')  
  {
    LCD_write_data(*hz);                             //写入数据
    hz++;
    delay_ms(1);
  }

}


//****************************************************************
//函数名称:Display()显示测试结果
//****************************************************************
void Display(void)
{
  DisplayCgrom(0x80,"当前信号频率为:");
  DisplayCgrom(0x88,x);
  DisplayCgrom(0x8d,unit);
}


//***********************************************************************
//        显示屏初始化函数
//***********************************************************************
void LCD_init(void)
{
  LCD_write_com(FUN_MODE);                        //工作模式:8位基本指令集
  delay_ms(5);
  LCD_write_com(DISPLAY_ON);                        //显示开,显示游标,且游标位置反白
  delay_ms(5);
  LCD_clear();                                        //清屏
  delay_ms(5);
}


//***********************************************************************
//      TIMERA初始化,用比较寄存器0,设置为增计数,阈值60000
//***********************************************************************
void TIMERA0_Init(void)                                   
{

  P1SEL |= BIT0;                                 //计时器时钟为TACLK,在P1.0,将其设为第二功能,输入模式
  P1DIR &= ~BIT0;

  TACTL = TACLR;            
  TACCR0 = 60000-1;                              //寄存器0比较模式,阈值60000   
  TACCTL0 |= CCIE;
  TACTL =  MC0;                                   //TACLK做时钟源,增计数模式            
  //P6OUT &= ~BIT0 ;




}
//***********************************************************************
//        TIMERA初始化,用捕获寄存器1,设置为连续计数
//***********************************************************************
void TIMERA1_Init(void)
{
  P1SEL |= BIT2;                           //捕获寄存器的捕获管脚在P1.2
  P1DIR &= ~BIT2;

  TACTL = TACLR;
  TACCTL1 |= CM0 + SCS + CAP + CCIE;           //寄存器1捕获模式,上升沿,CCIxA,同步
  TACTL |=TASSEL0 + MC1 + TAIE;

}


//***********************************************************************
//             寄存器0中断服务程序,计数器达到60000将溢出次数+1
//***********************************************************************
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A0 (void)
{
  overflow=overflow+1;
}


//***********************************************************************
//             寄存器1中断服务程序,达到捕获条件
//***********************************************************************
#pragma vector=TIMERA1_VECTOR
__interrupt void Timer_A1 (void)
{
  switch(TAIV)
  {  
    case 2:
    {
      k++;
      if(k==1) period_star = 60000*overflow + TACCR1;
      else if (k==2)
      {
        period = 60000*overflow + TACCR1-period_star;


        freL=multi*32768/period;
        temp=(ulong)freL;                               //计算长度

        len=0;
        while(temp)
        {
          len++;
          temp/=10;
        }
        if (len<4) {len=4;point++;temp =(ulong)(10*freL);}
        else {temp=(ulong)freL;}

        for (i=len;i>=0;i--)                    //存入指针中
        {
          if(i!=(len-point))
          {
            a[i]=temp%10+48;
            temp=temp/10;
          }
          else
          {
            a[i]='.';
          }
         }
        a[len+1]='\0';
        x=a;
      }   



    }break;

    case 4:break;
    case 10:
      {
        overflow++;
        break;
      }
    default:break;
  }
}


//***********************************************************************
//             WDT中断服务程序,1s时间到,计算频率,并转换成字符
//***********************************************************************
#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
{
  flag++;
  if(flag==2)
  {
    WDT_Init();                                            //5s到,关看门狗

    P6OUT &= ~BIT7;                                        //LED8亮作为提示
    P6OUT |= BIT0;

    freH=TAR+overflow*60000;                               //计算频率(此时是5倍的值,因为看门狗走了五秒)


    //判断频率的精度和位数
      if      (freH<20)       { point=3;unit=unitL;multi=1000;}            //频率在10Hz     以内
      else if (freH<200)      { point=2;unit=unitL;multi=100; }            //频率在10-100Hz 之间
      else if (freH<2000)     { point=1;unit=unitL;multi=10;  }            //频率在100-1kHz 之间
      else if (freH<4000)    { point=3;unit=unitH;multi=1;   }            //频率在1k-2kHz  之间
      else if (freH<20000)    { point=4;unit=unitH; }            //频率在2-10kHz  之间
      else if (freH<200000)   { point=4;unit=unitH; }            //频率在10k-100k 之间
      else if (freH<2000000)  { point=4;unit=unitH; }            //频率在100k-1MHz之间


    //判断频率高低频,高频脉冲测量输出,低频重新用周期法捕获测量
    if (freH>10000)
    {


      fre=5*freH;                                                //得到10倍频率

      //将测出来的数值转换成字符  

      temp=fre;                               //计算长度
      len=0;
      while(temp)
      {
        len++;
        temp/=10;
      }

      for (i=len;i>=0;i--)                    //存入指针中
      {
        if(i!=(len-point))
        {
          a[i]=fre%10+48;
          fre=fre/10;
        }
        else
        {
          a[i]='.';
        }
      }
      a[len+1]='\0';
      x=a;

    }   


    else
    {
      TIMERA1_Init();
      _EINT();      
    }



  }

}

//***********************************************************************
//      主程序
//***********************************************************************
int main(void)
{
  WDT_Init();                                    //关闭看门狗  
  Clock_Init_Ex32768();                          //系统时钟设置8M
  Port_Init();                                   //LCD端口初始化
  delay_ms(100);                                 //延时100ms
  LCD_init();                                    //液晶参数初始化设置
  LCD_clear();                                   //清屏

  TIMERA0_Init();                                 //比较寄存器0初始化

  IE1 |= WDTIE;                                  //打开开门狗中断,全局中断
  _EINT();

  WDTCTL = WDT_ADLY_1000;                        //看门狗计时1s

  DisplayCgrom(0x80,"信号频率测量中");
  DisplayCgrom(0x88,"请稍等...");
  delay_ms(3000);
  LCD_clear();

  delay_ms(200);
  while(1)
  {
    Display();                             //显示汉字  
    /*//重新启动
    delay_ms(1000);
    overflow = 0;
    TIMERA0_Init();
    IE1 |= WDTIE;                                  //打开开门狗中断,全局中断
    _EINT();
    WDTCTL = WDT_ADLY_1000;*/
    }
}





Frequency.rar

34.94 KB, 下载次数: 6, 下载积分: 黑币 -5

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1 发表于 2019-4-24 21:34 | 只看该作者
本帖需要重新编辑补全电路原理图,源码,详细说明与图片即可获得100+黑币(帖子下方有编辑按钮)
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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