这几天尝试用stm32驱动ads1115,是直接从淘宝买的模块,驱起来读数时而看起来准(和手持万用表测出来的差不多),时而不准,误差非常大,不知道是为什么。个人感觉程序没什么问题,会不会是硬件问题?因为我是用杜邦线接到开发板上的(正点原子的精英板),供电也用的是开发板上的3.3v,会不会是开发板3.3不稳定导致内部基准不稳导致的?下面贴上程序,希望有大神可以帮忙看看。
STM32单片机源程序如下:
- #include "ads1115.h"
- #include "delay.h"
- u16 Ads1115_Config; //存放ADS1115配置寄存器的配置
- u8 Ads1115_Result[2]; //存放ADS1115转换寄存器的数据
- u8 Writebuff[4],Readbuff[3]; //写数据的命令和读数据的命令缓存数组
- u16 ads1115_average_data[4]; //获取到的4个通道的经过滤波的后的值
- u16 filter_ave_buf[4][201]; //滤波的数据
- u32 filter_sum_buf[4]; //数据总和
- u8 ch_count; //通道数
- //初始化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;
- }
- //********************************************
- //函数名称:ADS1115_Start
- //功 能:完成IIC的起始条件操作
- //参 数:无
- //返回值 :无
- //********************************************/
- 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总线,准备发送或接收数据
- delay_us(2);
- }
- //********************************************
- //函数名称:ADS1115_Stop
- //功 能:完成IIC的终止条件操作
- //参 数:无
- //返回值 :无
- //********************************************/
- 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; //发送I2C总线结束信号
- delay_us(2);
- }
- //********************************************
- //函数名称:ADS1115_ACK
- //功 能:完成IIC的主机应答操作
- //参 数:无
- //返回值 :无
- //********************************************/
- 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;
- }
- //********************************************
- //函数名称:ADS1115_NACK
- //功 能:完成IIC的主机无应答操作
- //参 数:无
- //返回值 :无
- //********************************************/
- 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;
- }
- //**********检查应答信号函数******************/
- ///*如果返回值为1则证明有应答信号,反之没有*/
- ///*******************************************
- //函数名称:ADS1115_Check
- //功 能:检查从机的应答操作
- //参 数:无
- //返回值 :从机是否有应答: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数值
- 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(); //不连续读字节
- else
- ADS1115_ACK(); //连续读字节
- }
- ADS1115_Stop();
- }
- //***************Write a Word***********************/
- void WriteWord(void)
- {
- u8 t;
- ADS1115_Start(); //写入4个字节
- do
- {
- t=Write_N_Byte(Writebuff,4);
- }while(t==0);
- }
- //***************Read Word***********************/
- void ReadWord(void)
- {
- u8 t;
- ADS1115_Start(); //写入2个字节
- do
- {
- t=Write_N_Byte(Readbuff,2);
- }while(t==0);
- ADS1115_Start(); //写入1个字节
- do
- {
- t=Write_N_Byte(&Readbuff[2],1);
- }while(t==0);
- Read_N_Byte(Ads1115_Result,2); //读出2个字节
- }
- //***************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; //读转换寄存器
- Readbuff[2]=ADDRESS_R; //读地址
- WriteWord();
- delay_ms(1);
- ReadWord();
-
- result=Ads1115_Result[0]*256+Ads1115_Result[1]; //转换的数字量
- return result;
- }
- /*-----------------------------------------------------------------------------------------------
- 名称:中位值滤波法
- 方法:连续采样N次(N取奇数),把N次采样值按大小排列,取中间值为本次有效值。
- 优点:能有效克服因偶然因素引起的波动干扰,对温度、液体的变化缓慢的被测参数有良好的滤波效果。
- 缺点:对流量、速度等快速变化的参数不宜。
- 出口参数: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 个数中取最大的放在数组的最后(100-j)
- // {
- // if(filter_buf[i] > filter_buf[i + 1]) //数组右边的小于左边的
- // {
- // 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];
- //}
-
- /*-----------------------------------------------------------------------------------------------
- 名称:递推平均滤波法(又称滑动平均滤波法)
- 方法:把连续取得的N个采样值看成一个队列,队列的长度固定为N,
- 每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据(先进先出原则),
- 把队列中的N个数据进行算术平均运算,获得新的滤波结果。
- 优点:对周期性干扰有良好的抑制作用,平滑度高,适用于高频震荡的系统。
- 缺点:灵敏度低,对偶然出现的脉冲性干扰的抑制作用较差,不易消除由于脉冲干扰所引起的采样值偏差,
- 不适用于脉冲干扰比较严重的场合,比较浪费RAM。
- 出口参数:filter_sum_buf/200
- ------------------------------------------------------------------------------------------------*/
- void ADS1115_Process(void)
- {
- u8 i;
- filter_ave_buf[ch_count][200]=ADS1115_Get_Data(ch_count); //读出一个数据放在数组最右边
- for(i = 0; i < 200; i++) //200个数据取平均
- {
- filter_ave_buf[ch_count][i] = filter_ave_buf[ch_count][i + 1]; //所有数据左移,低位扔掉
- filter_sum_buf[ch_count] += filter_ave_buf[ch_count][i]; //求出200个数据总和
- }
- 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, 下载次数: 83)
|