⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 test.c

📁 用DSPtms2407实现电力系统数据采集的程序
💻 C
字号:
#include   "lf2407regs.h" 
/*------------------------------------------------------------*/
#define  N 32
unsigned int receive[10];     
int rev_num=0;
int rev_length=0;
unsigned int send[76]; 
long signed int v[6]={0,0,0,0,0,0};   
int sent_num=0;     //SCI已发送数目
int send_num=0;     //SCI欲发送数目
unsigned int result1,result2; 
int flag2=0;        
//int i;  
//int j; // ,a=0;
unsigned int period; 

unsigned int eeprom[32];

signed int sample_buffer[6][N*2];    //采样缓冲区

signed int ad_offset[6]={0,0,0,0,0,0};             //六个通道的直流偏移量补偿值

ioport signed int port1234;//ADS8364的IO地址(任意)
#define  AD_addres  port1234
int cmd=0;                   //命令字
int sample_count=0;          //采样周期(N点)计数值

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

void inline DISABLE()
{
   asm(" setc INTM ");
}
void inline ENABLE()
{
   asm(" clrc INTM ");
}
/*------------------------------------------------------------*/
void interrupt nothing()
{
 	return;
}               
/*------------------------------------------------------------*/
void inline DELAY(unsigned int time)
{
unsigned a,b;
	b=0;
	for(a=0;a<=time;a++) b+=1; 
}

/*---------------------------------------------------------------------------*/
void work_begin(void)
{
int a;
	for(a=0;a<6;a++)	v[a]=0;
	
	sample_count=0;
	
	*T1CON=*T1CON | 0x40;	    // 启动Timer1 
	
}
/*---------------------------------------------------------------------------*/
void work_end(void)
{
	*T1CON=*T1CON & 0xFFBF;	    // 禁止Timer1 
}
/*----------------------------SCI程序-------------------------*/ 
void  UARTSENT(int M)          	//发送服务程序
{   
	if(sent_num>M-1) 
	{
		sent_num=0;
		send_num=0;
		work_begin();
		return;
	}         //如果需要发送的字符都已经发送完,则中断直接返回 
	*SCITXBUF=send[sent_num];	          //依次发送定义的字符串中的各个字符
	sent_num++;
}


void  UARTREC()          	    //接收服务程序
{                        
//unsigned int SUM,N,L;
	receive[rev_num]=*SCIRXBUF;  //依次接收字符 
	rev_num++;    
	if (receive[0]!=0x68)
	{
		rev_num=0;
		return;
	} 
	
	if (rev_num==2) 
	{
		rev_length=receive[1];
	}               
 
	if (rev_num==3) 
	{
		cmd=receive[2];
	}
	
	if (rev_num>=rev_length+2)
	{
		rev_num=0;
		rev_length=0;
		return;
	}
}
       

/*----------------------------通讯中断服务程序-------------------------*/ 
interrupt void CAN_SCI() 
{  
unsigned char ch;
	ch=*PIVR;	                //保存现场中断向量 
	*EVAIMRA=*EVAIMRA | 0x80;	// 允许定时器1的周期中断
	ENABLE();
	switch(ch)
	{
		case 6:                 //如果PIVR=6,则发生了接收中断,执行接收服务程序
	    { 
	    	UARTREC(); 
	        *IFR=*IFR | 0x10;	//清除IFR中相应的中断标志 
	        break;
	    }  
		case 7:                 //如果PIVR=7,则发生了发送中断,执行发送服务程序 
		{ 
		    UARTSENT(send_num); 
		    *IFR=*IFR | 0x10;	 //清除IFR中相应的中断标志 
		    break;
		} 
		default:  break;
    } 
	ENABLE();
} 

/*------------------数据传送程序---------------------------------*/

void power_calculate()
{
int b;
	send[0]=0x86;
	send[1]=12;
		send[2]=(int)((v[0]>>5)&0x00ff);
		send[3]=(int)((v[0]>>13)&0x00ff);
		
		send[4]=(int)((v[1]>>5)&0x00ff);
		send[5]=(int)((v[1]>>13)&0x00ff);
		
		send[6]=(int)((v[2]>>5)&0x00ff);
		send[7]=(int)((v[2]>>13)&0x00ff);
		
		send[8]=(int)((v[3]>>5)&0x00ff);
		send[9]=(int)((v[3]>>13)&0x00ff);
		
		send[10]=(int)((v[4]>>5)&0x00ff);
		send[11]=(int)((v[4]>>13)&0x00ff);
		
		send[12]=(int)((v[5]>>5)&0x00ff);
		send[13]=(int)((v[5]>>13)&0x00ff);
		
				
	for(b=0;b<6;b++)	v[b]=0;
	send_num=14;	
	
	UARTSENT(send_num);	
}
interrupt void ADREAD()
{
 unsigned int b;    


	b=AD_addres&0x0007;  
	sample_buffer[b][sample_count]=AD_addres-ad_offset[b];
	b=AD_addres&0x0007;     
	sample_buffer[b][sample_count]=AD_addres-ad_offset[b];
	b=AD_addres&0x0007;     
	sample_buffer[b][sample_count]=AD_addres-ad_offset[b];
	b=AD_addres&0x0007;     
	sample_buffer[b][sample_count]=AD_addres-ad_offset[b];
	b=AD_addres&0x0007;     
	sample_buffer[b][sample_count]=AD_addres-ad_offset[b];
	b=AD_addres&0x0007;
	sample_buffer[b][sample_count]=AD_addres-ad_offset[b]; 
	for(b=0;b<=5;b++)
	{
		v[b]=v[b]+(long)sample_buffer[b][sample_count];
	}
	
	
	sample_count++;
	if(sample_count>(N-1))
	{	
		sample_count=0;
		cmd=11;
		work_end();
	} 
	*EVAIFRA=*EVAIFRA | 0x080;
	ENABLE();
}



/*------------------AD中断服务程序---------------------------------*/
interrupt void ADINT()
{
unsigned int b;    


	b=AD_addres&0x0007;  
	sample_buffer[b][sample_count]=AD_addres-ad_offset[b];
	b=AD_addres&0x0007;     
	sample_buffer[b][sample_count]=AD_addres-ad_offset[b];
	b=AD_addres&0x0007;     
	sample_buffer[b][sample_count]=AD_addres-ad_offset[b];
	b=AD_addres&0x0007;     
	sample_buffer[b][sample_count]=AD_addres-ad_offset[b];
	b=AD_addres&0x0007;     
	sample_buffer[b][sample_count]=AD_addres-ad_offset[b];
	b=AD_addres&0x0007;
	sample_buffer[b][sample_count]=AD_addres-ad_offset[b];
/*	for(a=0;a<6;a++)
	{
	b=AD_addres&0x0007;
	sample_buffer[b*N+sample_count]=AD_addres-ad_offset[b];
	}
	
	b=AD_addres&0x0007;  
	sample_buffer[b]=AD_addres-ad_offset[b];
	b=AD_addres&0x0007;     
	sample_buffer[b]=AD_addres-ad_offset[b];
	b=AD_addres&0x0007;     
	sample_buffer[b]=AD_addres-ad_offset[b];
	b=AD_addres&0x0007;     
	sample_buffer[b]=AD_addres-ad_offset[b];
	b=AD_addres&0x0007;     
	sample_buffer[b]=AD_addres-ad_offset[b];
	b=AD_addres&0x0007;
	sample_buffer[b]=AD_addres-ad_offset[b];*/
	
	for(b=0;b<=5;b++)
	{
		v[b]=v[b]+(long)sample_buffer[b][sample_count];
	}
	
	
	sample_count++;
	if(sample_count>(N-1))
	{	
		sample_count=0;
		cmd=11;
		work_end();
	}
	
	*XINT1CR=*XINT1CR | 0x1000;
	ENABLE();
}

/*------------------------操作EEPROM程序------------------------------*/
int busy()             //查询eeprom状态函数。空闲返回0;忙返回1
{  	
	int iFlag;
	int iCounter;
/*	*PCDATDIR=0x0302;  	//使能eeprom*/
    *PFDATDIR=*PFDATDIR & 0XFFFB;
	*SPIDAT=0x0500;		//发命令字,查询eeprom状态
   	while(((*SPISTS)&0x40)==0);	//判断发送是否完成
   	iCounter=*SPIRXBUF;	        //读取数据,清标志位
	*SPIDAT=0x00;			        //发命令字,回读eeprom状态  
   	while(((*SPISTS)&0x40)==0);	//判断发送是否完成,标志位置1
    *PFDATDIR=*PFDATDIR | 0X0004;
/*	*PCDATDIR=0x0303;		//禁止eeprom*/
	iFlag=*SPIRXBUF;		//取eeprom状态,清标志位
	iFlag=iFlag&0x0001;		//到eeprom状态    
	return iFlag;			//返回eeprom状态值
}   
/*------------------------------------------------------------*/
void eep_write(unsigned int start_add,signed int * data,int num)	
         //eeprom写子程序。start_add为地址;data为写入数据;num为写入个数
{
	int iCounter; 
	int iTemp;
    *SPICCR=0x47;      //复位SPI,8位数据,上升沿发送
    *SPIBRR=0x13;      //波特率2MHz
	*SPICTL=0x06;      //无延时,主模式,允许发送,禁止中断 
	*SPICCR=0xc7;      //脱离复位
   	while(busy()); 			//查询eeprom状态
	*PCDATDIR=0x0302;  	//使能eeprom
	*SPIDAT=0x0600;  		    //发命令字,打开eeprom写保护
   	while(((*SPISTS)&0x40)==0);	//判断发送是否完成,标志位置1
   	iTemp=*SPIRXBUF;	 	    //读取数据,清标志位
	*PCDATDIR=0x0303;		//禁止eeprom
 	while(busy()); 			//查询eeprom状态
   	*PCDATDIR=0x0302;  		//使能eeprom
 	*SPIDAT=0x0200; 		//发命令字,进行eeprom写操作
   	while(((*SPISTS)&0x40)==0);	//判断发送是否完成,标志位置1
   	iTemp=*SPIRXBUF;		    //读取数据,清标志位
	*SPIDAT=start_add;		        //发起始地址数值高8位 
	while(((*SPISTS)&0x40)==0);	//判断发送是否完成,标志位置1
   	iTemp=*SPIRXBUF;		//读取数据,清标志位
	*SPIDAT=start_add<<8;		//发起始地址数值低8位
	while(((*SPISTS)&0x40)==0);	//判断发送是否完成,标志位置1
   	iTemp=*SPIRXBUF;		//读取数据,清标志位
	for(iCounter=0;iCounter<num;iCounter++)  //发送数据
	{	
    	*SPIDAT=data[iCounter]<<8;
    	while(((*SPISTS)&0x40)==0);
       	iTemp=*SPIRXBUF;
	}
	*PCDATDIR=0x0303;  		              //禁止eeprom
}
/*------------------------------------------------------------*/
void eep_read(unsigned int start_add,signed int *data, int num) 
                             //eeprom读操作子程序
{   
	int iCounter;
	int iTemp;     
    *SPICCR=0x47;      //复位SPI,8位数据,上升沿发送
	*SPICTL=0x06;      //无延时,主模式,允许发送,禁止中断
    *SPIBRR=0x13;      //波特率2MHz
	*SPICCR=0xc7;      //脱离复位
	while(busy());			    //查询eeprom状态
    *PFDATDIR=*PFDATDIR & 0XFFFB;
/*	*PCDATDIR=0x0302;   		//使能eeprom */
	*SPIDAT=0x0300;			    //发命令字,进行eeprom读操作
	while(((*SPISTS)&0x40)==0);	//判断发送是否完成,标志位置1
   	iTemp=*SPIRXBUF;		//读取数据,清标志位
   	*SPIDAT=start_add; 		//发起始地址数值高8位
	while(((*SPISTS)&0x40)==0);	//判断发送是否完成,标志位置1	
   	iTemp=*SPIRXBUF;		//读取数据,清标志位
	*SPIDAT=start_add<<8;		//发起始地址数值低8位
	while(((*SPISTS)&0x40)==0);	//判断发送是否完成,标志位置1
   	iTemp=*SPIRXBUF;		//读取数据,清标志位  
	for(iCounter=0;iCounter<=num;iCounter++)   	//读取数据
	{       
		*SPIDAT=0x0000;		 
		while(((*SPISTS)&0x40)==0);
		data[iCounter]=(*SPIRXBUF) & 0xff;
	}
    *PFDATDIR=*PFDATDIR | 0X0004;
/*	*PCDATDIR=0x0303;  		    //禁止eeprom*/
}


/*----------------------计算模拟通道零点偏移量---------------------------------*/
void calculate_offset(void)
{
unsigned int a,b;
long int c;
	for(a=0;a<6;a++)
	{
		c=0;
		for(b=0;b<N;b++)
		{
			c+=(long)sample_buffer[a][b];
		}
		ad_offset[a]=(int)(c>>5);
	}
//	eep_write(0,ad_offset,6);
}
/*----------------------------------------------------*/
void send_ok()
{
	send[0]=79;
	send[1]=75;
	send_num=2;
	UARTSENT(send_num);
}



/**************************************************************/
void main()
{
int x;
	 
    DISABLE();  
    asm(" setc SXM ");
    asm(" clrc OVM ");  
    asm(" clrc CNF ");
    WSGR=0xFE40;           //设置IO空间访问插入7个延时
    *SCSR1=0x006d;         //4倍CLOCK 使能ADC,SPI,CAN,EVA,EVB的时钟
    *WDCR=0x00E8;          //禁止看门狗
    *MCRA=0x1017;          //配置端口
    *MCRB=0xFE3C;
    *MCRC=0x0c00;
    *PADATDIR=0xE000;
    *PBDATDIR=0xFFff;
    *PCDATDIR=0x0303;
    *PEDATDIR=0x8080;
    *PFDATDIR=0x3F0F; 
    *XINT1CR=0x8005;        //上升沿中断
/*----------------------SCI初始化-----------------------*/
    *SCICCR=0x07;           //1个停止位,不校验,空闲线多处理器模式,8位字符 
                        
    *SCICTL1=0x13;          //使能接收和发送,SLEEP=0,禁止休眠方式
                            //禁止接收错误中断,TXWAKE=0,即没有选定的发送特征
    *SCICTL2=0x03;     	    //使能接收和发送中断 
    *SCIHBAUD=0x02;
    *SCILBAUD=0x08;    	    //波特率=9600B/S
    *SCIPRI=0x60;        	//SCI中断(接收和发送中断)为低优先级中断
    *SCICTL1=*SCICTL1 | 0x20;   //使SCI脱离复位状态 
/*----------------------TIMER1初始化-----------------------  */
	*T1CON=0x1006;			    // Timer1为连续增计数模式,预分频值为1,
	                            //使用内部时钟,计数值为0或等于周期值重载,使能比较
	*GPTCONA=*GPTCONA|0x42;
	*T1PR=0x61a6;			    // Timer1的周期寄存器的值根据312.5us延时和预分频值确定
	*T1CMP=0x3000;              // Timer1的比较寄存器的值
	*T1CNT=0x00;				// Timer1的计数器清零
    *EVAIFRA=*EVAIFRA | 0x80;	// 清除定时器1周期中断标志
 	*EVAIMRA=*EVAIMRA | 0x80;	// 允许定时器1的周期中断
	*T1CON=*T1CON | 0x40;	    // 启动Timer1    

/*----------------------TIMER1初始化-----------------------
	*T3CON=0x1006;			    // Timer1为连续增计数模式,预分频值为1,
	                            //使用内部时钟,计数值为0或等于周期值重载,使能比较
	*GPTCONB=*GPTCONB|0x42;
	*T3PER=0x61a6;			    // Timer1的周期寄存器的值根据312.5us延时和预分频值确定
	*T3CMP=0x3000;              // Timer1的比较寄存器的值
	*T3CNT=0x00;				// Timer1的计数器清零
    *EVAIFRB=*EVAIFRB | 0x80;	// 清除定时器1周期中断标志
//	*EVAIMRB=*EVAIMRB | 0x80;	// 允许定时器1的周期中断
	*T3CON=*T3CON | 0x40;	    // 启动Timer1         */
/*----------------------ADS8364复位清零-------------------*/
	*PCDATDIR=*PCDATDIR & 0xfffd;
	*PCDATDIR=*PCDATDIR | 0x2;
/*-------------------------------------------------------*/
//	eep_read(0,ad_offset,6);
/*-------------------------------------------------------*/	
    *IFR=0xFFFF;      // 清除中断标志
    *IMR=0x0013;      // 允许INT1(xint1),5(COM)中断   
    ENABLE();
/*-------------------------------------------------------*/
    for(;;)
    {
		switch(cmd)
		{
			case 1: cmd=0;work_end();break;
			case 2: cmd=0;work_begin();break;
			case 3: cmd=0;calculate_offset();break;
			case 4: cmd=0;break;            //接收脉冲常数   
//			case 5: cmd=0;active_power=0;break;            //输出有功电量脉冲
//			case 6: cmd=0;active_power=1;break;            //输出无功电量脉冲
//			case 7: cmd=0;*T1PR=period>>2;break; 
//			case 10: cmd=0;power_calculate();break;           //修改电能脉冲频率
			case 11: cmd=0;power_calculate();break;           //计算传送实时值
			case 12: cmd=0;send_ok();break; //用于测试
//			case 13: cmd=0;send_cap();break;//传送捕捉值,用于测试 
			default:break;
		}
	}
}    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -