STM32 - SPI驱动ADS1220

一.硬件知识

ADS1220 是一款精密 24 位模数转换器 (ADC),所集 成的多种 特性 能够降低系统成本并减少小型传感器信 号测量 应用 中的组件数量。该器件 具有 通过输入多路复用器 (MUX) 实现的两个差分输入或四个单端输 入,一个低噪声可编程增益放大器 (PGA),两个可编程激励电流源,一个电压基准,一个振荡器,一个低侧开关和一个精密温度传感器。

二.GPIO驱动

在这里插入图片描述

PA5的SCK引脚需要使用复用推挽模式(GPIO_MODE_AF_PP)而不是直接使用推挽模式(GPIO_MODE_OUTPUT_PP),主要是因为SPI接口的时钟信号(SCK)需要由外设硬件控制。以下是详细原因:
1. 复用功能模式(Alternate Function Mode)
复用推挽模式(GPIO_MODE_AF_PP):
复用推挽模式不仅提供推挽输出功能,还允许引脚由STM32的外设(如SPI、I2C、UART等)控制。
在这种模式下,GPIO引脚的输出由外设硬件直接驱动,而不是通过软件控制。这对于需要精确时序控制的外
设(如SPI)至关重要
2. 硬件控制 SPI外设硬件控制SCK:

SPI的时钟信号(SCK)必须由SPI外设生成,以确保正确的时钟频率和相位。这些时钟信号需要精确的时间控制,以实现可靠的数据传输。
使用复用推挽模式,SCK引脚的状态变化由SPI外设硬件自动控制,而不需要软件干预。这种硬件控制方式能够提供更高的精度和更快的响应时间。
3. 软件控制的局限性 推挽模式(GPIO_MODE_OUTPUT_PP)*

如果使用普通的推挽输出模式(GPIO_MODE_OUTPUT_PP),引脚的状态必须通过软件来控制。这意味着每次状态变化都需要由CPU处理,导致较高的延迟和不稳定的时序。
软件控制的时钟信号可能无法满足SPI协议对时钟信号精度和稳定性的要求,进而影响数据传输的可靠性。

三.底层SPI时序通讯

在这里插入图片描述
在这里插入图片描述

DIN 数字输入 串行数据输入

/*******************************************************************************
Function    : spi_write_byte
Description : 完成底层spi操作,写一字节
Input       :  byte 写入的字节数据
Output      : 无
Return      : 无
*******************************************************************************/
uint8_t spi_write_byte(uint_t byte)   //
底层操作,不涉及器件
{
while(SPI_I2S_GetFlagStatus(ADS1248_SPI, SPI_I2S_FLAG_TXE) == RESET);

/* 通过 SPI 总线外设发送 u8 */
SPI_I2S_SendData(ADS1248_SPI,数据);

/* 等待接收 u8 */
while(SPI_I2S_GetFlagStatus(ADS1248_SPI, SPI_I2S_FLAG_RXNE) == RESET);

/* 返回从 SPI 总线读取的 u8 */
返回SPI_I2S_ReceiveData(ADS1248_SPI);
}
    }
}
/*******************************************************************************
Function    : spi_write_byte
Description : 完成底层spi操作,写一字节
Input       :  byte 写入的字节数据
Output      : 无
Return      : 无
*******************************************************************************/
uint8_t spi_ReadByte(void)
{
    return (ADS1248_WriteByte(ADS_NOP));
}

四、外围器件

1.参考电路

REFP0 模拟输入 正基准输入 0
在这里插入图片描述REF3025AIDBZT芯片的电压基准电路

  1. 输入电压:电路的输入电压为3V3(3.3V),通过R21电阻(1.5欧姆)输入到电压基准芯片的IN引脚。
  2. 滤波电容
    • C51和C50是并联的滤波电容,C51是一个钽电容(10uF/6.3V),而C50是一个陶瓷电容(0.1uF/50V)。这两个电容用于滤除电源中的高频噪声,提供一个稳定的输入电压给U10芯片。
    • C52是U10输出端的滤波电容,标记为一个钽电容(10uF/6.3V),它的作用是稳定输出电压。
  3. 电压基准芯片:U10是REF3025AIDBZT,这是一个高精度的2.5V电压基准芯片。其IN引脚接输入电压,OUT引脚提供2.5V的稳定输出,GND引脚接地。
  4. 输出电压:从OUT引脚输出2.5V电压,通过C52滤波,进一步稳定输出电压。C53是另一个滤波电容(0.1uF/50V),用于额外的高频滤波。
  5. 接地:GND标记的地方都接地,确保整个电路有一个共同的参考点。

简而言之,这个电路通过一个3.3V输入电压,经过滤波和稳压芯片处理后,输出一个稳定的2.5V电压,用于需要精确电压参考的电路部分。

五、编程

1.WREG (0100 rrnn)

在这里插入图片描述
在这里插入图片描述

  • 命令字节: 第一部分是固定的命令码,例如0100,专用于写操作。接下来的两位(rr)是起始寄存器地址,最后两位(nn)是除第一个寄存器外,额外想要写入的寄存器数量(即待写入字节数 - 1)。
  • 起始寄存器地址(rr00,表示从寄存器0开始。
  • 待写入的额外寄存器数量(nn01,表示除了第一个寄存器之外,还有一个寄存器要写入,总共是两个寄存器。
  • 命令码0100,固定为写命令。

因此,完整的命令字节为0100 0001

发送数据

  • 命令字节后随即发送的数据:在发送完命令字节之后,你需要继续发送数据字节。在这个例子中,如果nn = 01,则你需要发送nn + 1 = 2个数据字节。
ADS1256是一款高精度、低功耗的24位模数转换器(ADC),常用于电子测量、仪器仪表、传感器接口等领域。STM32F103是一款基于ARM Cortex-M3内核的微控制器,拥有丰富的外设资源,其中包括SPI接口。 为了驱动ADS1256,我们需要通过SPI接口与其进行通信。以下是基于STM32F103的ADS1256驱动程序示例: 首先,我们需要定义一些常量和变量: ``` #define ADS1256_SPI SPI1 #define ADS1256_CS GPIO_Pin_4 #define ADS1256_START 0x08 #define ADS1256_WAKEUP 0x00 #define ADS1256_RDATA 0x01 #define ADS1256_RDATAC 0x03 #define ADS1256_SDATAC 0x0F #define ADS1256_RREG 0x10 #define ADS1256_WREG 0x50 #define ADS1256_SELFCAL 0xF0 #define ADS1256_SELFOCAL 0xF1 #define ADS1256_SELFGCAL 0xF2 #define ADS1256_SYSOCAL 0xF3 #define ADS1256_SYSGCAL 0xF4 #define ADS1256_SYNC 0xFC #define ADS1256_STANDBY 0xFD #define ADS1256_RESET 0xFE uint8_t ADS1256_Buffer[3]; ``` 这里定义了SPI接口、ADS1256的CS引脚、ADS1256的指令常量以及一个用于缓存数据的数组。 接着,我们需要实现SPI的初始化函数: ``` void ADS1256_SPI_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = ADS1256_CS; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_Init(ADS1256_SPI, &SPI_InitStructure); SPI_Cmd(ADS1256_SPI, ENABLE); ADS1256_CS_HIGH(); } ``` 该函数首先初始化GPIO和SPI外设,并将ADS1256的CS引脚设置为输出模式。然后设置SPI的工作模式、传输速率等参数,并使能SPI外设。 接下来,我们可以编写一个函数用于向ADS1256发送指令: ``` void ADS1256_SendCommand(uint8_t command) { ADS1256_CS_LOW(); SPI_I2S_SendData(ADS1256_SPI, command); while (SPI_I2S_GetFlagStatus(ADS1256_SPI, SPI_I2S_FLAG_BSY) == SET); ADS1256_CS_HIGH(); } ``` 该函数将ADS1256的CS引脚拉低,发送指令,等待传输完成,然后将CS引脚拉高。 接着,我们可以编写一个函数用于向ADS1256写寄存器: ``` void ADS1256_WriteReg(uint8_t reg, uint8_t data) { ADS1256_CS_LOW(); ADS1256_Buffer[0] = ADS1256_WREG | reg; ADS1256_Buffer[1] = 0x00; ADS1256_Buffer[2] = data; SPI_I2S_SendData(ADS1256_SPI, ADS1256_Buffer[0]); while (SPI_I2S_GetFlagStatus(ADS1256_SPI, SPI_I2S_FLAG_BSY) == SET); SPI_I2S_SendData(ADS1256_SPI, ADS1256_Buffer[1]); while (SPI_I2S_GetFlagStatus(ADS1256_SPI, SPI_I2S_FLAG_BSY) == SET); SPI_I2S_SendData(ADS1256_SPI, ADS1256_Buffer[2]); while (SPI_I2S_GetFlagStatus(ADS1256_SPI, SPI_I2S_FLAG_BSY) == SET); ADS1256_CS_HIGH(); } ``` 该函数首先将ADS1256的CS引脚拉低,然后发送写寄存器指令和寄存器地址。接着,发送两个字节的数据,等待传输完成,最后将CS引脚拉高。 最后,我们可以编写一个函数用于从ADS1256读取数据: ``` int32_t ADS1256_ReadData(void) { uint32_t i; uint32_t timeout = 100000; ADS1256_CS_LOW(); ADS1256_Buffer[0] = ADS1256_RDATA; SPI_I2S_SendData(ADS1256_SPI, ADS1256_Buffer[0]); while (SPI_I2S_GetFlagStatus(ADS1256_SPI, SPI_I2S_FLAG_BSY) == SET); for (i = 0; i < 3; i++) { timeout = 100000; while (SPI_I2S_GetFlagStatus(ADS1256_SPI, SPI_I2S_FLAG_RXNE) == RESET) { if (--timeout == 0) { ADS1256_CS_HIGH(); return 0; } } ADS1256_Buffer[i] = SPI_I2S_ReceiveData(ADS1256_SPI); } ADS1256_CS_HIGH(); return ((int32_t)ADS1256_Buffer[0] << 16) | ((int32_t)ADS1256_Buffer[1] << 8) | ((int32_t)ADS1256_Buffer[2]); } ``` 该函数首先将ADS1256的CS引脚拉低,然后发送读数据指令。接着,循环读取三个字节的数据,等待传输完成,最后将CS引脚拉高。返回值为读取到的数据的24位有符号整数值。 以上就是基于STM32F103的ADS1256驱动程序示例。需要注意的是,该示例仅提供了基本的SPI通信和指令发送功能,具体的应用需要根据实际情况进行修改和完善。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值