ADS8688在STM32中使用HAL库的驱动方法
使用HAL库
先贴上ADS8688驱动
C文件ADS8688.c
#include "stm32f4xx_hal.h"
#include "stm32f4xx_hal_gpio.h"
#include "ads8688.h"
void ADS8688_IO_Init(void) //ADS8688 IO口初始化
{
GPIO_InitTypeDef GPIO_InitStructure;
__HAL_RCC_GPIOC_CLK_ENABLE(); //使能端口时钟
__HAL_RCC_GPIOE_CLK_ENABLE();
GPIO_InitStructure.Pin = GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_13;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
DAISY_L;
CS_H;
RST_H;
CLK_L;
delay_ms(5);
}
void ADS8688_Init(uint8_t ch_en) //ADS8688初始化
{
ADS8688_IO_Init();
SOFT_RESET(); //复位
delay_ms(25);
Set_Auto_Scan_Sequence(ch_en);//使能通道
ADS8688_WriteReg(CH_PD,~ch_en);//通道退出低功耗状态 通道上电
delay_ms(50);
while(ADS8688_ReadReg(AUTO_SEQ_EN)!=ch_en)//是否使能成功
{
Set_Auto_Scan_Sequence(ch_en);//使能通道
ADS8688_WriteReg(CH_PD,~ch_en);//通道退出低功耗状态 通道上电
delay_ms(50);
}
}
uint8_t ADS8688_SPI_Read8Bit(void)
{
uint8_t i=0;
uint8_t read=0;
for(i=0; i<8; i++)
{
read<<=1;
CLK_H;
delay_us(2);
if(READ_SDO) read++;
CLK_L;
delay_us(2);
}
return read;
}
void ADS8688_SPI_Write8Bit(uint8_t data)
{
uint8_t i=0;
CS_L;
for(i=0; i<8; i++)
{
if(data&0x80) SDI_H;
else SDI_L;
data<<=1;
CLK_H;
delay_us(2);
CLK_L;
delay_us(2);
}
}
void ADS8688_WriteCmd(uint16_t cmd)//写ADS8688命令寄存器
{
CS_L;
ADS8688_SPI_Write8Bit(cmd>>8 & 0XFF);
ADS8688_SPI_Write8Bit(cmd & 0XFF);
ADS8688_SPI_Write8Bit(0X00);
ADS8688_SPI_Write8Bit(0X00);
CS_H;
}
void SOFT_RESET(void)//软件复位
{
ADS8688_WriteCmd(RST);
}
void AUTO_RST_Mode(void)//自动扫描模式
{
ADS8688_WriteCmd(AUTO_RST);
}
void MAN_CH_Mode(uint16_t ch)//手动模式
{
ADS8688_WriteCmd(ch);
}
uint8_t ADS8688_ReadReg(uint8_t addr)
{
uint8_t data = 0;
CS_L;
ADS8688_SPI_Write8Bit(addr<<1);
data = ADS8688_SPI_Read8Bit();
data = ADS8688_SPI_Read8Bit();
CS_H;
return data;
}
void ADS8688_WriteReg(uint8_t addr,uint8_t data)
{
CS_L;
ADS8688_SPI_Write8Bit(addr<<1| 0X01);
ADS8688_SPI_Write8Bit(data);
CS_H;
}
void Set_Auto_Scan_Sequence(uint8_t seq)
{
ADS8688_WriteReg(AUTO_SEQ_EN, seq);
}
void Set_CH_Range(uint8_t ch,uint8_t range)
{
ADS8688_WriteReg(ch,range);
}
void Get_AUTO_RST_Mode_Data(uint16_t *data, uint8_t chnum)
{
uint8_t i=0,datal=0,datah=0;
for (i=0; i<chnum; i++)
{
CS_L;
ADS8688_SPI_Write8Bit(0X00);
ADS8688_SPI_Write8Bit(0X00);
datah = ADS8688_SPI_Read8Bit();
datal = ADS8688_SPI_Read8Bit();
//delay_ms(1);
CS_H;
*(data+i) = datah<<8 | datal;
}
}
uint16_t Get_MAN_CH_Mode_Data(void)
{
u8 datah=0,datal=0;
CS_L;
ADS8688_SPI_Write8Bit(0X00);
ADS8688_SPI_Write8Bit(0X00);
datah = ADS8688_SPI_Read8Bit();
datal = ADS8688_SPI_Read8Bit();
CS_H;
return (datah<<8 | datal);
}
头文件ADS8688.h
#ifndef __ADS8688_H
#define __ADS8688_H
#include "sys.h"
#include "stm32f4xx_hal.h"
//命令寄存器
#define NO_OP 0x0000 /*在选定模式下继续操作
在设备操作期间将SDI线连续保持为低电平(相当于向所有16位写入0)将继续在最后选择的模式(STDBY,PWR_DN或AUTO_RST,MAN_Ch_n)下进行设备操作。
在这种模式下,设备将遵循程序寄存器(地址01h至3Ch)中已配置的相同设置。*/
#define STDBY 0x8200 /*待机模式
器件支持低功耗待机模式(STDBY),在该模式下,仅部分电路断电。
内部基准电压源和缓冲器未断电,在退出STDBY模式时,可以在20 μs内为器件加电。退出STDBY模式时,程序寄存器不会复位为默认值。*/
#define PWR_DN 0x8300/*掉电模式(PWR_DN)
器件支持硬件和软件掉电模式(PWR_DN),在该模式下,所有内部电路均被掉电,包括内部基准电压源和缓冲器。
如果设备在内部参考模式下运行(REFSEL = 0),则退出PWR_DN模式后,设备加电并转换所选模拟输入通道至少需要15 ms的时间。
设备的硬件电源模式在RST / PD(输入)部分中说明。
硬件和软件掉电模式之间的主要区别在于,当设备从硬件掉电唤醒时,程序寄存器会重置为默认值,但是当设备从软件唤醒时,程序寄存器的先前设置会保留掉电。*/
#define RST 0x8500/*重置程序寄存器(RST)
器件支持硬件和软件复位(RST)模式,在该模式下,所有程序寄存器均复位为其默认值。也可以使用硬件引脚将设备置于RST模式*/
#define AUTO_RST 0xA000/*自动通道启用
自动扫描所有模拟信道上的输入信号。自动扫描的通道序列可由程序寄存器中的自动扫描顺序控制寄存器(01h至02h)配置;请参阅程序寄存器映射部分。
在此模式下,设备以升序连续循环通过所选通道,从最低通道开始,转换程序寄存器中选择的所有通道。
序列完成后,设备返回到程序寄存器中的最低计数通道,并重复该序列。通过设置程序寄存器的范围选择寄存器,可以配置自动扫描序列中每个通道的输入电压范围。*/
#define MAN_CH_1 0xC000/**/
#define MAN_CH_2 0xC400/**/
#define MAN_CH_3 0xC800/**/
#define MAN_CH_4 0xCC00/**/
#define MAN_CH_5 0xD000/**/
#define MAN_CH_6 0xD400/**/
#define MAN_CH_7 0xD800/**/
#define MAN_CH_8 0xDC00/*手动通道n选择(MAN_Ch_n)
通过在手动通道n扫描模式(MAN_Ch_n)中进行操作,可以对设备进行编程以转换特定的模拟输入通道。通过在命令寄存器中写入有效的手动通道n选择命令(MAN_Ch_n)来完成该编程*/
#define MAN_AUX 0XE000/*AUX通道*/
//程序寄存器
#define AUTO_SEQ_EN 0x01 /*自动扫描序列使能寄存器
该寄存器选择单个通道以在AUTO_RST模式下进行排序。
该寄存器的默认值为FFh,这意味着在默认条件下所有通道都包含在自动扫描序列中。*/
#define CH_PD 0x02 /*通道掉电寄存器
该寄存器关闭掉AUTO_RST模式下不包含的单个通道的电源。 该寄存器的默认值为00h,这意味着在默认条件下所有通道均已上电。*/
#define F_S 0X03 /*器件功能选择控制寄存器
该寄存器中的位可用于配置菊花链操作的设备ID,并配置SDO上的输出位格式。*/
//各通道范围选择寄存器 默认值为00h
#define CHIR_1 0x05/**/
#define CHIR_2 0x06/**/
#define CHIR_3 0x07/**/
#define CHIR_4 0x08/**/
#define CHIR_5 0x09/**/
#define CHIR_6 0x0A/**/
#define CHIR_7 0x0B/**/
#define CHIR_8 0x0C/**/
#define CMD_READ 0x3F /*命令回读寄存器
该寄存器允许用户读取设备的操作模式。 执行此命令后,设备将输出在前一个数据帧中执行的命令字。
有关命令寄存器的所有信息在前8位中包含,并且后8位为0。*/
/*************************************************************************************************************/
#define CH8_EN 0X80
#define CH7_EN 0X40
#define CH6_EN 0X20
#define CH5_EN 0X10
#define CH4_EN 0X08
#define CH3_EN 0X04
#define CH2_EN 0X02
#define CH1_EN 0X01
#define REF 4096
//输入范围
#define ADS8688_IR_N2_5V 0x00 //±2.5*ref ref=4.096V ±10.24V
#define ADS8688_IR_N1_25V 0x01 //±1.25*ref ±5.12V
#define ADS8688_IR_N0_625V 0x02 //±0.625*ref ±2.56V
#define ADS8688_IR_2_5V 0x05 //0-2.5*ref 0-10.24V
#define ADS8688_IR_1_25V 0x06 //0-1.25*ref 0-5.12V
//不同量程的1个ADC值对应的电压值,即分辨率
#define CONST_N2_5V_LSB_mV 2.5*2*REF/65535 //约为0.3mV
#define CONST_N1_25V_LSB_mV 1.25*2*REF/65535 //约为0.156mV
#define CONST_N0_625V_LSB_mV 0.625*2*REF/65535 //约为0.078mV
#define CONST_2_5V_LSB_mV 2.5*REF/65535 //约为0.156mV
#define CONST_1_25V_LSB_mV 1.25*REF/65535 //约为0.078mV
#define SDI_H HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_SET)//串行通信数据输入
#define RST_H HAL_GPIO_WritePin(GPIOE,GPIO_PIN_2,GPIO_PIN_SET)//复位
#define DAISY_H HAL_GPIO_WritePin(GPIOE,GPIO_PIN_6,GPIO_PIN_SET)//以菊花链模式连接串行通信期间的数据输入
#define CLK_H HAL_GPIO_WritePin(GPIOE,GPIO_PIN_4,GPIO_PIN_SET)//串行通信时钟输入
#define CS_H HAL_GPIO_WritePin(GPIOE,GPIO_PIN_3,GPIO_PIN_SET)//片选
#define SDI_L HAL_GPIO_WritePin(GPIOE,GPIO_PIN_5,GPIO_PIN_RESET)
#define RST_L HAL_GPIO_WritePin(GPIOE,GPIO_PIN_2,GPIO_PIN_RESET)//>400ns
#define DAISY_L HAL_GPIO_WritePin(GPIOE,GPIO_PIN_6,GPIO_PIN_RESET)
#define CLK_L HAL_GPIO_WritePin(GPIOE,GPIO_PIN_4,GPIO_PIN_RESET)
#define CS_L HAL_GPIO_WritePin(GPIOE,GPIO_PIN_3,GPIO_PIN_RESET)
#define READ_SDO HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13)
void ADS8688_IO_Init(void); //ADS8688 IO口初始化
void ADS8688_Init(uint8_t ch_en); //ADS8688初始化
uint8_t ADS8688_SPI_Read8Bit(void);//读8个bit数据
void ADS8688_SPI_Write8Bit(uint8_t com);//写8个bit数据
void ADS8688_WriteCmd(uint16_t cmd);//写ADS8688命令寄存器
void SOFT_RESET(void);//软件复位
void AUTO_RST_Mode(void);//自动扫描模式
void MAN_CH_Mode(uint16_t ch);//手动单次扫描模式通道选择
uint8_t ADS8688_ReadReg(uint8_t addr);//读指定的寄存器
void ADS8688_WriteReg(uint8_t addr,uint8_t data);//写指定的寄存器
void Set_Auto_Scan_Sequence(uint8_t seq);//设置自动扫描序列通道
void Set_CH_Range(uint8_t ch,uint8_t range);//设置指定通道测量范围
u16 Get_MAN_CH_Mode_Data(void);//读取手动模式AD值
void Get_AUTO_RST_Mode_Data(uint16_t* outputdata, uint8_t chnum);//读取自动扫描模式AD值
#endif
该驱动所包含头文件sys.h中,只需要delay相关函数。
驱动拿来不能直接用(在引脚和我不一样的情况下),初始化引脚可以根据自己具体接的线来修改驱动文件。
具体要修改的地方在void ADS8688_IO_Init(void)和void ADS8688_Init(uint8_t ch_en);
使用方法
ADS8688分两种模式,手动扫描和自动扫描。
说明:
自动扫描模式下,该模块一次性扫描八个通道,所以用户需要定义一个类型为uint16_t的数组,含八个数。如果用户只定义了一个数,那么在自动扫描的模式下,该数会按照从AIN0~AIN7采集到的数值来变化。
手动扫描模式(只能这样翻译了)。在该模式下,根据你所选用的通道来调用函数,函数返回值只读取该通道采样值。如果你没有用满八个通道,那么该模式更加节省资源,采样速率更快。
自动扫描模式
delay_init(168);我用的F4,主频最高位168MHz。
ADS8688_Init(CH7_EN);
Set_CH_Range(CHIR_7,ADS8688_IR_N2_5V);
AUTO_RST_Mode();
while(1)
{
Get_AUTO_RST_Mode_Data(value_8688,8);
Us=(value_8688[6]-32767)*CONST_N2_5V_LSB_mV;
}
直接调用即可。
说明:初始化函数参数可以写成形如(…CH7_EN|CH8_EN)形式,初始化你选用的通道。
Set_CH_Range(CHIR_7,ADS8688_IR_N2_5V);设置量程
Get_AUTO_RST_Mode_Data(value_8688,8);该函数要循环调用,更新采样值。
手动模式
delay_init(168);
ADS8688_Init(CH0_EN);//ADS8688初始化
Set_CH_Range(CHIR_1,ADS8688_IR_N2_5V);
while(1)
{
MAN_CH_Mode(MAN_CH_0);//选择通道
value[0]=Get_MAN_CH_Mode_Data();//读取通道数据,
}
同理,具体参数看头文件说明。
总结
到此模块可以正常使用;
ADS8688是一个很好用的模块,电赛神器;但是在实际使用的过程中经常会碰到令程序跑飞的情况,没想明白。
作者:「已注销」