> 技术文档 > STM32使用MCP3208采集八通道应变片数据

STM32使用MCP3208采集八通道应变片数据


前言

        最近做了一个工程,使用stm32f103c8t6搭配MCP3208采集八通道的应变片数据,然后eeprom存储数据加CDC打印数据到上位机,这里记录一下MCP3208的驱动。

芯片介绍

        MCP3208 12位模数转换器(ADC),MCP3208具有逐次逼近寄存器(SAR)架构和行业标准SPI™串行接口,允许将12位ADC功能添加到任何PICmicro®单片机。 MCP3208具有100k采样/秒,8个输入通道,低功耗(典型待机5nA,最大400μA),采用16引脚PDIP和SOIC封装。

电路设计

        CH0-7这八个通道分别接到了八个应变片传感器上,CLK、DOUT、DIN、CS这四个连接到了STM32的硬件SPI上,由于项目比较简单这里并没有做数字和模拟地的隔离而是直接连接同一地平面。然后特别注意这里的VREF参考电压一定要小于等于VDD电源,我刚开始就是没注意导致后面读取不了数据。

CUBEMX配置

        前面的其他我就跳过了直接从SPI配置这里开始,MODE这里选Full-Duplex Master全双工模式,然后BaudRate这里:

  • 5V供电时:≤ 2M

  • 2.7V供电时:≤ 1M

读取代码实现

uint16_t MCP3208_ReadChannel(uint8_t channel){ uint8_t txData[3] = {0}; uint8_t rxData[3] = {0}; // 构建命令字节 (单端模式固定格式) txData[0] = 0x06 | ((channel >> 2) & 0x01); txData[1] = channel << 6;  // 拉低CS HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // SPI传输 HAL_SPI_TransmitReceive(&hspi1, txData, rxData, 3, HAL_MAX_DELAY); // 拉高CS HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // 处理接收数据 return ((rxData[1] & 0x0F) << 8) | rxData[2];}
 uint8_t txData[3] = {0}; uint8_t rxData[3] = {0};

txData用于存储要发送的数据,rxData用于存储接收的数据

txData[0] = 0x06 | ((channel >> 2) & 0x01); 
  • 构建第一个命令字节:

    • 0x06是固定格式:00000110(起始位1 + 单端模式1 + D2=0)

    • (channel >> 2) & 0x01:将通道号右移2位后与1进行AND操作,获取通道号的最高位(D2)

    • 组合后形成第一个字节:0000011x(x是通道号的最高位)

txData[1] = channel << 6;
  • 构建第二个命令字节:

    • 将通道号左移6位,将通道号的低2位(D1,D0)放到字节的最高2位

    • 例如,通道5(101)会变成 01000000

return ((rxData[1] & 0x0F) << 8) | rxData[2];
  • 处理接收到的数据:

    • rxData[1] & 0x0F:获取第二个接收字节的低4位(有效数据的高4位)

    • << 8:将高4位左移8位

    • | rxData[2]:与第三个接收字节(有效数据的低8位)组合

    • 返回12位的ADC值(0-4095)

代码使用

 for (int i = 0; i < 8; i++) { memset(text_buf, 0, sizeof(text_buf)); // 清空文本缓冲区 voltage_value[i] = MCP3208_ReadChannel(i); // 读取每个通道的ADC值 voltage_value[i] = voltage_value[i] * 5.0f / 4095.0f; // 计算电压值 sprintf(text_buf, \"Channel %d: %d %.1f\\r\\n\", i, (int)(voltage_value[i] * 1000 / 2.0f), voltage_value[i]); // 格式化字符串 CDC_Transmit_FS((uint8_t *)text_buf, strlen(text_buf)); // 发送ADC值到USB虚拟串口 HAL_Delay(1000); }