這幾天嘗試用stm32驅(qū)動ads1115,是直接從淘寶買的模塊,驅(qū)起來讀數(shù)時而看起來準(和手持萬用表測出來的差不多),時而不準,誤差非常大,不知道是為什么。個人感覺程序沒什么問題,會不會是硬件問題?因為我是用杜邦線接到開發(fā)板上的(正點原子的精英板),供電也用的是開發(fā)板上的3.3v,會不會是開發(fā)板3.3不穩(wěn)定導致內(nèi)部基準不穩(wěn)導致的?下面貼上程序,希望有大神可以幫忙看看。
STM32單片機源程序如下:
- #include "ads1115.h"
- #include "delay.h"
- u16 Ads1115_Config; //存放ADS1115配置寄存器的配置
- u8 Ads1115_Result[2]; //存放ADS1115轉(zhuǎn)換寄存器的數(shù)據(jù)
- u8 Writebuff[4],Readbuff[3]; //寫數(shù)據(jù)的命令和讀數(shù)據(jù)的命令緩存數(shù)組
- u16 ads1115_average_data[4]; //獲取到的4個通道的經(jīng)過濾波的后的值
- u16 filter_ave_buf[4][201]; //濾波的數(shù)據(jù)
- u32 filter_sum_buf[4]; //數(shù)據(jù)總和
- u8 ch_count; //通道數(shù)
- //初始化ADS1115的IO
- void ADS1115_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE ); //使能PB端口時鐘
-
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_15; //PB13 PB15
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽輸出
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //輸出最大速度50MHz
- GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB
-
- ADS1115_SCL=1;
- ADS1115_SDA=1;
- }
- //********************************************
- //函數(shù)名稱:ADS1115_Start
- //功 能:完成IIC的起始條件操作
- //參 數(shù):無
- //返回值 :無
- //********************************************/
- void ADS1115_Start(void)
- {
- ADS1115_SDA_OUT(); //sda線輸出
- ADS1115_SDA=1;
- ADS1115_SCL=1;
- delay_us(2);
- ADS1115_SDA=0; //START:when CLK is high,DATA change form high to low
- delay_us(2);
- ADS1115_SCL=0; //鉗住I2C總線,準備發(fā)送或接收數(shù)據(jù)
- delay_us(2);
- }
- //********************************************
- //函數(shù)名稱:ADS1115_Stop
- //功 能:完成IIC的終止條件操作
- //參 數(shù):無
- //返回值 :無
- //********************************************/
- void ADS1115_Stop(void)
- {
- ADS1115_SDA_OUT(); //sda線輸出
- ADS1115_SCL=0;
- ADS1115_SDA=0; //STOP:when CLK is high,DATA change form low to high
- delay_us(2);
- ADS1115_SCL=1;
- delay_us(2);
- ADS1115_SDA=1; //發(fā)送I2C總線結(jié)束信號
- delay_us(2);
- }
- //********************************************
- //函數(shù)名稱:ADS1115_ACK
- //功 能:完成IIC的主機應答操作
- //參 數(shù):無
- //返回值 :無
- //********************************************/
- void ADS1115_ACK(void)
- {
- ADS1115_SCL=0;
- ADS1115_SDA_OUT(); //sda線輸出
- ADS1115_SDA=0;
- delay_us(2);
- ADS1115_SCL=1;
- delay_us(2);
- ADS1115_SCL=0;
- }
- //********************************************
- //函數(shù)名稱:ADS1115_NACK
- //功 能:完成IIC的主機無應答操作
- //參 數(shù):無
- //返回值 :無
- //********************************************/
- void ADS1115_NACK(void)
- {
- ADS1115_SCL=0;
- ADS1115_SDA_OUT(); //sda線輸出
- ADS1115_SDA=1;
- delay_us(2);
- ADS1115_SCL=1;
- delay_us(2);
- ADS1115_SCL=0;
- }
- //**********檢查應答信號函數(shù)******************/
- ///*如果返回值為1則證明有應答信號,反之沒有*/
- ///*******************************************
- //函數(shù)名稱:ADS1115_Check
- //功 能:檢查從機的應答操作
- //參 數(shù):無
- //返回值 :從機是否有應答:1--有,0--無
- //********************************************/
- u8 ADS1115_Check(void)
- {
- u8 slave_ack;
- ADS1115_SDA_IN();
- ADS1115_SDA=1;
- delay_us(1);
- ADS1115_SCL=1;
- delay_us(1);
- slave_ack = ADS1115_READ_SDA; //讀入SDA數(shù)值
- ADS1115_SCL=0;
- delay_us(3);
- if(slave_ack)return FALSE;
- else return TRUE;
- }
- /***************Write a Byte****************/
- void Write_1_Byte(u8 DataByte)
- {
- u8 i;
- ADS1115_SDA_OUT(); //sda線輸出
- for(i=0;i<8;i++)
- {
- if(DataByte&0x80)
- ADS1115_SDA=1;
- else
- ADS1115_SDA=0;
- delay_us(3);
- ADS1115_SCL=1;
- delay_us(3);
- ADS1115_SCL=0;
- delay_us(2);
- DataByte <<= 1;
- }
- ADS1115_SDA=1;
- delay_us(2);
- }
- /***************Write N Byte****************/
- u8 Write_N_Byte(u8 *writebuffer,u8 n)
- {
- u8 i;
- ADS1115_SDA_OUT(); //sda線輸出
- for(i=0;i<n;i++)
- {
- Write_1_Byte(*writebuffer);
- if(ADS1115_Check())
- writebuffer++;
- else
- {
- ADS1115_Stop();
- return FALSE;
- }
- }
- ADS1115_Stop();
- return TRUE;
- }
- //***************Read a Byte****************/
- u8 Read_1_Byte(void)
- {
- u8 data_Value=0,i;
- for(i=0;i<8;i++)
- {
- ADS1115_SDA_OUT(); //sda線輸出
- ADS1115_SDA=1;
- delay_us(3);
- ADS1115_SCL=1;
- delay_us(3);
- ADS1115_SDA_IN();
- data_Value<<= 1;
- if(ADS1115_READ_SDA)
- data_Value++;
- ADS1115_SCL=0;
- delay_us(2);
- }
- return data_Value;
- }
- //***************Read N Byte****************/
- void Read_N_Byte(u8*readbuff, u8 n)
- {
- u8 i;
- for(i=0;i<n;i++)
- {
- readbuff[i]=Read_1_Byte();
- if(i==n-1)
- ADS1115_NACK(); //不連續(xù)讀字節(jié)
- else
- ADS1115_ACK(); //連續(xù)讀字節(jié)
- }
- ADS1115_Stop();
- }
- //***************Write a Word***********************/
- void WriteWord(void)
- {
- u8 t;
- ADS1115_Start(); //寫入4個字節(jié)
- do
- {
- t=Write_N_Byte(Writebuff,4);
- }while(t==0);
- }
- //***************Read Word***********************/
- void ReadWord(void)
- {
- u8 t;
- ADS1115_Start(); //寫入2個字節(jié)
- do
- {
- t=Write_N_Byte(Readbuff,2);
- }while(t==0);
- ADS1115_Start(); //寫入1個字節(jié)
- do
- {
- t=Write_N_Byte(&Readbuff[2],1);
- }while(t==0);
- Read_N_Byte(Ads1115_Result,2); //讀出2個字節(jié)
- }
- //***************ADS1115********************/
- u16 ADS1115_Get_Data(u8 ch)
- {
- u16 result;
- if(ch==0)
- Ads1115_Config = OS+MUX_A0+PGA+DR+COMP_QUE+MODE;
- else if(ch==1)
- Ads1115_Config = OS+MUX_A1+PGA+DR+COMP_QUE+MODE;
- else if(ch==2)
- Ads1115_Config = OS+MUX_A2+PGA+DR+COMP_QUE+MODE;
- else if(ch==3)
- Ads1115_Config = OS+MUX_A3+PGA+DR+COMP_QUE+MODE;
- Writebuff[0]=ADDRESS_W; //寫地址
- Writebuff[1]=Pointer_1; //寫配置寄存器
- Writebuff[2]=Ads1115_Config/256; //寫配置
- Writebuff[3]=Ads1115_Config%256;
-
- Readbuff[0]=ADDRESS_W; //寫地址
- Readbuff[1]=Pointer_0; //讀轉(zhuǎn)換寄存器
- Readbuff[2]=ADDRESS_R; //讀地址
- WriteWord();
- delay_ms(1);
- ReadWord();
-
- result=Ads1115_Result[0]*256+Ads1115_Result[1]; //轉(zhuǎn)換的數(shù)字量
- return result;
- }
- /*-----------------------------------------------------------------------------------------------
- 名稱:中位值濾波法
- 方法:連續(xù)采樣N次(N取奇數(shù)),把N次采樣值按大小排列,取中間值為本次有效值。
- 優(yōu)點:能有效克服因偶然因素引起的波動干擾,對溫度、液體的變化緩慢的被測參數(shù)有良好的濾波效果。
- 缺點:對流量、速度等快速變化的參數(shù)不宜。
- 出口參數(shù):filter_buf[50]
- ------------------------------------------------------------------------------------------------*/
- //void ADS1115_Process(void)
- //{
- // u16 filter_buf[101];
- // u16 i, j;
- // u16 filter_temp;
- // for(i = 0; i < 101; i++)
- // {
- // filter_buf[i] = ADS1115_Get_Data(1);
- // }
- // for(j = 0; j < 100; j++)
- // {
- // for(i = 0; i < 100 - j; i++) //將 100-j 個數(shù)中取最大的放在數(shù)組的最后(100-j)
- // {
- // if(filter_buf[i] > filter_buf[i + 1]) //數(shù)組右邊的小于左邊的
- // {
- // filter_temp = filter_buf[i];
- // filter_buf[i] = filter_buf[i + 1]; //將小的放在左邊
- // filter_buf[i + 1] = filter_temp; //將大的放在右邊
- // }
- // }
- // }
- // ads1115_average_data[1] = filter_buf[50];
- //}
-
- /*-----------------------------------------------------------------------------------------------
- 名稱:遞推平均濾波法(又稱滑動平均濾波法)
- 方法:把連續(xù)取得的N個采樣值看成一個隊列,隊列的長度固定為N,
- 每次采樣到一個新數(shù)據(jù)放入隊尾,并扔掉原來隊首的一次數(shù)據(jù)(先進先出原則),
- 把隊列中的N個數(shù)據(jù)進行算術(shù)平均運算,獲得新的濾波結(jié)果。
- 優(yōu)點:對周期性干擾有良好的抑制作用,平滑度高,適用于高頻震蕩的系統(tǒng)。
- 缺點:靈敏度低,對偶然出現(xiàn)的脈沖性干擾的抑制作用較差,不易消除由于脈沖干擾所引起的采樣值偏差,
- 不適用于脈沖干擾比較嚴重的場合,比較浪費RAM。
- 出口參數(shù):filter_sum_buf/200
- ------------------------------------------------------------------------------------------------*/
- void ADS1115_Process(void)
- {
- u8 i;
- filter_ave_buf[ch_count][200]=ADS1115_Get_Data(ch_count); //讀出一個數(shù)據(jù)放在數(shù)組最右邊
- for(i = 0; i < 200; i++) //200個數(shù)據(jù)取平均
- {
- filter_ave_buf[ch_count][i] = filter_ave_buf[ch_count][i + 1]; //所有數(shù)據(jù)左移,低位扔掉
- filter_sum_buf[ch_count] += filter_ave_buf[ch_count][i]; //求出200個數(shù)據(jù)總和
- }
- ads1115_average_data[ch_count]=filter_sum_buf[ch_count]/200; //得到平均值
- filter_sum_buf[ch_count]=0; //清總和
- ch_count++; //切換下個通道,共4通道
- if(ch_count>=4)
- ch_count=0;
- }
- void read(u8 ch)
- {
-
- }
復制代碼
所有資料51hei提供下載:
F1-ADS1115例程.7z
(231.58 KB, 下載次數(shù): 83)
2019-8-3 15:17 上傳
點擊文件名下載附件
|