電感-數(shù)字轉(zhuǎn)換器LDC1314是電子工程人員經(jīng)常會(huì)接觸的芯片,LDC1314是4-通道12位的電感-數(shù)字轉(zhuǎn)換器(LDC),用于解決電感檢測(cè)問題。采用多個(gè)信道和遙感的支持,LDC1314以最低的成本與最小的功耗來獲得電感感測(cè)的性能和可靠性。此類產(chǎn)品使用簡(jiǎn)便,僅需要傳感器頻率處于 1kHz 至 10MHz 的范圍內(nèi)即可開始工作。 由于支持的傳感器頻率范圍 1kHz 至 10MHz 較寬,因此還支持使用非常小的 PCB 線圈,從而進(jìn)一步降低感測(cè)解決方案的成本和尺寸。
ldc1314工作原理
導(dǎo)體在與交變電磁(EM)場(chǎng)接觸時(shí)將引起磁場(chǎng)變化,可以采用傳感器中的電感傳感器進(jìn)行檢測(cè)。一個(gè)電感器與一個(gè)電容器可以構(gòu)造一個(gè)L-C振蕩器,可以用來產(chǎn)生電磁場(chǎng)。在一個(gè)LC振蕩器中,當(dāng)電磁場(chǎng)收到干擾時(shí),可以觀察到電感發(fā)生微小的偏移,與共振頻率存在一定關(guān)系。
利用這個(gè)原理,在LDC1314是一個(gè)電感-數(shù)字轉(zhuǎn)換器(LDC),通過測(cè)量LC諧振器的振蕩頻率。該器件輸出數(shù)字值與振蕩頻率成比例關(guān)系。此頻率測(cè)量值可以被轉(zhuǎn)換為一個(gè)等效電感。
LDC1314特征參數(shù)
*合格的汽車應(yīng)用
*符合AEC-Q100的結(jié)果如下:
-設(shè)備溫度等級(jí)1:- 40°C至125°C環(huán)境工作溫度范圍
-設(shè)備HBM的ESD等級(jí)分類2
-裝置CDM ESD分類等級(jí)C
*易于使用的最低配置要求
*測(cè)量多達(dá)4個(gè)傳感器與一個(gè)集成電路
*多渠道支持環(huán)境和老齡化補(bǔ)償
*多通道遙感提供最低系統(tǒng)成本
*引腳兼容的介質(zhì)和高分辨率選項(xiàng)
-LDC1312-Q1/LDC1314-Q1: 2/4-ch 12-bit LDC
-LDC1612-Q1/LDC1614-Q1: 2/4-ch 28-bit LDC
*支持廣泛的傳感器頻率范圍10MHz 1KHz
*35μ低功耗的睡眠模式 -200鈉關(guān)斷模式 *3.3V的操作
*支持內(nèi)部或外部參考時(shí)鐘 *對(duì)直流磁場(chǎng)和磁鐵的免疫
ldc1314引腳圖
ldc1314引腳定義
說明:DAP不能做地使用,可以懸空,為獲得最佳性能對(duì)DAP應(yīng)連接到相同的電位作為設(shè)備的GND管腳。
典型ldc1314應(yīng)用電路一:
典型ldc1314應(yīng)用電路二:
系統(tǒng)以MSP430F169單片機(jī)為控制核心,采用可充電鋰電池為電源,以L298N為驅(qū)動(dòng)芯片,結(jié)合PWM技術(shù)實(shí)現(xiàn)對(duì)4個(gè)直流減速機(jī)速度控制,從而實(shí)現(xiàn)小車的前進(jìn)、轉(zhuǎn)向等功能。在本系統(tǒng)中,單片機(jī)通過LDC1314芯片實(shí)現(xiàn)對(duì)賽道表面金屬絲和硬幣的識(shí)別與小車位置的判定,利用電機(jī)尾部的霍爾傳感器與編碼器實(shí)現(xiàn)對(duì)小車行進(jìn)路程的計(jì)算,并使用LCD12864液晶實(shí)時(shí)顯示小車行進(jìn)路程與所用時(shí)間。
電機(jī)驅(qū)動(dòng)芯片L298N原理圖如下
主程序
void main( void )
{
P2SEL &=~ BIT7; //蜂鳴器
P2DIR |= BIT7;
P2OUT &=~ BIT7;
InitSys();
InitLDC1314();
Ini_Lcd();
P6SEL=0;P6DIR|=BIT0+BIT1;P6OUT&=~(BIT0+BIT1); //電機(jī)旋轉(zhuǎn)方向
_EINT();
int i;
InitPWM(0x03E8); //PWM初始化,采用TB輸出2路PWM波
TBCCR1=TBCCR2=0;
for(i=0;i《1500;i++) // 電感傳感器自校準(zhǔn)
{
D1=LDC1314_Result(1);
D2=LDC1314_Result(2);
D3=LDC1314_Result(3);
}
initTA(); // 定時(shí)器A初始化,用于計(jì)時(shí)
go(); //直行
Time=mc=sx=0; //開始執(zhí)行 時(shí)間路程清零
while(1)
{
Component_Display(4,0,Time);//時(shí)間
sl=(int)((float)sx*3.0);
Component_Display(4,4,sl); //路程
if(sl》800){while(1);_DINT();TBCCR1=TBCCR2=0;} //到達(dá)終點(diǎn) 結(jié)束
value1 = LDC1314_Result(1); Component_Display(1,1,value1);//顯示通道1
value2 = LDC1314_Result(2); Component_Display(2,1,value2);
value3 = LDC1314_Result(3); Component_Display(3,1,value3);//顯示
// 硬幣的檢測(cè)
if ((value1》(2+D1))|| (value2》(2+D2))|| (value3》(2+D3)) || (abs(value2-D2)》20)|| (abs(value1-D1)》20)|| (abs(value3-D3)》20))
P2OUT |=BIT7;
else
P2OUT &=~BIT7;
//循跡
if((abs(value3-D3)《20)&&(D3》value3)) { turn_r(); }
else if((abs(value1-D1)《20)&&(D1》value1)) { turn_l(); }
else go();
}
}
ldc1314例程
ldc1314例程一:
MSP430F149/169驅(qū)動(dòng)LDC1314程序,可用于金屬的檢測(cè),已給出各個(gè)文件名稱,自建工程添加文件即可使用。顯示程序較為普遍,未給出。
MAIN.C文件
#include 《msp430f169.h》
#include “config.h”
#include “12864.h”
extern uint LDC1314_Result(uchar Channal);
extern void InitLDC1314(void);
/***************************************************
系統(tǒng)初始化,MCLK=8MHz,SMCLK=1MHz
*************************************************/
void InitSys()
{
unsigned int iq0;
_DINT(); // 關(guān)中斷,本可以不必這樣小心
WDTCTL = WDTPW + WDTHOLD;
BCSCTL1 &=~XT2OFF;
do
{
IFG1 &= ~OFIFG; // 清除振蕩器失效標(biāo)志
for (iq0 = 0xFF; iq0 》 0; iq0--); // 延時(shí),等待XT2起振
}
while ((IFG1 & OFIFG) != 0); // 判斷XT2是否起振
BCSCTL2 =SELM_2+SELS+DIVS_3; //MCLK,SMCLK時(shí)鐘為XT2,SMCLK8分頻1MHz
}
void main( void )
{
uint value = 0;
InitSys();
InitLDC1314();
Ini_Lcd();
Component_Display(4,0,134);//顯示
while(1)
{
value = LDC1314_Result(0);//通道0
Component_Display(1,0,value);//顯示
delay_ms(200);
}
_NOP();
}
LDC1314.C文件
#include “LDC1314.h”
/*I2C總線初始化*/
void I2C_Init()
{
LDC_SCL_L(); //拉低時(shí)鐘線
delay_us(5); //延時(shí)
I2C_Stop();
}
//**************************************
//I2C起始信號(hào)
//**************************************
void I2C_Start()
{
LDC_SCL_OUT(); // SCL設(shè)置為輸出
LDC_SDA_OUT(); // SDA設(shè)置為輸出
LDC_SDA_H(); //拉高數(shù)據(jù)線
LDC_SCL_H(); //拉高時(shí)鐘線
delay_us(5); //延時(shí)
LDC_SDA_L(); //產(chǎn)生下降沿
delay_us(5); //延時(shí)
LDC_SCL_L(); //拉低時(shí)鐘線
}
//**************************************
//I2C停止信號(hào)
//**************************************
void I2C_Stop()
{
LDC_SCL_OUT(); // SCL設(shè)置為輸出
LDC_SDA_OUT(); // SDA設(shè)置為輸出
LDC_SDA_L(); //拉低數(shù)據(jù)線
LDC_SDA_H(); //產(chǎn)生上升沿
delay_us(5); //延時(shí)
}
//**************************************
//I2C發(fā)送應(yīng)答信號(hào)
//入口參數(shù):ack (0:ACK 1:NAK)
//**************************************
void I2C_SendACK(uchar ack)
{
if(ack)
LDC_SDA_H();
else
LDC_SDA_L();
// SDA = ack; //寫應(yīng)答信號(hào)
LDC_SCL_H(); //拉高時(shí)鐘線
delay_us(5); //延時(shí)
LDC_SCL_L(); //拉低時(shí)鐘線
delay_us(5); //延時(shí)
}
//**************************************
//I2C接收應(yīng)答信號(hào),0有效,1無效
//**************************************
uchar I2C_RecvACK()
{
uchar cy;
LDC_SCL_OUT(); // SCL設(shè)置為輸出
LDC_SCL_H(); //拉高時(shí)鐘線
delay_us(5); //延時(shí)
if(LDC_SDA_DAT())
{
cy=1;
}
else
{
cy=0;
}
// cy = SDA; //讀應(yīng)答信號(hào)
LDC_SCL_L(); //拉低時(shí)鐘線
delay_us(5); //延時(shí)
LDC_SDA_OUT(); // SDA設(shè)置為輸出
return cy;
}
/*向I2C總線發(fā)送一個(gè)字節(jié)數(shù)據(jù)*/
uchar I2C_SendByte(uchar dat)
{
uchar i,temp;
LDC_SCL_OUT(); // SCL設(shè)置為輸出
LDC_SDA_OUT(); // SDA設(shè)置為輸出
for (i=0; i《8; i++) //8位計(jì)數(shù)器
{
if((dat《《i))
{
LDC_SDA_H();
}
else
{
LDC_SDA_L();
}
LDC_SCL_H(); //拉高時(shí)鐘線
delay_us(5); //延時(shí)
LDC_SCL_L(); //拉低時(shí)鐘線
delay_us(5); //延時(shí)
}
temp=I2C_RecvACK();
return temp;
}
/*從I2C總線接收一個(gè)字節(jié)數(shù)據(jù)*/
uchar I2C_RecvByte()
{
uchar i;
uchar dat = 0,cy;
LDC_SCL_OUT(); // SCL設(shè)置為輸出
LDC_SDA_OUT(); // SDA設(shè)置為輸出
LDC_SDA_H(); //使能內(nèi)部上拉,準(zhǔn)備讀取數(shù)據(jù),
LDC_SDA_IN(); // SDA設(shè)置為輸入,準(zhǔn)備向主機(jī)輸入數(shù)據(jù)
for (i=0; i《8; i++) //8位計(jì)數(shù)器
{
dat 《《= 1;
LDC_SCL_H(); //拉高時(shí)鐘線
delay_us(5); //延時(shí)
if(LDC_SDA_DAT())
{
cy=1;
}
else
{
cy=0;
}
dat |= cy; //讀數(shù)據(jù)
LDC_SCL_L(); //拉低時(shí)鐘線
delay_us(5); //延時(shí)
}
LDC_SDA_OUT();
return dat;
}
/*向I2C設(shè)備寫入一個(gè)字節(jié)數(shù)據(jù)*/
/*
void ByteWrite1314(uchar REG_Address,uchar REG_data)
{
I2C_Start(); //起始信號(hào)
I2C_SendByte(SlaveAddress); //發(fā)送設(shè)備地址+寫信號(hào)
I2C_SendByte(REG_Address); //內(nèi)部寄存器地址,
I2C_SendByte(REG_data); //內(nèi)部寄存器數(shù)據(jù),
I2C_Stop(); //發(fā)送停止信號(hào)
}
*/
//**************************************
//從I2C設(shè)備讀取一個(gè)字節(jié)數(shù)據(jù)
//**************************************
/*
uchar ByteRead1314(uchar REG_Address)
{
uchar REG_data;
I2C_Start(); //起始信號(hào)
I2C_SendByte(SlaveAddress); //發(fā)送設(shè)備地址+寫信號(hào)
I2C_SendByte(REG_Address); //發(fā)送存儲(chǔ)單元地址,從0開始
I2C_Start(); //起始信號(hào)
I2C_SendByte(SlaveAddress+1); //發(fā)送設(shè)備地址+讀信號(hào)
REG_data=I2C_RecvByte(); //讀出寄存器數(shù)據(jù)
I2C_SendACK(1); //接收應(yīng)答信號(hào)
I2C_Stop(); //停止信號(hào)
return REG_data;
}
*/
//**************************************
//向I2C設(shè)備寫入一個(gè)字?jǐn)?shù)據(jù)
//**************************************
void WordWrite1314(uchar REG_Address,uint REG_data)
{
uchar REG_data_H,REG_data_L;
REG_data_L=(uchar)(REG_data&0xFF);
REG_data_H=(uchar)((REG_data&0xFF00)》》8);
I2C_Start(); //起始信號(hào)
I2C_SendByte(SlaveAddress); //發(fā)送設(shè)備地址+寫信號(hào)
I2C_SendByte(REG_Address); //內(nèi)部寄存器地址
I2C_SendByte(REG_data_H); //發(fā)送內(nèi)部寄存器數(shù)據(jù),高8位
I2C_SendByte(REG_data_L); //發(fā)送內(nèi)部寄存器數(shù)據(jù),低8位
I2C_Stop(); //發(fā)送停止信號(hào)
}
/*從I2C設(shè)備讀取一個(gè)字?jǐn)?shù)據(jù)*/
uint WordRead1314(uchar REG_Address)
{
uint REG_data;
uchar REG_data_H,REG_data_L;
I2C_Start(); //起始信號(hào)
I2C_SendByte(SlaveAddress); //發(fā)送設(shè)備地址+寫信號(hào)
I2C_SendByte(REG_Address); //發(fā)送存儲(chǔ)單元地址,從0開始
I2C_Start(); //起始信號(hào),??原因不明
I2C_SendByte(SlaveAddress+1); //發(fā)送設(shè)備地址+讀信號(hào)
REG_data_H=I2C_RecvByte(); //讀出寄存器數(shù)據(jù)
I2C_SendACK(0); //接收應(yīng)答信號(hào)
REG_data_L=I2C_RecvByte(); //讀出寄存器數(shù)據(jù)
I2C_SendACK(1); //接收應(yīng)答非信號(hào)
I2C_Stop(); //發(fā)送停止信號(hào)
REG_data=REG_data_H;
REG_data《《=8;
REG_data|=REG_data_L;
return REG_data;
}
/*初始化LDC1314*/
void InitLDC1314(void)
{
I2C_Init();
while(WordRead1314(DEVICE_ID)!=0x3025);//等待,I2C正常
//WordWrite1314(RESET_DEV,0x8800);
/*重啟LDC1314*/
WordWrite1314(CONFIG,0x2451);
/*默認(rèn)值,睡眠模式開,方便配置*/
WordWrite1314(CLOCK_DIVIDERS_CH0,0X500a);//fSENSOR不分頻,fCLK 2分頻
/* 時(shí)鐘源分頻選擇,分頻系數(shù)1,1
Using L and C, 得fSENSOR = 1/2π×sqrt(L ×C)
注意fSENSOR須小于8.75 MHz,fSENSOR分頻系數(shù)才能置1
注意fREF0須至少大于 4 × fSENSOR,以決定fREF0分頻系數(shù)
fin0 = fSENSOR0/CH0_FIN_DIVIDER
fREF0 = fCLK / CH0_FREF_DIVIDER
*
WordWrite1314(SETTLECOUNT_CH0,0x0A60);
/* 建立(Settling)時(shí)間設(shè)置
計(jì)算得Q=Rp*sqrt(C/L)
寄存器值小于10取10,大于10取其值,且應(yīng)滿足以下條件:
CHx_SETTLECOUNT ≥ QSENSORx × fREFx / (16 × fSENSORx) (10進(jìn)制)
(1)fSENSORx:x通道傳感器頻率
(2)fREFx:x通道參考頻率
?。?)QSENSORx:品質(zhì)因數(shù),Q=Rp ×sqrt(C/L)
注意,不等式右邊算出有小數(shù)則向上取整
建立時(shí)間tSx = (CH0_SETTLECOUNT*16) / fREF0
通道切換時(shí)間tCsd = Channel Switch Delay = 692 ns + 5 / fref (us)
*/
WordWrite1314(RCOUNT_CH0,0xFFFF);
/*轉(zhuǎn)換時(shí)間設(shè)置
得轉(zhuǎn)換時(shí)間tCx = TSAMPLE(采樣時(shí)間) – tSx – tCsd (us)
由下式算出寄存器的值(有小數(shù)則向下取整(舍去)):
轉(zhuǎn)換時(shí)間tCx = (CHx_RCOUNT × 16) / fREFx (10進(jìn)制)
注意寄存器的值化為16進(jìn)制
*/
/*使用ERROR_CONFIG默認(rèn)值,錯(cuò)誤中斷關(guān)閉*/
WordWrite1314(DRIVE_CURRENT_CH0,0x9800);
/*傳感器驅(qū)動(dòng)電流設(shè)置,使用請(qǐng)同時(shí)注意CONFIG寄存器相關(guān)配置
查數(shù)據(jù)手冊(cè)的Figure 15,得IDRIVE值(10進(jìn)制),INIT_DRIVE值不使用,保持默認(rèn)
使用CH0_IDRIVE[15:11]時(shí),Rp Override須打開
使用CH0_INIT_IDRIVE[10:6]時(shí),保證AUTO_AMP_DIS位不置位
*/
//WordWrite1314(MUX_CONFIG,0x801);
/* 多通道轉(zhuǎn)換選擇,輸入尖峰脈沖濾波器帶寬選擇,使用請(qǐng)同時(shí)注意CONFIG寄存器相關(guān)配置!
?。╝)置AUTOSCAN_EN位為b1使能連續(xù)模式(sequential mode)
?。╞)置RR_SEQUENCE位為b00使能兩個(gè)通道的數(shù)據(jù)轉(zhuǎn)換(channel 0,channel 1)
?。╟)置DEGLITCH位為b100設(shè)定輸入尖峰脈沖濾波器帶寬,此值必須高于諧振頻率fTank!
*/
//WordWrite1314(OFFSET_CH0,0x00);
/*頻率偏移(補(bǔ)償)設(shè)置
可以設(shè)置從每個(gè)數(shù)據(jù)值中減去偏移值,以補(bǔ)償頻率偏移或最大化動(dòng)態(tài)范圍的樣本數(shù)據(jù)
fOFFSET0 = CH0_OFFSET * (fREF0/2^16)
且偏移值應(yīng)小于 fSENSORx_MIN / fREFx
*/
//WordWrite1314(RESET_DEV,0x00);
/*輸出增益設(shè)置,[10:9],對(duì)所有通道有效
對(duì)于傳感器信號(hào)變化量小于滿量程25%的系統(tǒng),設(shè)置輸出增益可以提供更高的分辨率(精度)
*/
/*
狀態(tài)寄存器:STATUS,ERROR_CONFIG
*/
WordWrite1314(CONFIG,0x1501);
/*默認(rèn)連續(xù)轉(zhuǎn)換(單)通道0,睡眠模式關(guān),Rp Override開
低功耗模式關(guān),傳感器自動(dòng)幅度校正(AUTO_AMP)關(guān),Ref時(shí)鐘源選外部時(shí)鐘源
INTB中斷開,高電流驅(qū)動(dòng)關(guān)*/
}
/*讀取LDC1314轉(zhuǎn)換結(jié)果,輸入?yún)?shù)為選擇通道數(shù)*/
uint LDC1314_Result(uchar Channal)
{
uint temp=0;
switch(Channal)
{
case 0x00:
temp=WordRead1314(DATA_CH0); //通道0
break;
case 0x01:
temp=WordRead1314(DATA_CH1); //通道1
break;
case 0x02:
temp=WordRead1314(DATA_CH2); //通道2
break;
case 0x03:
temp=WordRead1314(DATA_CH3); //通道3
break;
default :
break;
}
while((temp&0xF000)!=0);
/*有錯(cuò)誤Flag!,有輸出增益時(shí)注意此句,可能出錯(cuò)!
0x000 = under range,0xfff = over range
*/
return temp;
}
LDC1314.H文件
#ifndef __LDC1314_H
#define __LDC1314_H
#include 《msp430f169.h》
#include “config.h”
static void I2C_Init();
static void I2C_Start();
static void I2C_Stop();
static void I2C_SendACK(uchar ack);
static uchar I2C_RecvACK();
static uchar I2C_SendByte(uchar dat);
static uchar I2C_RecvACK();
static void WordWrite1314(uchar REG_Address,uint REG_data);
static uint WordRead1314(uchar REG_Address);
void InitLDC1314(void);
uint LDC1314_Result(uchar Channal);
//****定義LDC1314硬件接口(不同硬件修改此處即可)***********
#define LDC1314DIR P1DIR
#define LDC1314OUT P1OUT
#define LDC1314IN P1IN
#define LDC_SCL BIT2
#define LDC_SDA BIT3
#define LDC_INTB BIT4//中斷
#define LDC_SD BIT5//置高,則進(jìn)入掉電模式
//*********I2C硬件相關(guān)接口函數(shù)**************
#define LDC_SCL_OUT() LDC1314DIR |= LDC_SCL // SCL腳輸出
#define LDC_SCL_H() LDC1314OUT |= LDC_SCL // SCL拉高
#define LDC_SCL_L() LDC1314OUT &= ~LDC_SCL // SCL拉低
#define LDC_SDA_OUT() LDC1314DIR |= LDC_SDA // SDA腳輸出
#define LDC_SDA_H() LDC1314OUT |= LDC_SDA // SDA拉高
#define LDC_SDA_L() LDC1314OUT &= ~LDC_SDA // SDA拉低
#define LDC_SDA_IN() LDC1314DIR &= ~LDC_SDA // SDA腳輸入
#define LDC_SDA_DAT() (LDC1314IN&LDC_SDA) // SDA輸入數(shù)據(jù)
#define SlaveAddress 0x2A //IIC寫入時(shí)的地址字節(jié)數(shù)據(jù),+1為讀取,ADDR接高電平,地址則為0x2B
#define DATA_CH0 0x00 //Channel 0 Conversion Result and Error Status
#define DATA_CH1 0x02
#define DATA_CH2 0x04
#define DATA_CH3 0x06
#define RCOUNT_CH0 0x08 //Reference Count setting for Channel 0
#define RCOUNT_CH1 0x09
#define RCOUNT_CH2 0x0A
#define RCOUNT_CH3 0x0B
#define OFFSET_CH0 0x0C //Offset value for Channel 0
#define OFFSET_CH1 0x0D
#define OFFSET_CH2 0x0E
#define OFFSET_CH3 0x0F
#define SETTLECOUNT_CH0 0x10 //Channel 0 Settling Reference Count
#define SETTLECOUNT_CH1 0x11
#define SETTLECOUNT_CH2 0x12
#define SETTLECOUNT_CH3 0x13
#define CLOCK_DIVIDERS_CH0 0x14
#define CLOCK_DIVIDERS_CH1 0x15
#define CLOCK_DIVIDERS_CH2 0x16
#define CLOCK_DIVIDERS_CH3 0x17
#define STATUS 0x18 //Device Status Report
#define ERROR_CONFIG 0x19 //Error Reporting Configuration
#define MUX_CONFIG 0x1A //Channel Multiplexing Configuration
#define CONFIG 0x1B //Conversion Configuration
#define RESET_DEV 0x1C //Reset Device
#define DRIVE_CURRENT_CH0 0x1E //Channel 0 sensor current drive configuration
#define DRIVE_CURRENT_CH1 0x1F
#define DRIVE_CURRENT_CH2 0x20
#define DRIVE_CURRENT_CH3 0x21
#define MANUFACTURER_ID 0x7E //廠商ID,默認(rèn)值0x5449
#define DEVICE_ID 0x7F //設(shè)備ID,默認(rèn)值0x3054
#endif
ldc1314例程二:
#include 《intrinsics.h》
#include 《string.h》
#include 《stdint.h》
#include 《cstring》
#include 《stdio.h》
#include “LDC13xx16xx_evm.h”
#include “scheduler.h”
#include “host_interface.h”
#include “host_packet.h”
#include “USB_API/USB_Common/device.h”
#include “USB_API/USB_Common/types.h” //Basic Type declarations
#include “USB_API/USB_Common/usb.h” //USB-specific functions
#include “F5xx_F6xx_Core_Lib/HAL_UCS.h”
#include “F5xx_F6xx_Core_Lib/HAL_PMM.h”
#include “USB_API/USB_CDC_API/UsbCdc.h”
#include “usbConstructs.h”
#include “USB_config/descriptors.h”
// prototypes
void InitMCU(void);
void Init_Clock(void);
void USBCommunicationTask(void);
void LDC16_13_Evm_Test_Routine();
uint16_t L_Noise(uint16_t * t_buf, uint8_t ch_num);
uint8_t L_Sample(uint16_t * t_buf, uint8_t ch_num);
volatile uint8_t bCDCDataReceived_event = FALSE; //Indicates data has been received without an open rcv operation
volatile uint16_t usbEvents = (kUSB_VbusOnEvent + kUSB_VbusOffEvent + kUSB_receiveCompletedEvent
+ kUSB_dataReceivedEvent + kUSB_UsbSuspendEvent + kUSB_UsbResumeEvent +
kUSB_UsbResetEvent);
// used as an edge-trigger for USB connect/disconnect
uint8_t usb_led_flag;
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; //Stop watchdog timer
// hardware bootloader entry
EVM_SHUTDOWN_SEL &= ~EVM_SHUTDOWN_BIT; // gpio
EVM_SHUTDOWN_DIR &= ~EVM_SHUTDOWN_BIT; // input
EVM_SHUTDOWN_REN |= EVM_SHUTDOWN_BIT; // enable pull-down
EVM_SHUTDOWN_OUT &= ~EVM_SHUTDOWN_BIT; // pull low
__delay_cycles(36000);
if (EVM_SHUTDOWN_IN & EVM_SHUTDOWN_BIT) {
_disable_interrupts();
?。ǎ╲oid (*)())0x1000)();
}
EVM_SHUTDOWN_REN &= ~EVM_SHUTDOWN_BIT; // disable pull-down
// InitMCU(); //included in evm init
evm_init();
LDC16_13_Evm_Test_Routine();
_enable_interrupts();
// evm_LED_Set(ALLON);
initHostInterface();
// evm_LED_Set(RED); // red on only
usb_led_flag = 0;
while (1)
{
// USB Comms
USBCommunicationTask();
}
}
/** Initialze MCU
Initializes the MSP430 peripherals and modules.
*/
void InitMCU(void)
{
__disable_interrupt(); // Disable global interrupts
SetVCore(3);
Init_Clock(); //Init clocks
USB_init(); //Init USB
USB_setEnabledEvents((WORD)usbEvents);
//Check if we‘re already physically attached to USB, and if so, connect to it
//This is the same function that gets called automatically when VBUS gets attached.
if (USB_connectionInfo() & kUSB_vbusPresent){
USB_handleVbusOnEvent();
}
__enable_interrupt(); // enable global interrupts
}
/** USB Communication
Handles USB Comms
*/
void USBCommunicationTask(void)
{
uint16_t bytesSent, bytesReceived;
uint8_t error=0, status;
switch (USB_connectionState())
{
case ST_ENUM_ACTIVE:
if (!usb_led_flag) {
// evm_LED_Set(GREEN); // green on only
usb_led_flag = 1;
}
status = USBCDC_intfStatus(CDC0_INTFNUM,&bytesSent, &bytesReceived);
if (status & kUSBCDC_waitingForSend) {
error = 1;
}
if(bCDCDataReceived_event || (status & kUSBCDC_dataWaiting))
{
bCDCDataReceived_event = FALSE;
processCmdPacket ();
}
else {
evm_processDRDY(); // process DRDY added here for speed (not scheduler-assigned)
executeTasks();
}
break;
case ST_USB_DISCONNECTED: case ST_USB_CONNECTED_NO_ENUM:
case ST_ENUM_IN_PROGRESS: case ST_NOENUM_SUSPENDED: case ST_ERROR:
if (usb_led_flag) {
// evm_LED_Set(RED); // red on only
usb_led_flag = 0;
}
removeAllTasks();
break;
default:;
} //end of switch-case sentence
if(error)
{
error = 0;
_nop();
//TO DO: User can place code here to handle error
}
}
/** Initialize Clock
Initializes all clocks: ACLK, MCLK, SMCLK.
*/
void Init_Clock(void)
{
//Initialization of clock module
if (USB_PLL_XT == 2){
#if defined (__MSP430F552x) || defined (__MSP430F550x)
P5SEL |= 0x0C; //enable XT2 pins for F5529
#elif defined (__MSP430F563x_F663x)
P7SEL |= 0x0C;
#endif
#if 0
//use REFO for FLL and ACLK
UCSCTL3 = (UCSCTL3 & ~(SELREF_7)) | (SELREF__REFOCLK);
UCSCTL4 = (UCSCTL4 & ~(SELA_7)) | (SELA__REFOCLK);
//MCLK will be driven by the FLL (not by XT2), referenced to the REFO
Init_FLL_Settle(USB_MCLK_FREQ / 1000, USB_MCLK_FREQ / 32768); //Start the FLL, at the freq indicated by the config
//constant USB_MCLK_FREQ
XT2_Start(XT2DRIVE_0); //Start the “USB crystal”
#endif
// for USB2ANY which has XT2 crytstal = 24MHz
UCSCTL4 = SELA_5 + SELS_5 + SELM_5; // ACLK=XT2 SMCLK=XT2 MCLK=XT2
XT2_Start(XT2DRIVE_3);
}
else {
#if defined (__MSP430F552x) || defined (__MSP430F550x)
P5SEL |= 0x10; //enable XT1 pins
#endif
//Use the REFO oscillator to source the FLL and ACLK
UCSCTL3 = SELREF__REFOCLK;
UCSCTL4 = (UCSCTL4 & ~(SELA_7)) | (SELA__REFOCLK);
//MCLK will be driven by the FLL (not by XT2), referenced to the REFO
Init_FLL_Settle(USB_MCLK_FREQ / 1000, USB_MCLK_FREQ / 32768); //set FLL (DCOCLK)
XT1_Start(XT1DRIVE_0); //Start the “USB crystal”
}
}
// L noise measurement
// take 16 sampling averages of size 1024
// returns noise measurement
uint16_t L_Noise(uint16_t * t_buf, uint8_t ch_num) {
uint8_t i;
uint32_t j,sample,min,max;
uint16_t avg = 0;
// if L noise is out of range after tuning return FALSE
for (i = 0; i 《 4; i++) {
// evm_LED_Set(ALLTOGGLE);
min = 0xFFFFFFFF; //min
max = 0; //max
// measure L noise
for (j = 0; j 《 1024; j++) {
#ifdef SERIES_16
smbus_readWord(0x2A, ch_num, &t_buf[0]);
smbus_readWord(0x2A, ch_num+1, &t_buf[1]);
sample = ((uint32_t) t_buf[1]) | (((uint32_t) t_buf[0]) 《《 16);
#endif
#ifdef SERIES_13
smbus_readWord(0x2A, ch_num, &t_buf[0]);
sample = ((uint32_t) t_buf[0]);
#endif
if (sample 《 min)
min = sample;
if (sample 》 max)
max = sample;
}
if (max 》 min) {
avg += (max - min);
}
else if (min 》 max) {
return 0xFFFF;
}
}
avg /= 4; // should compile to right shift by 4
return avg;
}
// L sample range measurement
// take 64 sampling windows of size 16
// FALSE if no errors, TRUE otherwise
uint8_t L_Sample(uint16_t * t_buf, uint8_t ch_num) {
uint8_t i,j;
uint32_t avg;
for (i = 0; i 《 16; i++) {
// evm_LED_Set(ALLTOGGLE);
avg = 0;
for (j = 0; j 《 16; j++) {
smbus_readWord(0x2A,ch_num, &t_buf[0]);
avg += t_buf[0];
}
avg = avg / 16;
#ifdef SERIES_16
if(avg 《0xC0 || avg 》0xD4 ) { //if(avg 《0x147 || avg 》0x1BA ) {
return TRUE;
}
#endif
#ifdef SERIES_13
if(avg 《0xC0 || avg 》0xD4 ) { //if(avg 《0x147 || avg 》0x1BA ) {
return TRUE;
}
#endif
}
return FALSE;
}
//LDC1000 Test Routine
void LDC16_13_Evm_Test_Routine() {
uint16_t t_buf[2] = {0x00, 0x00}, test_0=0, test_1=0, test_2=0, test_3=0;
//uint8_t rpmin,rpmax;
uint16_t i,j,thld;//,noise,min
for(i=0;i《10;i++){
__delay_cycles(65000);
}
#ifdef SERIES_16
thld=5000;
#endif
#ifdef SERIES_13
thld=32;
#endif
// test_0=L_Noise(&t_buf[0],0);
// test_1=L_Noise(&t_buf[0],2);
#ifdef CH_4
// test_2=L_Noise(&t_buf[0],4);
// test_3=L_Noise(&t_buf[0],6);
#endif
if(L_Sample(&t_buf[0],0)){
evm_LED_Set(RED);
}
// else if(test_0》thld){
// evm_LED_Set(RED);
// }
else if(L_Sample(&t_buf[0],2)){
evm_LED_Set(RED);
}
// else if(test_1》thld){
// evm_LED_Set(RED);
// }
#ifdef CH_4
else if(L_Sample(&t_buf[0],4)){
evm_LED_Set(RED);
}
// else if(test_2》thld){
// evm_LED_Set(RED);
// }
else if(L_Sample(&t_buf[0],6)){
evm_LED_Set(RED);
}
// else if(test_3》thld){
// evm_LED_Set(RED);
// }
#endif
else{
evm_LED_Set(GREEN);
}
}
/** Oscillator
Disables USB if there is a problem with the oscillator
*/
#pragma vector = UNMI_VECTOR
__interrupt VOID UNMI_ISR (VOID)
{
switch (__even_in_range(SYSUNIV, SYSUNIV_BUSIFG ))
{
case SYSUNIV_NONE:
__no_operation();
break;
case SYSUNIV_NMIIFG:
__no_operation();
break;
case SYSUNIV_OFIFG:
UCSCTL7 &= ~(DCOFFG + XT1LFOFFG + XT2OFFG); //Clear OSC flaut Flags fault flags
SFRIFG1 &= ~OFIFG; //Clear OFIFG fault flag
break;
case SYSUNIV_ACCVIFG:
__no_operation();
break;
case SYSUNIV_BUSIFG:
SYSBERRIV = 0; //clear bus error flag
USB_disable(); //Disable
}
}