目录
ADS8866 ADC转换芯片驱动调试
开发环境:
主控芯片:STM32F103RCT6、ADS8866转换芯片、使用HAL库进行开发。
ADS8866功能简介
ADS8866是一款16位,100kSPS,单端输入,模数转换器 (ADC)。此器件以2.5V至5V的外部基准运行,从而在无需额外的信号调节情况下提供宽信号范围。此基准电压设置独立于,并且可超过,模拟电源电压(AVDD)。此器件提供一个SPI兼容串口,此串口也支持菊花链操作以实现多个器件级联。 此器件支持-0.1V至VREF + 0.1V范围的单极单端模拟输入。器件运行针对极低功耗运行进行了优化。功耗直接与速度成比例。这个特性使得ADS8866非常适合于低速应用。
以下链接是其详细的数据手册:
https://download.youkuaiyun.com/download/qq_45143522/89216266
硬件连接
我这边是使用STM32F103RCT6的SPI3与ADS8866进行通讯的。引脚对应如下: stm32f103引脚 ADS8866引脚 PA15 CONVST作为片选引脚使用 PB3 SCLK时钟引脚 PB4 DOUT(MISO) PB5 DIN(MOSI) 由于ADS8866分为三线模式和四线模式,我这边使用的是三线模式,即不使用DIN(MISO),硬件设计时可以根据ads8866的datesheet手册根据三线模式的要求将DIN引脚直接和DVDD相连使其保持高电平即可。
SPI3的软件驱动
这里如何使用STM32CubeMX配置SPI3的驱动,可以自己查找相关的资料进行配置,这里不再配置,直接看程序框架及驱动代码。
主函数main程序架构:
uint8_t ads8866_buf[2]; //用来存储ads8866发送来的数据
int main()
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init(); //初始化GPIO,片选引脚CONVST
MX_SPI3_Init(); //初始化SPI3的相关引脚及配置SPI3
while(1)
{
get_ads8866_data(&hspi3,ads8866_buf); //stm32读取ads8866转换数据接口函数
HAL_Delay(2000);
}
}
MX_GPIO_Init函数主要内容如下:
MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);
//这里将CONVST初始化为低电平是由ADS8866的通讯时序决定的,后面会说。
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_15,GPIO_PIN_RESET);
}
MX_SPI3_Init函数主要内容如下:
void MX_SPI3_Init(void)
{
hspi3.Instance = SPI3;
hspi3.Init.Mode = SPI_MODE_MASTER; //主模式
hspi3.Init.Direction = SPI_DIRECTION_2LINES;
hspi3.Init.DataSize = SPI_DATASIZE_8BIT; //8位帧结构
hspi3.Init.CLKPolarity = SPI_POLARITY_LOW; //SCLK的空闲状态为低电平
hspi3.Init.CLKPhase = SPI_PHASE_2EDGE; //在SCLK的第2个跳变沿开始传输数据
hspi3.Init.NSS = SPI_NSS_SOFT;
hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; //4分频值 频率为36MHz/4 = 9MHz
hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB; //数据传输从MSB位开始
hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi3.Init.CRCPolynomial = 7;
if(HAL_SPI_Init(&hspi3) != HAL_OK)
{
Error_Handler();
}
__HAL_SPI_ENABLE(&hspi3);
}
其中: 时钟极性CPOL和时钟相位CPHA两项的设置依然是和ADS8866芯片的通讯时序有关,后面会说到。
HAL_SPI_MspInit(SPI_HandleTypeDef * spiHandle)函数的主要内容如下:
void HAL_SPI_MspInit(SPI_HandleTypeDef * spiHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(spiHandle->Instance == SPI3)
{
__HAL_RCC_SPI3_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
//PB3--SCLK PB4--DOUT(MISO) PB5--DIN(MOSI)
GPIO_InitStruct.Pin = GPIO_PIN_3 | GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB,&GPIO_InitStruct);
}
}
至此,SPI3的HAL库驱动就基本完成了,接着需要与ADS8866芯片进行通讯,来获取adc采集的数据。
ADS8866通讯时序分析
在进行ADS8866驱动开发前,我们需要阅读芯片的datesheet手册来确定通讯的时序。如下图是数据手册里的三线模式的通讯时序图:
根据数据手册及时序图,我们可以知道: 1、在三线模式下,CONVST引脚与DVDD引脚相连,并且将CONVST引脚作为片选引脚使用。 2、CONVST引脚的上升沿会使得DOUT进入三态的状态,并且开始与ads8866建立会话。 3、CONVST引脚由低变高后最少要持续t_conv-max的时间,这个参数为8.8微秒。 4、当建立会话的过程结束之后就进入传输数据的阶段。 5、在CONVST的下降沿,DOUT退出三态状态,ADS8866开始向外传输数据,数据传输从最高位开始。 6、之后的数据传输都是在SCLK的下降沿到来时进行传输。数据在SCLK的双边沿均有效。 7、将片选信号CONVST拉高或者在第16次SCLK时钟的下降沿到来之后DOUT将重新回到三态的状态。 除了以上信息,我们根据时序图还可以知道: CONVST片选信号的初始状态为低电平。 SCLK时钟线的空闲状态为低电平。即时钟极性CPOL = 0。 在SCLK的第2个跳变沿(下降沿)开始传输数据,即时钟相位CPHA为1。 这三点对我们编写程序非常重要。
ADS8866驱动
经过以上对ADS8866芯片的时序分析之后,我们想要通过SPI通讯读取ADS8866芯片采集转换后的adc数据将十分简单。 具体程序代码如下:
//使用到的微秒级延时函数
void delay_us(uint32_t us)
{
uint8_t i = 0;
while(us--)
{
i = 12;
while(i--);
}
}
//获取ADS8866的转换数据
void get_ads8866_data(SPI_HandleTypeDef *hspi,uint8_t *buf)
{
//建立会话
ADC_CS3_HIGH; //片选信号初始化为低,在DIN为高的时候,片选信号给个上升沿开始与adc芯片建立会话
delay_us(10); //片选信号拉高后的持续时间要超过8.8微秒
//传输数据
ADC_CS3_LOW; //片选信号拉低开始传输数据
HAL_SPI_Receive(hspi,buf,2,100); //接收ADS8866发送的2字节数据到buf缓存中
}