打印
[MCU]

代码跑步起来

[复制链接]
301|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
liliang9554|  楼主 | 2020-1-22 23:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

//软件设计介绍:基于MSP430的单相交流电能质量采集模块程序
//***************************************************
//功能介绍:对220V交流电能质量的采集并显示
//对P6.0口电压进行采集 液晶显示(输入的是脉冲波形(去除掉正弦波形的负半周))
//对P6.1口电流进行采集 液晶显示(同上)
//对P2.3口频率进行采集 液晶显示(输入的方波)
/*
LCD16x2
预演效果如下
****************
V:220.0V I:400uA
P:50.00Hz
*/
//****************************************************
#include  <msp430x14x.h>
#include  "cry1602.h"
//#include  "cry1602.c"
//有一个报错:目前的解决方案是注释掉上面一行的语句,并且把1602.C里面的int,char定义放到.h里面去
#define   Num_of_Results   32   

uchar shuzi[] = {"0123456789."};//定义数字
uchar tishi1[] = {"V:"};//定义提示电压信息
uchar tishi2[] = {"I:"};//定义提示电流信息
uchar tishi3[] = {"P:"};//定义提示频率信息
uchar tishi4[] = {"uA"};//定义提示电流单位
uchar tishi5[] = {"Hz"};//定义提示频率信息

uint start,end;
uint width; //==用于存放脉宽==
uint period; //==用于存放周期==
uint frequency; //==用于存放频率==
uint fy[4]; //==用于存放频率显示数据==
void process(void); //==函数声明==
void InitSys();    //==初始化时钟==

static uint A0results[Num_of_Results];    //保存ADC转换结果的数组  
static uint A1results[Num_of_Results];    //保存ADC转换结果的数组
void Trans_val(uint Hex_Val);
void Trans_val1(uint Hex_Val);



/**********************************************************/
void main(void)
{
  WDTCTL = WDTPW+WDTHOLD;                   //关闭看门狗
  LcdReset();                               //复位1602液晶
  DispNChar(0,0,2,tishi1);                  //显示电压提示信息
  //分配电压信息的坐标值(第1个位置开始,放在LCD的第1行)
  DispNChar(9,0,2,tishi2);                  //显示电流提示信息
  DispNChar(0,1,2,tishi3);                  //显示频率提示信息
  Disp1Char(7,0,'V');                      //显示电压单位V
  DispNChar(14,0,2,tishi4);                   //显示电流单位uA
  DispNChar(7,1,2,tishi5);                      //显示频率单位Hz
  
//ADC的初始化
  P6SEL |= BIT0;                            //使能ADC通道A0,即P6.0口(采集电压)0x01
  P6SEL |= BIT1;                            //使能ADC通道A1,即P6.1口(采集电流) 0x02
  ADC12CTL0 = ADC12ON+SHT0_8+MSC;           //打开ADC,设置采样时间 SHT0_8是64分频
  //上面的配置没有打开内部的参考电压
  //ADC12MCTLx用来选择通道和参考电压,这里面没有对此寄存器进行配置为默认的值
  //默认值是参考电压选择AVCC(3.3V),通道是A0,所以测量范围是0~3.3V
  //选择通道与参考电压的被省略: ADC12MCTL0=ADC12INCH_0+ADC12SREF_1;
  ADC12CTL1 = CSTARTADD_0+SHP+CONSEQ_3;                 //使用采样定时器,序列通道多次重复采集
  //寄存器配置采样保持触发源选择时ADC12SC,采样信号使用采样时序电路产生的信号
  ADC12IE = BIT0;                           //使能ADC中断 P6.0
  ADC12IE = BIT1;                           //使能ADC中断 P6.1
  ADC12CTL0 |= ENC;                         //使能转换
  ADC12CTL0 |= ADC12SC;                     //开始转换

  //定时器的初始化
  InitSys(); //==初始化时钟,SMCLK,MCLK均为8M==
  
  P2DIR&=~BIT3;
  P2SEL = BIT3; //==设置P1.2端口为功能模块使用,即:做捕获源==
  TACTL = TASSEL_2+ID_3+TACLR+TAIE+MC1;//==定时器A时钟信号选择SMCLK,8分频,同时设置定时器A计数模式为连续增计模式==   
  
  CCTL1 = CM_1+SCS+CAP+CCIE; //==输入上升沿捕获,CCI0A为捕获信号源==


  _EINT();                                  //使能中断,(开启全局中断)
  LPM0;                                     //低功耗模式
}

/**********************************************************/

//ADC中断服务函数
#pragma vector=ADC_VECTOR                  
__interrupt void ADC12ISR (void)
{
  static uint index = 0;
  A0results[index++] = ADC12MEM0;// 将转换出来的结果存入数组
  A1results[index++] = ADC12MEM1;// 将转换出来的结果存入数组
  if(index == Num_of_Results)//如果数组存满           
  {
        uchar i;
        unsigned long sum0 = 0;
        unsigned long sum1 = 0;
        index = 0;//再重新开始存放数组(会导致覆盖原有的数据)
        for(i = 0; i < Num_of_Results; i++)//计算数组的和
        {
            sum0 += A0results[i];
            sum1 += A1results[i];
        }
        sum0 >>= 5;                            //除以32,得到平均值,因为前面定义了一个32,即采集32次
        sum1 >>= 5;
        sum0=(sum0<<7)+(sum0<<5)+(sum0<<4);
        //采集时电压在前端的处理电路中被放小了多少,
        //这里就放大回去,分析得出应该为176倍(变回220V)
        sum1=(sum1<<10)+(sum1<<6)+(sum1<<5)+(sum1<<3)+(sum1<<2);
        //放大回去,分析得出应该为1132倍
        //(这里求电流,1K的采样电阻要/1000,但是单位A变为uA要*10^6,所以是*1000)
        Trans_val(sum0);
        Trans_val1(sum1);
  }
}

/**********************************************************/
/********频率采集处理模块**********/
//时钟初始化函数
void InitSys()
{
   unsigned int i;
//--- 使用XT2振荡器,8MHz的那个 ---
   BCSCTL1&=~XT2OFF; //==打开XT2振荡器==

   do
   {
   IFG1 &= ~OFIFG; //==清除振荡器失效标志==
   for (i = 0xFF; i > 0; i--); //==延时,等待XT2起振==
  }
  while ((IFG1 & OFIFG) != 0); //==判断XT2是否起振==
  BCSCTL2 =SELM_2+SELS; //==选择MCLK、SMCLK为XT2,8M==  
}


//中断处理函数
#pragma vector=TIMERA1_VECTOR //==定时器A中断处理==
__interrupt void timer_a(void)
{
  switch(TAIV) //==向量查询==
  { case 2: //==捕获中断==
       if(CCTL1&CM0) //==捕获到上升沿==
         {
            CCTL1=(CCTL1&(~CM0))|CM1; //==更变设置为下降沿触发==
           start=TAR; //==记录初始时间==           
         }
   
       else if (CCTL1&CM1) //==捕获到下降沿==
        {
            CCTL1=(CCTL1&(~CM1))|CM0; //==更变设置为上升沿触发==
           end=TAR; //==用start,end,overflow计算脉冲宽度==
           
        }
        break;
                    
    default:
       break;
  }
}
  
  
//数据处理函数
void process(void)
{
    while(end<start);
    //while(end<start)的话就让其一直等待下去,直到end>start
    uchar i;
    width = end-start; //==实际脉冲宽度的计算==
    period = 2* width;
    frequency=10000/period; //这里放大的目的是为了后面便于显示
      
    fy[0]=frequency/10000;
    fy[1]=(frequency-10000*fy[0])/1000;
    fy[3]=(frequency-10000*fy[0]-1000*fy[1])/100;
    fy[4]=(frequency-10000*fy[0]-1000*fy[1]-100*fy[3])/10;
    fy[2]=shuzi[10];
    for(i = 0;i < 5;i++)
    Disp1Char((2 + i),1,shuzi[fy[i]]); //第3个开始显示5位 ,例如 50.00,然后在第8位加上单位Hz)
}


/**********************************************************/

//将16进制的ADC转换数据变为10进制的模拟电压,电流数据并显示到LCD上面
//电压转换部分
void Trans_val(uint Hex_Val)
{
    unsigned long caltmp;
    uint Curr_Volt;
    uchar t1,i;
    uchar ptr[5];  
    caltmp = Hex_Val;
    caltmp = (caltmp << 5) + Hex_Val;           //caltmp = Hex_Val * 33 扩大10倍便于计算
    caltmp = (caltmp << 3) + (caltmp << 1);     //caltmp = caltmp * 10  扩大10倍便于计算
    Curr_Volt = (caltmp >> 12);                   //Curr_Volt = caltmp / 2^n  
    //由于这里是V为单位,要转化为
    //参考电压为3.3V,所以计算公式应该为Hex_Val*3.3/2^n
    //在程序计算的过程中位移运算是最有效率的
    //实际电压值是3.3*(ad采样值)/1024(v)
    ptr[0] = Curr_Volt / 10000;//百位上面的数字(Hex到Dec的变换)因为放大了,所以要除以100*100
    ptr[1] = (Curr_Volt % 10000)/1000; //十位上面的数字
    ptr[2] = (Curr_Volt % 1000)/100; //个位上面的数字
    t1 = Curr_Volt - (ptr[0] * 10000)-(ptr[1] * 1000)-(ptr[2] * 100);
    ptr[4] = t1 / 10;//相当于小数点后第一位
    ptr[3] = shuzi[10];//数字表中第10位对应符号"."
    //在液晶上显示变换后的结果
    for(i = 0;i < 5;i++)
    Disp1Char((2 + i),0,shuzi[ptr[i]]);  //(第3个开始显示5位 ,例如 220.0,然后在第8位加上单位V)
}

//电流转换部分
void Trans_val1(uint Hex_Val)
{
    unsigned long caltmp;
    uint Curr_I;
    uchar i;
    uchar ptr[3];  
    caltmp = Hex_Val;
    caltmp = (caltmp << 5) + Hex_Val;           //caltmp = Hex_Val * 33 扩大10倍便于计算
    caltmp = (caltmp << 3) + (caltmp << 1);     //caltmp = caltmp * 10  扩大10倍便于计算
    Curr_I = caltmp >> 12;                   //Curr_Volt = caltmp / 2^n
    //参考电压为3.3V,所以计算公式应该为Hex_Val*3.3/2^n
    //在程序计算的过程中位移运算是最有效率的
    //实际电压值是3.3*(ad采样值)/1024(v)
    ptr[0] = Curr_I / 10000;//百位上面的数字(Hex到Dec的变换)
    ptr[1] = (Curr_I % 10000)/1000; //十位上面的数字
    ptr[2] = (Curr_I % 1000)/100; //个位上面的数字
    //在液晶上显示变换后的结果
    for(i = 0;i < 3;i++)
    Disp1Char((11 + i),0,shuzi[ptr[i]]); //(第12个开始显示3位 ,例如 400,然后在第15位加上单位uA)
}

使用特权

评论回复

相关帖子

沙发
liuzaiy| | 2020-1-22 23:29 | 只看该作者
代码放上去跑不起来是什么意思,程序不运行吗?还是别的什么

使用特权

评论回复
板凳
yinxiangh| | 2020-1-22 23:32 | 只看该作者
有没有数据,程序编译上有没有问题

使用特权

评论回复
地板
pangb| | 2020-1-22 23:33 | 只看该作者
单步调试程序看看死在哪边

使用特权

评论回复
5
yszong| | 2020-1-22 23:35 | 只看该作者
1602要是本身显示就不正常,就调他的基本操作函数。要是正常,但电压等内容不正常。就用串口调一下。看看是得不到数,还是数不对,再往下分析。

使用特权

评论回复
6
chenjunt| | 2020-1-22 23:36 | 只看该作者
可能性太多,不好说!

使用特权

评论回复
7
xxmmi| | 2020-1-22 23:37 | 只看该作者

代码放哪里跑了

使用特权

评论回复
8
kangzj| | 2020-1-22 23:38 | 只看该作者
这个先看中断的正常启用起来没

使用特权

评论回复
9
guoyt| | 2020-1-22 23:43 | 只看该作者
硬件的问题吗?

使用特权

评论回复
10
yufe| | 2020-1-22 23:44 | 只看该作者

怎么无法跑程序

使用特权

评论回复
11
llia| | 2020-1-22 23:45 | 只看该作者
不一定是软件的问题

使用特权

评论回复
12
wangzsa| | 2020-1-22 23:46 | 只看该作者

线检查硬件电路。

使用特权

评论回复
13
gongche| | 2020-1-22 23:47 | 只看该作者
LCD能够亮吗?

使用特权

评论回复
14
huanghuac| | 2020-1-22 23:48 | 只看该作者

楼主使用的14系类的单片机,编译器是否设置正确

使用特权

评论回复
15
wenfen| | 2020-1-22 23:48 | 只看该作者
晶振是否正常工作?

使用特权

评论回复
16
songqian17| | 2020-1-22 23:49 | 只看该作者
单步调试尝试了吗

使用特权

评论回复
17
chenho| | 2020-1-22 23:49 | 只看该作者
查看电源供电和晶振。

使用特权

评论回复
18
chuxh| | 2020-1-22 23:50 | 只看该作者
测量一下电源的电压是否正常?

使用特权

评论回复
19
zhuhuis| | 2020-1-22 23:51 | 只看该作者
最好把工程文件都上传测试一下。

使用特权

评论回复
20
liliang9554|  楼主 | 2020-1-22 23:51 | 只看该作者

其实还是不大明白,我再琢磨琢磨吧,多谢了哈先

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

950

主题

11568

帖子

6

粉丝