msp430g2553内存不足和中断算法时间问题

2019-03-24 10:54发布

用msp430g2553做一个电能检测装置,20us进一次中断,在中断里面进行采样和ANF锁相算法的运算,现在出现了两个问题解决不了,1.内存不够,建立80以上的数组就提示空间不够,2.进中断后还没算完锁相运算就要要进入下一次中断了,由于终端算法必须要在一个周期内取多个点,所以中断时间不能加大,请问大神有什么解决方案吗?help!!!!!!!!!
  1. #include "msp430g2553.h"
  2. #define uint  unsigned int
  3. #define uchar  unsigned char
  4. #define NOP() __no_operation() //本句很重要是关于NOP在430里好不好用的问题
  5. #define HT1621_CS BIT3;    //LCD 引脚定义
  6. #define HT1621_WR BIT4;
  7. #define HT1621_DAT BIT5;
  8. #define  BIAS     0x52             //0b1000 0101 0010  1/3duty 4com
  9. #define  SYSDIS   0X00             //0b1000 0000 0000  关振系统荡器和LCD偏压发生器
  10. #define  SYSEN    0X02             //0b1000 0000 0010 打开系统振荡器
  11. #define  LCDOFF   0X04             //0b1000 0000 0100  关LCD偏压
  12. #define  LCDON    0X06             //0b1000 0000 0110  打开LCD偏压
  13. #define  XTAL     0x28             //0b1000 0010 1000 外部接时钟
  14. #define  RC256    0X30             //0b1000 0011 0000  内部时钟
  15. #define  TONEON   0X12             //0b1000 0001 0010  打开声音输出
  16. #define  TONEOFF  0X10             //0b1000 0001 0000 关闭声音输出
  17. #define  WDTDIS1   0X0A        //0b1000 0000 1010  禁止看门狗

  18. //ANF全局变量定义
  19.         float sinevalue=0.0;
  20.         float w=314.1593;
  21.         float dc=0.0;
  22.         float jibo=0.0;
  23.         float jiboquad=0.0;
  24.         float q=0.0;
  25.         float sinesum=0.0;
  26.         float f=50.0;
  27.         float e=0.0;                                //ANF锁相中变所需
  28.         float a1=0.0;
  29.         float a2=0.0;
  30.         float tim=0.0002;
  31.         float shuju;
  32. uint a[2],UI[20];
  33. uint i,j,ad1,ad0,x;

  34. const unsigned char Row[]={0x04,0x08,0x10};  //行为高电平扫描
  35. const unsigned char Col[]={0x20,0x40,0x80};  //列检测高电平
  36. volatile unsigned short KeyBuff = 0;  //定义为char的话存储的不是数值,不知为何
  37. volatile unsigned int temp1,t;  //全局定义会不会对内存有优化,而不是每次调用函数都重新定义
  38. void display1(int KeyBuff);

  39. uchar  Ht1621Tab[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//32个地址缓冲区
  40. uchar SEG_7[10][2]=
  41. {
  42.   0xc4,0xc8,//00
  43.   0x04,0x40,//01
  44.   0x4c,0x88,//02
  45.   0x4c,0x48,//03
  46.   0x8c,0x40,//04
  47.   0xc8,0x48,//05
  48.   0xc8,0xc8,//06
  49.   0x44,0x40,//07
  50.   0xcc,0xc8,//08
  51.   0xcc,0x48,//09
  52. };//        定义0-9数字的二维数组

  53. //ANF算法程序
  54. void anf(float shuju)
  55. {
  56.     sinevalue =(shuju-512)*0.0007326*300;
  57.     e=sinevalue-sinesum;
  58.         dc = dc + e* 65 * tim;
  59.         a1=w * q;
  60.         a2= w * e;
  61.         jibo = jibo+tim* (1.2*a2-w*a1);
  62.         q=q+tim*jibo;
  63.         jiboquad=-w *q;
  64.         sinesum= dc + jibo;
  65.         w=w-a2*q*0.1*tim;
  66.         f=w* 0.159155;
  67. }


  68. //定时器中断初始化函数
  69. void timer_init()
  70. {
  71.   TACCR0 =200;  //计到2500,约100s
  72.   TACTL = TASSEL_2+MC_1+TACLR;  //设置TIMERA的时钟源为SMCLK(1M),8分频后(125K),计数模式为up,到CCR0再自动从0开始计数
  73.   TACCTL0 |= CCIE;                             // CCR0 interrupt enabled
  74. }

  75. //键盘扫描函数
  76. void ScanKey()
  77. {


  78.     //KeyBuff = 0;
  79.     for(i=0;i<3;i++) //行扫描
  80.     {
  81.               x++;

  82.         P1OUT = Row[i];  //行依次为高电平
  83. //        __delay_cycles(1000);  //防抖延时,不知道该插到哪里
  84.         if(x>10)
  85.                         {
  86.                                 x=0;

  87.         temp1 = P1IN & 0xe0;  //只取列的数据,PxOUT会影响PxIN的数据
  88.         for(j=0;j<3;j++)  //扫描列
  89.         {
  90.             if(temp1 == Col[j])  //判断按键取值为那一列对应的值
  91.             {
  92.                 KeyBuff =i*3+j+1;  //计算该按键对应的数值
  93.             }
  94.         }
  95.     }
  96.     }

  97. }


  98. //延时函数
  99. //void Delay(uchar us)  //5,7,9
  100. //{
  101. //  while(--us);
  102. //}
  103. ////-----------------------------------------------------------------------------------------
  104. ////函数名称:DelayMS()
  105. ////功    能:延时子程序
  106. ////-----------------------------------------------------------------------------------------
  107. //void DelayMS(uint iMs)
  108. //{
  109. //  uint i,j;
  110. //  NOP();
  111. //    for(i=0;i<iMs;i++)
  112. //    for(j=0;j<65;j++)
  113. //  {
  114. //   Delay(1);
  115. //  }
  116. //}

  117. //-----------------------------------------------------------------------------------------
  118. //函数名称:Ht1621Wr_Data()
  119. //功    能:写数据函数,cnt为传送数据位数,数据传送为低位在前
  120. //-----------------------------------------------------------------------------------------

  121. //LCD屏写数据函数
  122. void Ht1621Wr_Data(uchar Data,uchar cnt)
  123. {
  124.   uchar i;
  125.   for (i=0;i<cnt;i++)
  126.   {
  127.         P2OUT &= ~HT1621_WR;
  128.     NOP();
  129.     NOP();
  130.     NOP();
  131.         if((Data & 0x80)==0x80)
  132.         {
  133.            P2OUT |=HT1621_DAT;
  134.         }
  135.           else
  136.         {
  137.            P2OUT &=~HT1621_DAT;
  138.         }
  139.     P2OUT |=HT1621_WR;
  140.     NOP();
  141.     NOP();
  142.     NOP();
  143.     Data<<=1;
  144.   }
  145. }
  146. //-----------------------------------------------------------------------------------------
  147. //函数名称:void Ht1621WrCmd(uchar Cmd)
  148. //功能描述: HT1621命令写入函数
  149. //参数说明:Cmd为写入命令数据
  150. //说    明:写入命令标识位100
  151. //-----------------------------------------------------------------------------------------
  152. void Ht1621WrCmd(uchar Cmd)
  153. {
  154.   P2OUT&=~HT1621_CS;
  155.   NOP();
  156.   NOP();
  157.   NOP();
  158.   Ht1621Wr_Data(0x80,4); //写入命令标志100
  159.   Ht1621Wr_Data(Cmd,8); //写入命令数据
  160.   P2OUT |= HT1621_CS;
  161.   NOP();
  162.   NOP();
  163.   NOP();
  164. }
  165. //-----------------------------------------------------------------------------------------
  166. //函数名称:void Ht1621WrAllData()
  167. //功能描述: HT1621连续写入方式函数
  168. //说    明:HT1621的数据位4位,此处每次数据为8位,写入数据总数按8位计算
  169. //-----------------------------------------------------------------------------------------
  170. void Ht1621WrAllData(uchar Addr,uchar *p,uchar cnt)
  171. {
  172.   uchar i;
  173.   P2OUT &=~HT1621_CS;
  174.   Ht1621Wr_Data(0xa0,3); //写入数据标志101
  175.   Ht1621Wr_Data(Addr<<2,6); //写入地址数据
  176.   for (i=0;i<cnt;i++)
  177.   {
  178.    Ht1621Wr_Data(*p,8); //写入数据
  179.    p++;
  180.   }
  181.   P2OUT |=HT1621_CS;
  182.   NOP();
  183.   NOP();
  184.   NOP();
  185. }
  186. //-----------------------------------------------------------------------------------------
  187. //函数名称:void Ht1621_Init(void)
  188. //功能描述: HT1621初始化
  189. //说    明:初始化后,液晶屏所有字段均显示
  190. //-----------------------------------------------------------------------------------------
  191. void Ht1621_Init(void)
  192. {
  193.         int lk=0;
  194.         lk++;
  195.    P2OUT |=HT1621_CS;
  196.    NOP();
  197.    P2OUT |=HT1621_WR;
  198.    NOP();
  199.    P2OUT |=HT1621_DAT;
  200.    NOP();
  201.    if(lk>=2000)
  202.    {
  203. //   DelayMS(2000);                         //延时使LCD工作电压稳定
  204.    Ht1621WrCmd(BIAS);
  205.    Ht1621WrCmd(RC256);              //使用内部振荡器
  206.    Ht1621WrCmd(SYSDIS);
  207.    Ht1621WrCmd(WDTDIS1);
  208.    Ht1621WrCmd(SYSEN);
  209.    Ht1621WrCmd(LCDON);
  210.    }
  211. }
  212. //-----------------------------------------------------------------------------------------
  213. //函数名称:Initial()
  214. //功    能:初始化子程序
  215. //-----------------------------------------------------------------------------------------
  216. void Initial(void)
  217. {
  218. WDTCTL = WDTPW + WDTHOLD;//关闭看门狗
  219. BCSCTL1 = CALBC1_1MHZ;                    // Set range
  220.   DCOCTL = CALDCO_1MHZ;
  221.   BCSCTL2 &= ~(DIVS_3);                     // SMCLK = DCO = 1MHz
  222.   P2DIR=0xFF;
  223.   P2OUT=0xFF;
  224. }

  225. //显示功能标识函数
  226. void display1(int KeyBuff)
  227. {
  228.         if(KeyBuff>=1&&KeyBuff<=8)
  229.         {
  230.         if (KeyBuff==1)
  231.         {
  232.                         Ht1621Tab[14]=0;
  233.                         Ht1621Tab[15]=0;
  234.                         Ht1621Tab[15]=0x40;
  235.         }
  236.         else if(KeyBuff==2)
  237.         {
  238.                 Ht1621Tab[15]=0;
  239.                 Ht1621Tab[14]=0;
  240.                 Ht1621Tab[15]=0x04;
  241.         }
  242.         else if(KeyBuff==3)
  243.         {
  244.                 Ht1621Tab[14]=0;
  245.                 Ht1621Tab[15]=0;
  246.                 Ht1621Tab[15]=0x80;
  247.         }
  248.         else if(KeyBuff==4)
  249.         {
  250.                 Ht1621Tab[14]=0;
  251.                 Ht1621Tab[15]=0;
  252.                 Ht1621Tab[15]=0x08;
  253.         }

  254.         else if(KeyBuff==5)
  255.         {
  256.                 Ht1621Tab[14]=0;
  257.                 Ht1621Tab[15]=0;
  258.                 Ht1621Tab[14]=0x40;
  259.         }
  260.         else if(KeyBuff==6)
  261.         {
  262.                 Ht1621Tab[14]=0;
  263.                 Ht1621Tab[15]=0;
  264.                 Ht1621Tab[14]=0x04;
  265.         }
  266.         else if(KeyBuff==7)
  267.         {
  268.                 Ht1621Tab[14]=0;
  269.                 Ht1621Tab[15]=0;
  270.                 Ht1621Tab[14]=0x80;
  271.         }
  272.         else if(KeyBuff==8)
  273.         {
  274.                 Ht1621Tab[14]=0;
  275.                 Ht1621Tab[15]=0;
  276.                 Ht1621Tab[14]=0x08;
  277.         }
  278.         }
  279. }

  280. //显示字符函数
  281. void display()
  282. {
  283.           volatile long unsigned int i;
  284.           uint qian,bai,shi,ge,count;

  285.      count=4523;//扩大1000倍

  286.                 qian=count/1000;
  287.                 bai=count%1000/100;
  288.                 shi=count%100/10;
  289.                 ge=count%10;
  290.                 i++;
  291.                 if(i >=100 )
  292.                 {
  293.                         i = 0;
  294.                         Ht1621WrAllData(0,Ht1621Tab,16);//清除1621寄存器数据,暨清屏


  295.                 //第一位数码管
  296.                   Ht1621Tab[6]=SEG_7[qian][0];
  297.                   Ht1621Tab[7]=SEG_7[qian][1]|0x04;
  298. //                  Ht1621Tab[7]=0x04;
  299.                   //第二位数码管
  300.                   Ht1621Tab[8]=SEG_7[bai][0];
  301.                   Ht1621Tab[9]=SEG_7[bai][1];
  302.                   //第三位数码管
  303.                   Ht1621Tab[10]=SEG_7[shi][0];
  304.                   Ht1621Tab[11]=SEG_7[shi][1];
  305.                   //第四位数码管
  306.                   Ht1621Tab[12]=SEG_7[ge][0];
  307.                   Ht1621Tab[13]=SEG_7[ge][1];

  308.                   Ht1621WrAllData(0,Ht1621Tab,16);//清除1621寄存器数据,暨清屏
  309.                 }
  310. }


  311. void main()
  312. {  WDTCTL = WDTPW + WDTHOLD;
  313.    int lki=0;
  314.   //主系统时钟切换为外部高速晶振

  315.   // Configure Basic Clock
  316.   BCSCTL1 = CALBC1_8MHZ;     // Set range
  317.   DCOCTL = CALDCO_8MHZ;    // Set DCO step + modulation*/

  318. //  P2SEL=0x00;//P2为I/O模式
  319. //  P2DIR|=0xff;//P2为LCD输出
  320.   P1SEL|=BIT1+BIT0;//P1.0和P1.1设置为ADC功能A1和A2

  321.                 ADC10CTL1|=CONSEQ_3+INCH_1;//序列通道多次转换+最大通道为A2
  322.                 ADC10CTL0|=SREF_0+ADC10SHT_2+MSC+ADC10ON+ADC10IE;

  323.                 Initial();      //初始化子程序
  324.                 Ht1621_Init();          //上电初始化LCD

  325.                 P1DIR |= 0x1c; //P1方向,低位输出,高位输入
  326.                 P1REN |= 0xe0; //开启P1输入端电阻

  327.                 timer_init();

  328. //                __delay_cycles(100);  //防抖延时,不知道该插到哪里
  329.                 lki++;
  330.                 if(lki>=100)
  331.                 {
  332.                         lki=0;
  333.                 _BIS_SR(GIE);              //开总中断
  334.                 }

  335.   for(;;)
  336. {


  337.         ScanKey();  //扫描按键

  338.         display1(KeyBuff);

  339.     display();//lcd显示
  340. }
  341. }

  342. #pragma vector=ADC10_VECTOR
  343. __interrupt void ADC(void)
  344. {
  345.      LPM0_EXIT;//退出低功耗模式
  346. }

  347. //--------定时器中断函数------------
  348. #pragma vector=TIMER0_A0_VECTOR
  349. __interrupt void Timer_A(void)
  350. {
  351. //            int hj=0;

  352.                 ADC10DTC1|=0x02;//一共采样8次
  353.                 ADC10AE0|=BIT0+BIT1;//+BIT3;//打开A0和A1的模拟输入通道
  354.                 ADC10CTL0 |=ENC+ADC10SC;//启动ADC
  355.                 ADC10SA=(unsigned int)a;//获取a[]的首地址。首先对A1、A0采样,放入a[0]和a[1]中。再对A1、A0采样,放入a[2]和a[3]中,如此循环下去。
  356.                 _BIS_SR(LPM0_bits+GIE);//低功耗模式0,开中断

  357.                 anf(a[1]);

  358.          hj++;
  359.          if(hj>=20)
  360.          {hj=0;}
  361. //锁相功能相关
  362.                 UI[hj]=a[1];
  363.     TACCTL0&=~ CCIE; //关中断
  364. }
复制代码 此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
7条回答
追梦人weijian
1楼-- · 2019-03-24 18:29
 精彩回答 2  元偷偷看……
music_586
2楼-- · 2019-03-24 23:11
< :TI_MSP430_内容页_SA7 --> 那就想办法有没有简易的算法;
lcofjp
3楼-- · 2019-03-25 02:01
20us算一堆浮点数思则运算,能算完就相当不错了。
推荐你换一个MCU吧。
zca123
4楼-- · 2019-03-25 04:56
 精彩回答 2  元偷偷看……
zca123
5楼-- · 2019-03-25 09:27
1.内存不够,建立80以上的数组就提示空间不够,2.进中断后还没算完锁相运算就要要进入下一次中断了,

1、看你要建什么类型的变量,自己算一下需要多大的空间,2553有多大的RAM,要是超了,那没办法,换MCU。如果够,那把那么多全局变量改改。看看生成的链接文件具体的RAM分配情况,配置更高的优化等级。

2、你在中断里,再促发ADC进行一系列的采样,你可以算一下20us的时间有多少个指令周期,再算一下这么多次采样和采样率需要的时间。是否已经超20μS。还有多少余量,这样的安排是否合理。提高主频是否可以。算法是否可以优化。
armcu
6楼-- · 2019-03-25 14:59
根据你这两个问题,430G系列的是满足不了你的需求的。20us要采样还要运算,首先ADC的采样速度要快,最好1M以上,另外你的算法中有乘除法还是浮点数,普通MCU应该也满足不了。最好找个带FPU的最少带硬件乘法器的MCU。还是换成一个32bit的MCU吧

一周热门 更多>

相关问题

    相关文章