用msp430g2553做一个电能检测装置,20us进一次中断,在中断里面进行采样和ANF锁相算法的运算,现在出现了两个问题解决不了,1.内存不够,建立80以上的数组就提示空间不够,2.进中断后还没算完锁相运算就要要进入下一次中断了,由于终端算法必须要在一个周期内取多个点,所以中断时间不能加大,请问大神有什么解决方案吗?help!!!!!!!!!
- #include "msp430g2553.h"
- #define uint unsigned int
- #define uchar unsigned char
- #define NOP() __no_operation() //本句很重要是关于NOP在430里好不好用的问题
- #define HT1621_CS BIT3; //LCD 引脚定义
- #define HT1621_WR BIT4;
- #define HT1621_DAT BIT5;
- #define BIAS 0x52 //0b1000 0101 0010 1/3duty 4com
- #define SYSDIS 0X00 //0b1000 0000 0000 关振系统荡器和LCD偏压发生器
- #define SYSEN 0X02 //0b1000 0000 0010 打开系统振荡器
- #define LCDOFF 0X04 //0b1000 0000 0100 关LCD偏压
- #define LCDON 0X06 //0b1000 0000 0110 打开LCD偏压
- #define XTAL 0x28 //0b1000 0010 1000 外部接时钟
- #define RC256 0X30 //0b1000 0011 0000 内部时钟
- #define TONEON 0X12 //0b1000 0001 0010 打开声音输出
- #define TONEOFF 0X10 //0b1000 0001 0000 关闭声音输出
- #define WDTDIS1 0X0A //0b1000 0000 1010 禁止看门狗
- //ANF全局变量定义
- float sinevalue=0.0;
- float w=314.1593;
- float dc=0.0;
- float jibo=0.0;
- float jiboquad=0.0;
- float q=0.0;
- float sinesum=0.0;
- float f=50.0;
- float e=0.0; //ANF锁相中变所需
- float a1=0.0;
- float a2=0.0;
- float tim=0.0002;
- float shuju;
- uint a[2],UI[20];
- uint i,j,ad1,ad0,x;
- const unsigned char Row[]={0x04,0x08,0x10}; //行为高电平扫描
- const unsigned char Col[]={0x20,0x40,0x80}; //列检测高电平
- volatile unsigned short KeyBuff = 0; //定义为char的话存储的不是数值,不知为何
- volatile unsigned int temp1,t; //全局定义会不会对内存有优化,而不是每次调用函数都重新定义
- void display1(int KeyBuff);
- uchar Ht1621Tab[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//32个地址缓冲区
- uchar SEG_7[10][2]=
- {
- 0xc4,0xc8,//00
- 0x04,0x40,//01
- 0x4c,0x88,//02
- 0x4c,0x48,//03
- 0x8c,0x40,//04
- 0xc8,0x48,//05
- 0xc8,0xc8,//06
- 0x44,0x40,//07
- 0xcc,0xc8,//08
- 0xcc,0x48,//09
- };// 定义0-9数字的二维数组
- //ANF算法程序
- void anf(float shuju)
- {
- sinevalue =(shuju-512)*0.0007326*300;
- e=sinevalue-sinesum;
- dc = dc + e* 65 * tim;
- a1=w * q;
- a2= w * e;
- jibo = jibo+tim* (1.2*a2-w*a1);
- q=q+tim*jibo;
- jiboquad=-w *q;
- sinesum= dc + jibo;
- w=w-a2*q*0.1*tim;
- f=w* 0.159155;
- }
- //定时器中断初始化函数
- void timer_init()
- {
- TACCR0 =200; //计到2500,约100s
- TACTL = TASSEL_2+MC_1+TACLR; //设置TIMERA的时钟源为SMCLK(1M),8分频后(125K),计数模式为up,到CCR0再自动从0开始计数
- TACCTL0 |= CCIE; // CCR0 interrupt enabled
- }
- //键盘扫描函数
- void ScanKey()
- {
- //KeyBuff = 0;
- for(i=0;i<3;i++) //行扫描
- {
- x++;
- P1OUT = Row[i]; //行依次为高电平
- // __delay_cycles(1000); //防抖延时,不知道该插到哪里
- if(x>10)
- {
- x=0;
- temp1 = P1IN & 0xe0; //只取列的数据,PxOUT会影响PxIN的数据
- for(j=0;j<3;j++) //扫描列
- {
- if(temp1 == Col[j]) //判断按键取值为那一列对应的值
- {
- KeyBuff =i*3+j+1; //计算该按键对应的数值
- }
- }
- }
- }
- }
- //延时函数
- //void Delay(uchar us) //5,7,9
- //{
- // while(--us);
- //}
- ////-----------------------------------------------------------------------------------------
- ////函数名称:DelayMS()
- ////功 能:延时子程序
- ////-----------------------------------------------------------------------------------------
- //void DelayMS(uint iMs)
- //{
- // uint i,j;
- // NOP();
- // for(i=0;i<iMs;i++)
- // for(j=0;j<65;j++)
- // {
- // Delay(1);
- // }
- //}
- //-----------------------------------------------------------------------------------------
- //函数名称:Ht1621Wr_Data()
- //功 能:写数据函数,cnt为传送数据位数,数据传送为低位在前
- //-----------------------------------------------------------------------------------------
- //LCD屏写数据函数
- void Ht1621Wr_Data(uchar Data,uchar cnt)
- {
- uchar i;
- for (i=0;i<cnt;i++)
- {
- P2OUT &= ~HT1621_WR;
- NOP();
- NOP();
- NOP();
- if((Data & 0x80)==0x80)
- {
- P2OUT |=HT1621_DAT;
- }
- else
- {
- P2OUT &=~HT1621_DAT;
- }
- P2OUT |=HT1621_WR;
- NOP();
- NOP();
- NOP();
- Data<<=1;
- }
- }
- //-----------------------------------------------------------------------------------------
- //函数名称:void Ht1621WrCmd(uchar Cmd)
- //功能描述: HT1621命令写入函数
- //参数说明:Cmd为写入命令数据
- //说 明:写入命令标识位100
- //-----------------------------------------------------------------------------------------
- void Ht1621WrCmd(uchar Cmd)
- {
- P2OUT&=~HT1621_CS;
- NOP();
- NOP();
- NOP();
- Ht1621Wr_Data(0x80,4); //写入命令标志100
- Ht1621Wr_Data(Cmd,8); //写入命令数据
- P2OUT |= HT1621_CS;
- NOP();
- NOP();
- NOP();
- }
- //-----------------------------------------------------------------------------------------
- //函数名称:void Ht1621WrAllData()
- //功能描述: HT1621连续写入方式函数
- //说 明:HT1621的数据位4位,此处每次数据为8位,写入数据总数按8位计算
- //-----------------------------------------------------------------------------------------
- void Ht1621WrAllData(uchar Addr,uchar *p,uchar cnt)
- {
- uchar i;
- P2OUT &=~HT1621_CS;
- Ht1621Wr_Data(0xa0,3); //写入数据标志101
- Ht1621Wr_Data(Addr<<2,6); //写入地址数据
- for (i=0;i<cnt;i++)
- {
- Ht1621Wr_Data(*p,8); //写入数据
- p++;
- }
- P2OUT |=HT1621_CS;
- NOP();
- NOP();
- NOP();
- }
- //-----------------------------------------------------------------------------------------
- //函数名称:void Ht1621_Init(void)
- //功能描述: HT1621初始化
- //说 明:初始化后,液晶屏所有字段均显示
- //-----------------------------------------------------------------------------------------
- void Ht1621_Init(void)
- {
- int lk=0;
- lk++;
- P2OUT |=HT1621_CS;
- NOP();
- P2OUT |=HT1621_WR;
- NOP();
- P2OUT |=HT1621_DAT;
- NOP();
- if(lk>=2000)
- {
- // DelayMS(2000); //延时使LCD工作电压稳定
- Ht1621WrCmd(BIAS);
- Ht1621WrCmd(RC256); //使用内部振荡器
- Ht1621WrCmd(SYSDIS);
- Ht1621WrCmd(WDTDIS1);
- Ht1621WrCmd(SYSEN);
- Ht1621WrCmd(LCDON);
- }
- }
- //-----------------------------------------------------------------------------------------
- //函数名称:Initial()
- //功 能:初始化子程序
- //-----------------------------------------------------------------------------------------
- void Initial(void)
- {
- WDTCTL = WDTPW + WDTHOLD;//关闭看门狗
- BCSCTL1 = CALBC1_1MHZ; // Set range
- DCOCTL = CALDCO_1MHZ;
- BCSCTL2 &= ~(DIVS_3); // SMCLK = DCO = 1MHz
- P2DIR=0xFF;
- P2OUT=0xFF;
- }
- //显示功能标识函数
- void display1(int KeyBuff)
- {
- if(KeyBuff>=1&&KeyBuff<=8)
- {
- if (KeyBuff==1)
- {
- Ht1621Tab[14]=0;
- Ht1621Tab[15]=0;
- Ht1621Tab[15]=0x40;
- }
- else if(KeyBuff==2)
- {
- Ht1621Tab[15]=0;
- Ht1621Tab[14]=0;
- Ht1621Tab[15]=0x04;
- }
- else if(KeyBuff==3)
- {
- Ht1621Tab[14]=0;
- Ht1621Tab[15]=0;
- Ht1621Tab[15]=0x80;
- }
- else if(KeyBuff==4)
- {
- Ht1621Tab[14]=0;
- Ht1621Tab[15]=0;
- Ht1621Tab[15]=0x08;
- }
- else if(KeyBuff==5)
- {
- Ht1621Tab[14]=0;
- Ht1621Tab[15]=0;
- Ht1621Tab[14]=0x40;
- }
- else if(KeyBuff==6)
- {
- Ht1621Tab[14]=0;
- Ht1621Tab[15]=0;
- Ht1621Tab[14]=0x04;
- }
- else if(KeyBuff==7)
- {
- Ht1621Tab[14]=0;
- Ht1621Tab[15]=0;
- Ht1621Tab[14]=0x80;
- }
- else if(KeyBuff==8)
- {
- Ht1621Tab[14]=0;
- Ht1621Tab[15]=0;
- Ht1621Tab[14]=0x08;
- }
- }
- }
- //显示字符函数
- void display()
- {
- volatile long unsigned int i;
- uint qian,bai,shi,ge,count;
- count=4523;//扩大1000倍
- qian=count/1000;
- bai=count%1000/100;
- shi=count%100/10;
- ge=count%10;
- i++;
- if(i >=100 )
- {
- i = 0;
- Ht1621WrAllData(0,Ht1621Tab,16);//清除1621寄存器数据,暨清屏
- //第一位数码管
- Ht1621Tab[6]=SEG_7[qian][0];
- Ht1621Tab[7]=SEG_7[qian][1]|0x04;
- // Ht1621Tab[7]=0x04;
- //第二位数码管
- Ht1621Tab[8]=SEG_7[bai][0];
- Ht1621Tab[9]=SEG_7[bai][1];
- //第三位数码管
- Ht1621Tab[10]=SEG_7[shi][0];
- Ht1621Tab[11]=SEG_7[shi][1];
- //第四位数码管
- Ht1621Tab[12]=SEG_7[ge][0];
- Ht1621Tab[13]=SEG_7[ge][1];
- Ht1621WrAllData(0,Ht1621Tab,16);//清除1621寄存器数据,暨清屏
- }
- }
- void main()
- { WDTCTL = WDTPW + WDTHOLD;
- int lki=0;
- //主系统时钟切换为外部高速晶振
- // Configure Basic Clock
- BCSCTL1 = CALBC1_8MHZ; // Set range
- DCOCTL = CALDCO_8MHZ; // Set DCO step + modulation*/
- // P2SEL=0x00;//P2为I/O模式
- // P2DIR|=0xff;//P2为LCD输出
- P1SEL|=BIT1+BIT0;//P1.0和P1.1设置为ADC功能A1和A2
- ADC10CTL1|=CONSEQ_3+INCH_1;//序列通道多次转换+最大通道为A2
- ADC10CTL0|=SREF_0+ADC10SHT_2+MSC+ADC10ON+ADC10IE;
- Initial(); //初始化子程序
- Ht1621_Init(); //上电初始化LCD
- P1DIR |= 0x1c; //P1方向,低位输出,高位输入
- P1REN |= 0xe0; //开启P1输入端电阻
- timer_init();
- // __delay_cycles(100); //防抖延时,不知道该插到哪里
- lki++;
- if(lki>=100)
- {
- lki=0;
- _BIS_SR(GIE); //开总中断
- }
- for(;;)
- {
- ScanKey(); //扫描按键
- display1(KeyBuff);
- display();//lcd显示
- }
- }
- #pragma vector=ADC10_VECTOR
- __interrupt void ADC(void)
- {
- LPM0_EXIT;//退出低功耗模式
- }
- //--------定时器中断函数------------
- #pragma vector=TIMER0_A0_VECTOR
- __interrupt void Timer_A(void)
- {
- // int hj=0;
- ADC10DTC1|=0x02;//一共采样8次
- ADC10AE0|=BIT0+BIT1;//+BIT3;//打开A0和A1的模拟输入通道
- ADC10CTL0 |=ENC+ADC10SC;//启动ADC
- ADC10SA=(unsigned int)a;//获取a[]的首地址。首先对A1、A0采样,放入a[0]和a[1]中。再对A1、A0采样,放入a[2]和a[3]中,如此循环下去。
- _BIS_SR(LPM0_bits+GIE);//低功耗模式0,开中断
- anf(a[1]);
- hj++;
- if(hj>=20)
- {hj=0;}
- //锁相功能相关
- UI[hj]=a[1];
- TACCTL0&=~ CCIE; //关中断
- }
复制代码
此帖出自
小平头技术问答
推荐你换一个MCU吧。
1、看你要建什么类型的变量,自己算一下需要多大的空间,2553有多大的RAM,要是超了,那没办法,换MCU。如果够,那把那么多全局变量改改。看看生成的链接文件具体的RAM分配情况,配置更高的优化等级。
2、你在中断里,再促发ADC进行一系列的采样,你可以算一下20us的时间有多少个指令周期,再算一下这么多次采样和采样率需要的时间。是否已经超20μS。还有多少余量,这样的安排是否合理。提高主频是否可以。算法是否可以优化。
一周热门 更多>