?? sa9904_spi_read.c
字號:
#include <msp430x44x.h>
#include <in430.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#define VLD_1_9V (0x10) //1.9V
#define VLD_2_1V (0x20) //2.1V
#define VLD_2_2V (0x30) //2.2V
#define VLD_2_3V (0x40) //2.3V
#define VLD_2_4V (0x50) //2.4V
#define VLD_2_5V (0x60) //2.5V
#define VLD_2_65V (0x70) //2.65V
#define VLD_2_8V (0x80) //2.8V
#define VLD_2_9V (0x90) //2.9V
#define VLD_3_05V (0xa0) //3.05V
#define VLD_3_2V (0xb0) //3.2V
#define VLD_3_35V (0xc0) //3.35V
#define VLD_3_5V (0xd0) //3.5V
#define VLD_3_7V (0xe0) //3.7V
#define SVSOFF (0x0) //VLD=0;
#define POUT BIT4
#define QOUT BIT7
unsigned int Flag_Time=0;//時間標志字.BIT0位作125ms周期標志
unsigned int Flag_State=0;//狀態/事件標志字.BIT0標志有主電源;BIT1標志表示剛上電,將讀取的
//數據直接送Data_SA9904_Up[12];BIT2表示讀SA9904寄存器完成,
//等待處理;
unsigned char F50_Num=0; //F50計數器(每5個F50脈沖啟動一次讀SA9904過程)
unsigned char Spi_Num1=0; //接收每個SA9904寄存器數據時的順序(0-3表示高位到低位)
unsigned char Spi_Num0=0; //SA9904寄存器順序( 0-->11 )
long pl=0; //讀SA9904時數據裝配單元
long Sa9904_N=0;
long Sa9904_NM=0;
long Data_SA9904_Up[12];
long Data_SA9904_Now[12];
static unsigned char P,Q;
void Power_Stste(void);
void Pulse_Compute(void);
void Delay(unsigned int i)
{
for(;i!=0;i--);
}
void main(void)
{
WDTCTL = WDTPW + WDTHOLD;
FLL_CTL0 =XCAP18PF; //配置晶振負載電容
//TA定時器控制
TACTL =MC1 +TASSEL_1; //選擇ACLK時鐘
BTCTL=BT_fLCD_DIV64+BT_ADLY_125;//BASIC Timer1定時器125ms中斷周期
//LCDCTL=LCDON+LCD4MUX+LCDSG0_4;
IE2 |= BTIE;
//TACCTL1 = CCIE+CAP+CM_1;//捕獲方式,允許中斷,異步捕獲,輸入信號源為CCI1A,上升沿捕獲
_EINT();
for(;;)
{
if(Flag_State&BIT0)//有電
{
if(Flag_State&BIT2)//已經讀完
{
if(Flag_State&BIT1)//是上電后首次讀操作
{
unsigned int i;
Flag_State &= ~BIT1;
for(i=0;i<12;i++)
Data_SA9904_Up[i]=Data_SA9904_Now[i];//存底數
}
else
{
//確定5個F50的有功無功速率(兼考慮潛動)
Pulse_Compute();
}
Flag_State &= ~BIT2;//清SPI讀完標志
}
else
{
}
}
if(Flag_Time&BIT0)//每125ms檢測一次電源狀態
{
Power_Stste();
Flag_Time&=~BIT0;
}
_BIS_SR(LPM0_bits);
}
}
//在主程序中檢測電源狀態,負責上電初始化,掉電保存數據等工作
void Power_Stste(void)
{
SVSCTL |= (VLD_3_2V);//判斷是否上電(ATT3221改成3.5V輸出) VLD_3_2V
Delay(20);//延時,等待SVS電路正常工作
if( !(SVSCTL & SVSOP) )//當前有電源!!!
{
if( !(Flag_State&BIT0) )
{
//因為Flag_State的BIT0等于0,表明系統剛上電
SCFQCTL = SCFQ_4M;
FLL_CTL1 &= ~XT2OFF; //啟動XT2高速晶振
do FLL_CTL0 &= ~XT2OF;
while(FLL_CTL0 & XT2OF);
Delay(100);
FLL_CTL0 &= ~XT2OF;
FLL_CTL1 |= SELS;
//POUT,QOUT為輸入方向時滅,輸出方向時亮
P3DIR &= ~POUT;
P2DIR &= ~QOUT;
//增加讀FM24CL16程序(初始化,累計校驗(RAM和24CL16數據))
//...............
//SA9904的CS端為0
P4OUT &= ~BIT2; //SA9904的CS端等于0
P4DIR &= ~BIT4;
P4DIR |= BIT2+BIT3+BIT5;
P4SEL |= BIT3+BIT4+BIT5;
UCTL1 = CHAR+SYNC+MM;//CHAR表示8位模式,SYNC表示當前是SPI模式,MM表示主機模式
UTCTL1 = SSEL1+SSEL0+STC+CKPL;//SMCLK時鐘源+3線模式+下降沿開始發數據
UBR01 = 10;//20K
UBR11 = 0;
UMCTL1 = 0;
//P1.3啟動讀SA9904周期
//P1IES &= ~BIT2;//上升沿觸發中斷11968
//P1IFG &= ~BIT2;
//P1IE |= BIT2;
//系統剛上電后,啟動一次讀SA9904,將讀取的數據存放到
F50_Num=4; //往后第一個F50立即讀數據
Flag_State |= BIT1;//讀得的數據直接送Data_SA9904_Up[12],不需要運算
Sa9904_N=0;
Sa9904_NM=0;
}
else//系統上一次檢測時有電,當前仍然有電
{
}
Flag_State |= BIT0;//有主電源
}
else//系統沒有電源
{
if( !(Flag_State&BIT0) )
{
//因為Flag_State的BIT0等于0,表明系統維持停電狀態
}
else
{
//因為Flag_State的BIT0等于1,表明系統剛停電
//關閉指示燈
P3DIR &= ~POUT;
P2DIR &= ~QOUT;
//增加關閉485的控制端,發送端,紅外發送端,寫累計到24CL16等內容,取消禁止SA9904
//....................
//F50計數清0
P1IE &= ~BIT2;//禁止F50觸發中斷
F50_Num = 0;
Flag_State &= ~BIT1;//禁止讀SA9904
SCFQCTL = SCFQ_512K;
}
Flag_State &= ~BIT0;//沒有主電源
}
SVSCTL = SVSOFF;//關閉電源檢測電路,降低功耗
}
void Spi_Start(void)
{
P4DIR |=BIT2+BIT3+BIT5;
P4SEL |=BIT3+BIT4+BIT5;
IFG2 &= ~(URXIFG1+UTXIFG1);//清接收中斷標志,清發送中斷標志
UTCTL1 = SSEL1+SSEL0+STC+CKPL; // 下降沿開始發數據
P4OUT |= BIT2;
ME2 |= USPIE1;
IE2 |= UTXIE1;//允許發送中斷
U1TXBUF = 0x01;//啟動發送過程,發送高字節地址
}
#pragma vector=PORT1_VECTOR
__interrupt void SPI_START(void)
{
//while( (UTCTL1&TXEPT)==0 );
F50_Num++;
if(F50_Num>4)
{
F50_Num=0;
//Spi_Start();
}
P1IFG &= ~BIT2;//清P1.2中斷標志
}
#pragma vector=BASICTIMER_VECTOR
__interrupt void Clock(void)
{
Flag_Time |=BIT0;
Spi_Start();
_BIC_SR_IRQ(LPM0_bits);
}
#pragma vector=USART1TX_VECTOR
__interrupt void SPI_TXD(void)
{
IFG2 &= ~UTXIFG1;
U1TXBUF = 0x80;
while((UTCTL1&TXEPT)==0);//等待發送完畢
IE2 &= ~UTXIE1;//禁止發送中斷
IFG2 &= ~(URXIFG1+UTXIFG1);
IE2 |= URXIE1;//允許接收中斷
UTCTL1 = SSEL1+SSEL0+STC;//上升沿發數據,下降沿接收數據
ME2 |= USPIE1;
Spi_Num1=0;
Spi_Num0=0;
pl=0;
U1TXBUF = 0; //發送偽數據
}
#pragma vector=USART1RX_VECTOR
__interrupt void SPI_RXD(void)
{
unsigned long x;
x=(unsigned long)U1RXBUF;
pl |= x;
Spi_Num1++;
if(Spi_Num1>=3)
{
Spi_Num1=0;
Data_SA9904_Now[Spi_Num0++]=pl;
pl=0;
if(Spi_Num0>=12)
{
P4OUT &= ~BIT2;
P4DIR &= ~(BIT3+BIT5);
ME2 &= ~USPIE1;
IE2 &= ~URXIE1;
Flag_State |= BIT2;//接收完畢,等待處理
_BIC_SR_IRQ(LPM0_bits);//在主循環處理
}
else
{
U1TXBUF = 0;
}
}
else
{
pl<<=8;
U1TXBUF = 0;
}
}
unsigned char Sa9904_Data_right(void)
{
unsigned int i;
for(i=3;i<12;i=i+4)
{
if(Data_SA9904_Now[i]&0x3fc00)
return 0;
}
return 1;
}
#define Pulse_N 261818 //每脈沖的讀數
void Pulse_Compute(void)
{
unsigned int i;
long x,y=0;
//驗證讀出的數據是否合法
if(Sa9904_Data_right())
{
//有功脈沖計算,計算在一次間隔采樣中總的讀數
for(i=0;i<=8;i=i+4) //3相有功總加
{
x=Data_SA9904_Now[i]-Data_SA9904_Up[i]; //A,B,C相有功
if( (x<0)&&(x<-400000) )
{
x+=0x1000000; //正向
}
else if( (x>0)&&(x>400000) )
{
x=x-0x1000000; //反向
}
y+=x;
Data_SA9904_Up[i]=Data_SA9904_Now[i];
}
if(y<0)
y=-y;
if(y<150)
y=0;
Sa9904_N+=y;
x=Pulse_N-Sa9904_N;
if(x<=0)
{
P=1;
TACCTL1=CCIE+CCIFG;//立即發送脈沖
}
else
{
if( (y!=0)&&(x<=y) )
{
x*=4096/y;
TACCR1=TAR+(unsigned int)x;
P=1;
TACCTL1=CCIE;
}
else
{
//TACCTL1=0;
}
}
//無功計算
for(i=1;i<=9;i=i+4)
{
x=Data_SA9904_Now[i]-Data_SA9904_Up[i];
if( (x<0)&&(x<-400000) )
{
x+=0x1000000;
}
else if( (x>0)&&(x>400000) )
{
x=x-0x1000000;
}
if( (x>400000)||(x<-400000) )
x=0;
y+=x;
}
if(y<0)
y=-y;
if(y<150)
y=0;
Sa9904_NM+=y;
x=Pulse_N-Sa9904_NM;
if(x<=0)
{
Q=1;
TACCTL2=CCIE+CCIFG;//立即發送脈沖
}
else
{
if( (y!=0)&&(x<y) )
{
x*=4096/y;
TACCR2=TAR+(unsigned int)x;
Q=1;
TACCTL2=CCIE;
}
else
{
//TACCTL2=0;
}
}
//脈沖輸出處理結束
}
}
//TA中斷服務函數
#pragma vector=TIMERA1_VECTOR
__interrupt void Timer(void)
{
//_EINT();????????????????????
switch (TAIV)
{
case 2: //CCR1
if( P )
{
TACCR1 =TAR+2950;
P=0;
Sa9904_N-=Pulse_N;
P3DIR |= POUT;
}
else
{
P3DIR &= ~POUT;
TACCTL1 &= ~CCIE;
}
break;
case 4: //CCR2
if( Q )
{
TACCR2 =TAR+2950;
Q=0;
Sa9904_NM-=Pulse_N;
P2DIR |= QOUT;
}
else
{
P2DIR &= ~QOUT;
TACCTL1 &= ~CCIE;
}
break;
case 10: //TA
break; //TA中斷服務程序
default:break;
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -