STM32-24位AD7799驅動之手冊程式碼詳解,支援模擬SPI和硬體SPI
1.AD7799介紹
AD7799結構圖如下所示:
其中REFIN參考電壓建議為2.5V, REFIN電壓低於0.1V時,則差分輸入ad值就無法檢測了,如下圖所示:
注意:
如果REG_CONFIG的REF_DET開啟的話,那麼輸入AD值電壓低於0.5V時,則差分輸入ad值就無法檢測了,如下圖所示:
2.AD7799差分訊號的輸入模式
如下圖所示,差分輸入電壓有3種模式:
注意:
單端輸入電壓(AIN-接地,只有正電壓)則支援任意範圍,比如In-Amp模式下,單端輸入如果為10mv的話,也能檢測到.
2.1 Unbuffered Mode非緩衝模式
該模式可測的AD值可以在 -30mV ~ (AVDD+30mv)範圍之間,如果開了雙極型模式(雙極型模式通過將REG_CONFIG的U/B位設0實現),則也可以測-(AVDD+30mv)~30mV之間AD值.
也就是說假如我們要測的AD值位於-100mV~100mV之間,則用這個模式.
該模式優缺點:可測範圍最大,但是精度誤差不是很高
2.2 Buffered Mode緩衝模式
緩衝的作用就是減少測的AD誤差,並且功耗相應地會增高點,該模式主要是測100mV~( AVDD-100mV)之間.
該模式優缺點:可測範圍比Unbuffered小一點,並且精度誤差高一點
2.3 In-Amp 高增益模式
需要將REG_CONFIG的Gain調到4及以上才是該模式,否則的話,就會根據REG_CONFIG的BUF位來自動判斷是Buffered Mode還是Unbuffered Mode.
並且AD值必須位於300mv~(AVDD+1100mv)之間,否則的話該模式是無法檢測AD值的,之前筆者就是測差分輸入的正負20mV,卻一直沒有反應,後來才發現是處於這個模式的原因.
該模式優缺點:可測範圍可以通過設定Gain來設定測試範圍,比如VREF為3V,Gain=4,則可測量程為正負600mv.
注意:
當使用Buffered Mode或者In-Amp模式時,需要將REG_CONFIG的BO位開啟,介紹如下圖所示:
3.程式碼效果
串列埠截圖如下:
通過電壓發生器不停修改AD值時,可以看到萬用表和串列埠列印的資料相差不大:
PS:由於GIF錄製的畫素位數太低,所以不清晰
4.程式碼實現
支援硬體SPI1或者GPIO模擬方式
程式碼通過巨集AD7799_INTERFACE_MODE判斷,能夠支援硬體SPI1或者GPIO模擬方式,如下圖所示:
通過巨集定義VREF參考電壓,以及GAIN增益值
如下圖所示,只需修改下面巨集,就可以實現轉換電壓資料自動轉換:
實現通道1和通道2來回切換
串列埠傳送select 1,表示選擇通道1:
傳送select 2,則表示選擇通道2.
4.1初始化過程
/*ad7799初始化*/ AD7799_gpio_init(); while(!AD7799_Init()) { LED0 = !LED0; delay_ms(50); } LED0 = 1; AD7799_Calibrate(); //通道校準 AD7799_SetGain(AD7799_CHIP_GAIN); AD7799_SetBurnoutCurren(0); //關閉BO AD7799_SetBufMode(0); //由於我們要測的電壓低於100mV,所以設定為Unbuffered Mode AD7799_SetChannel(ChannelBuf[0]); //通道設定. AD7799_SetMode(AD7799_MODE_CONT,5); //預設雙極性 頻率為5 AD7799_SetReference(0); //關閉參考檢測,因為我們的 AD7799_RefmV 參考電壓低於0.5V
4.2 上面的函式如下所示:
void AD7799_gpio_init(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = AD_CS_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(AD_CS_GPIO, &GPIO_InitStructure); //CS片選 #if ( AD7799_INTERFACE_MODE == AD7799_INTERFACE_SPI1 ) //spi1 mode SPI1_Init(); SPI1_SetSpeed(SPI_BaudRatePrescaler_2); #else //gpio模擬spi mode GPIO_InitStructure.GPIO_Pin = AD_DI_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(AD_DI_GPIO, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = AD_SCK_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(AD_SCK_GPIO, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = AD_DO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(AD_DO_GPIO, &GPIO_InitStructure); spi_AD7799_init(); #endif AD7799_Reset(); } void AD7799_SetGain(unsigned long gain) { unsigned long command; command = AD7799_GetRegisterValue(AD7799_REG_CONF,2); command &= ~AD7799_CONF_GAIN(0xFF); command |= AD7799_CONF_GAIN(gain); AD7799_SetRegisterValue( AD7799_REG_CONF, command, 2 ); } void AD7799_SetBurnoutCurren(u8 enable)//設定BO { unsigned long command; command = AD7799_GetRegisterValue(AD7799_REG_CONF,2); command &= ~0X2000; if(enable) command |= 0X2000; AD7799_SetRegisterValue( AD7799_REG_CONF, command, 2 ); } void AD7799_SetBufMode(u8 enable) //設定buf { unsigned long command; command = AD7799_GetRegisterValue(AD7799_REG_CONF,2); command &= ~0X10; if(enable) command |= 0X10; AD7799_SetRegisterValue( AD7799_REG_CONF, command, 2 ); } void AD7799_SetChannel(unsigned long channel) { unsigned long command; command = AD7799_GetRegisterValue(AD7799_REG_CONF,2); command &= ~AD7799_CONF_CHAN(0xFF); command |= AD7799_CONF_CHAN(channel); AD7799_SetRegisterValue( AD7799_REG_CONF, command, 2 ); } void AD7799_SetMode(unsigned long mode,u8 rate) { unsigned long command; command = AD7799_GetRegisterValue(AD7799_REG_MODE,2); command &= ~AD7799_MODE_SEL(0xFF); command |= AD7799_MODE_SEL(mode); command &= 0XFFF0; command |= rate; //設定頻率 AD7799_SetRegisterValue( AD7799_REG_MODE, command, 2 ); } void AD7799_SetReference(unsigned char state) { unsigned long command = 0; command = AD7799_GetRegisterValue(AD7799_REG_CONF,2); command &= ~AD7799_CONF_REFDET(1); command |= AD7799_CONF_REFDET(state); AD7799_SetRegisterValue(AD7799_REG_CONF, command, 2); } void AD7799_SetRegisterValue(unsigned char regAddress, unsigned long regValue, unsigned char size) { unsigned char data[5] = {0x03, 0x00, 0x00, 0x00, 0x00}; data[0] = AD7799_COMM_WRITE | AD7799_COMM_ADDR(regAddress); if(size == 1) { data[1] = (unsigned char)regValue; } if(size == 2) { data[2] = (unsigned char)((regValue & 0x0000FF) >> 0); data[1] = (unsigned char)((regValue & 0x00FF00) >> 8); } if(size == 3) { data[3] = (unsigned char)((regValue & 0x0000FF) >> 0); data[2] = (unsigned char)((regValue & 0x00FF00) >> 8); data[1] = (unsigned char)((regValue & 0xFF0000) >> 16); } AD7799_CS_LOW; SPI_Write(data,(1 + size)); AD7799_CS_HIGH; } unsigned long AD7799_GetRegisterValue(unsigned char regAddress, unsigned char size) { unsigned char data[5] = {0x00, 0x00, 0x00, 0x00, 0x00}; unsigned long receivedData = 0x00; data[0] = AD7799_COMM_READ | AD7799_COMM_ADDR(regAddress); AD7799_CS_LOW; SPI_Write(data,1); SPI_Read(data,size); AD7799_CS_HIGH; if(size == 1) { receivedData += (data[0] << 0); } if(size == 2) { receivedData += (data[0] << 8); receivedData += (data[1] << 0); } if(size == 3) { receivedData += (data[0] << 16); receivedData += (data[1] << 8); receivedData += (data[2] << 0); } return receivedData; }
4.3 獲取通道電壓程式碼如下所示:
while(1) { if(Serial_Post_ChannelValue!=0XFF) //0:不選擇 1~2:更改通道 { CurrentChannelValue = Serial_Post_ChannelValue; Serial_Post_ChannelValue =0XFF; if(CurrentChannelValue && CurrentChannelValue<=2) //1~2 { AD7799_SetChannel(ChannelBuf[CurrentChannelValue-1]);//通道設定. 0~1 delay_ms(10); AD7799_GetRegisterValue(AD7799_REG_DATA,3);//清空之前的AD } else if(CurrentChannelValue == 0) { printf("%s value0 0 0 \r\n",Board_Name); } } if(CurrentChannelValue) //選擇了通道? { for(i=0;i<2;i++) //獲取每個通道資料 if(CurrentChannelValue == (i+1)) { while( !AD7799_Ready()) //1~2 { delay_ms(5); } ADValues[i]= analyzeAD7799_Data(AD7799_GetRegisterValue(AD7799_REG_DATA,3)); } else ADValues[i] = 0.0000; printf("%s 當前通道為:%d %.3fmV %.3fmV \r\n",Board_Name,CurrentChannelValue,ADValues[0],ADValues[1]); } LED0 =!LED0; delay_ms(100); }
如果您有收穫,不妨點個讚唄~
&n