#ifndef ADC_PROCESS_H
#define ADC_PROCESS_H
#include "stm32g0xx_hal.h"
// 修正枚举名:添加ADC_PROC_前缀,避免与HAL库冲突
typedef enum {
ADC_PROC_CHANNEL_4 = 0, // 对应硬件ADC通道4
ADC_PROC_CHANNEL_5, // 对应硬件ADC通道5
ADC_PROC_CHANNEL_6, // 对应硬件ADC通道6
ADC_PROC_CHANNEL_7, // 对应硬件ADC通道7
ADC_PROC_CHANNEL_MAX
} ADC_ProcChannelTypeDef;
// ADC处理结构体(封装所有ADC相关数据)
typedef struct {
ADC_HandleTypeDef *hadc; // ADC句柄
DMA_HandleTypeDef *hdma; // DMA句柄
TIM_HandleTypeDef *htim; // 定时器句柄(用于数据更新)
uint16_t dma_buf[512]; // DMA接收缓冲区
uint16_t ch_buf[ADC_PROC_CHANNEL_MAX][30]; // 各通道循环缓冲区(深度30)
float ref_voltage; // 参考电压
float voltage_offset; // 电压偏移量
float calibration_factor; // 校准系数
uint16_t adc_offset; // 偏移量对应的ADC值
uint16_t average[ADC_PROC_CHANNEL_MAX];// 各通道平均值
uint8_t buf_index; // 循环缓冲区索引
} ADC_ProcessHandleTypeDef;
// 初始化ADC处理模块
HAL_StatusTypeDef AdcProcess_Init(ADC_ProcessHandleTypeDef *hadc_proc,
ADC_HandleTypeDef *hadc,
DMA_HandleTypeDef *hdma,
TIM_HandleTypeDef *htim);
// 获取通道平均值(对外接口)
uint16_t AdcProcess_GetAverage(ADC_ProcessHandleTypeDef *hadc_proc, ADC_ProcChannelTypeDef channel);
// DMA数据处理(定时器中断中调用)
void AdcProcess_HandleDMAData(ADC_ProcessHandleTypeDef *hadc_proc);
#endif // ADC_PROCESS_H
#include "adc_process.h"
#include <string.h>
// 初始化ADC处理模块
HAL_StatusTypeDef AdcProcess_Init(ADC_ProcessHandleTypeDef *hadc_proc,
ADC_HandleTypeDef *hadc,
DMA_HandleTypeDef *hdma,
TIM_HandleTypeDef *htim) {
if (hadc_proc == NULL || hadc == NULL || hdma == NULL || htim == NULL) {
return HAL_ERROR;
}
// 初始化句柄
hadc_proc->hadc = hadc;
hadc_proc->hdma = hdma;
hadc_proc->htim = htim;
// 校准参数配置
hadc_proc->ref_voltage = 2.5f;
hadc_proc->voltage_offset = 0.06f;
hadc_proc->calibration_factor = hadc_proc->ref_voltage / (hadc_proc->ref_voltage + 0.07f);
hadc_proc->adc_offset = (uint16_t)(hadc_proc->voltage_offset * 4095 / hadc_proc->ref_voltage);
// 清空缓冲区
memset(hadc_proc->dma_buf, 0, sizeof(hadc_proc->dma_buf));
for (uint8_t i = 0; i < ADC_PROC_CHANNEL_MAX; i++) {
memset(hadc_proc->ch_buf[i], 0, sizeof(hadc_proc->ch_buf[i]));
hadc_proc->average[i] = 0;
}
hadc_proc->buf_index = 0;
// 启动ADC DMA和定时器
HAL_ADC_Start_DMA(hadc, (uint32_t*)hadc_proc->dma_buf, sizeof(hadc_proc->dma_buf)/sizeof(uint16_t));
HAL_TIM_Base_Start_IT(htim);
return HAL_OK;
}
// 处理DMA数据,计算校准值和平均值
void AdcProcess_HandleDMAData(ADC_ProcessHandleTypeDef *hadc_proc) {
uint32_t ch_sum[ADC_PROC_CHANNEL_MAX] = {0};
uint16_t samples = 0;
// 1. 计算单次DMA缓冲区的各通道总和(映射:i+0=通道4,i+1=通道5,i+2=通道6,i+3=通道7)
for (uint16_t i = 0; i < sizeof(hadc_proc->dma_buf)/sizeof(uint16_t); i += ADC_PROC_CHANNEL_MAX) {
// 通道4:ADC_PROC_CHANNEL_4(索引0)
if (i + 0 < sizeof(hadc_proc->dma_buf)/sizeof(uint16_t)) {
ch_sum[ADC_PROC_CHANNEL_4] += hadc_proc->dma_buf[i + 0] & 0x0FFF;
}
// 通道5:ADC_PROC_CHANNEL_5(索引1)
if (i + 1 < sizeof(hadc_proc->dma_buf)/sizeof(uint16_t)) {
ch_sum[ADC_PROC_CHANNEL_5] += hadc_proc->dma_buf[i + 1] & 0x0FFF;
}
// 通道6:ADC_PROC_CHANNEL_6(索引2)
if (i + 2 < sizeof(hadc_proc->dma_buf)/sizeof(uint16_t)) {
ch_sum[ADC_PROC_CHANNEL_6] += hadc_proc->dma_buf[i + 2] & 0x0FFF;
}
// 通道7:ADC_PROC_CHANNEL_7(索引3)
if (i + 3 < sizeof(hadc_proc->dma_buf)/sizeof(uint16_t)) {
ch_sum[ADC_PROC_CHANNEL_7] += hadc_proc->dma_buf[i + 3] & 0x0FFF;
}
samples++;
}
// 2. 校准并存储到循环缓冲区
for (uint8_t ch = 0; ch < ADC_PROC_CHANNEL_MAX; ch++) {
uint16_t avg_single = (uint16_t)(ch_sum[ch] / samples);
// 校准:系数校准 + 偏移校准
uint16_t calibrated = (uint16_t)(avg_single * hadc_proc->calibration_factor);
calibrated = (calibrated > hadc_proc->adc_offset) ? (calibrated - hadc_proc->adc_offset) : 0;
hadc_proc->ch_buf[ch][hadc_proc->buf_index] = calibrated;
}
// 3. 计算循环缓冲区的平均值
for (uint8_t ch = 0; ch < ADC_PROC_CHANNEL_MAX; ch++) {
uint32_t total = 0;
for (uint8_t i = 0; i < 30; i++) {
total += hadc_proc->ch_buf[ch][i];
}
hadc_proc->average[ch] = (uint16_t)(total / 30);
}
// 4. 更新缓冲区索引
hadc_proc->buf_index = (hadc_proc->buf_index + 1) % 30;
}
// 获取通道平均值
uint16_t AdcProcess_GetAverage(ADC_ProcessHandleTypeDef *hadc_proc, ADC_ProcChannelTypeDef channel) {
if (channel >= ADC_PROC_CHANNEL_MAX) {
return 0;
}
return hadc_proc->average[channel];
}
#ifndef SENSOR_UART_H
#define SENSOR_UART_H
#include "stm32g0xx_hal.h"
#include <stdint.h>
// 传感器ID枚举
typedef enum {
SENSOR_ID_2 = 0,
SENSOR_ID_3,
SENSOR_ID_4,
SENSOR_ID_MAX
} SensorIDTypeDef;
// 传感器状态机状态
typedef enum {
SENSOR_STATE_IDLE = 0, // 空闲状态
SENSOR_STATE_SEND_REQ, // 发送请求状态
SENSOR_STATE_WAIT_RESP, // 等待响应状态
SENSOR_STATE_PROCESS_DATA // 处理数据状态
} SensorStateTypeDef;
// 传感器数据缓存结构体
typedef struct {
uint16_t reg_11; // 寄存器11数据
uint8_t updated; // 数据更新标志
uint32_t timestamp; // 时间戳
uint8_t valid; // 数据有效标志
} SensorDataCacheTypeDef;
// 传感器处理结构体(封装所有传感器相关数据)
typedef struct {
UART_HandleTypeDef *huart; // UART句柄
SensorIDTypeDef id; // 传感器ID
uint8_t dev_addr; // 设备地址
uint8_t func_code; // 功能码
uint8_t reg_addr; // 寄存器地址
uint8_t tx_buf[8]; // 发送缓冲区
uint8_t rx_buf[8]; // 接收缓冲区
SensorStateTypeDef state; // 状态机状态
uint32_t last_op_time; // 上次操作时间(ms)
uint16_t timeout; // 超时时间(ms)
uint8_t error_count; // 连续错误计数
uint8_t rx_ok_flag; // 接收完成标志
uint8_t rx_count; // 接收字节数
SensorDataCacheTypeDef data; // 数据缓存
} SensorUartHandleTypeDef;
// 初始化传感器
HAL_StatusTypeDef SensorUart_Init(SensorUartHandleTypeDef *hsensor,
SensorIDTypeDef id,
UART_HandleTypeDef *huart,
uint8_t dev_addr,
uint8_t func_code,
uint8_t reg_addr,
uint16_t timeout);
// 传感器状态机处理(非阻塞,主循环调用)
void SensorUart_Process(SensorUartHandleTypeDef *hsensor);
// 获取传感器数据(对外接口)
SensorDataCacheTypeDef SensorUart_GetData(SensorUartHandleTypeDef *hsensor);
// UART接收完成回调函数(需要在stm32g0xx_it.c中调用)
void SensorUart_RxCpltCallback(SensorUartHandleTypeDef *hsensor);
#endif // SENSOR_UART_H
#include "sensor_uart.h"
#include "delay.h"
#include "string.h"
// CRC计算函数(内部使用)
static uint16_t CRC16_CreatTx(uint8_t *buf, uint16_t len) {
uint16_t crc = 0;
uint8_t crc1 = 0, crc2 = 0;
for (uint8_t i = 0; i < len; i++) {
if (i % 2 == 0) crc1 += buf[i];
crc2 += buf[i];
}
crc = crc2 * crc1 * 7639;
return crc;
}
// CRC校验函数(内部使用)
static uint8_t CRC16_CheckRx(uint8_t *buf, uint16_t len) {
uint16_t crc_calc = 0, crc_rx = 0;
uint8_t crc1 = 0, crc2 = 0;
for (uint8_t i = 0; i < len - 2; i++) {
if (i % 2 == 0) crc1 += buf[i];
crc2 += buf[i];
}
crc_rx = (buf[len-2] << 8) | buf[len-1];
crc_calc = crc2 * crc1 * 7639;
return (crc_calc == crc_rx) ? 1 : 0;
}
// 初始化传感器
HAL_StatusTypeDef SensorUart_Init(SensorUartHandleTypeDef *hsensor,
SensorIDTypeDef id,
UART_HandleTypeDef *huart,
uint8_t dev_addr,
uint8_t func_code,
uint8_t reg_addr,
uint16_t timeout) {
if (hsensor == NULL || huart == NULL || id >= SENSOR_ID_MAX) {
return HAL_ERROR;
}
hsensor->id = id;
hsensor->huart = huart;
hsensor->dev_addr = dev_addr;
hsensor->func_code = func_code;
hsensor->reg_addr = reg_addr;
hsensor->timeout = timeout;
memset(hsensor->tx_buf, 0, sizeof(hsensor->tx_buf));
memset(hsensor->rx_buf, 0, sizeof(hsensor->rx_buf));
hsensor->state = SENSOR_STATE_IDLE;
hsensor->last_op_time = HAL_GetTick();
hsensor->error_count = 0;
hsensor->rx_ok_flag = 0;
hsensor->rx_count = 0;
hsensor->data = (SensorDataCacheTypeDef){0, 0, 0, 0};
return HAL_OK;
}
// 构建并发送请求帧(内部使用)
static HAL_StatusTypeDef SensorUart_SendRequest(SensorUartHandleTypeDef *hsensor) {
hsensor->tx_buf[0] = hsensor->dev_addr;
hsensor->tx_buf[1] = 0xAA;
hsensor->tx_buf[2] = hsensor->func_code;
hsensor->tx_buf[3] = hsensor->reg_addr;
hsensor->tx_buf[4] = 0x00;
hsensor->tx_buf[5] = 0x01;
uint16_t crc = CRC16_CreatTx(hsensor->tx_buf, 6);
hsensor->tx_buf[6] = (crc >> 8) & 0xFF;
hsensor->tx_buf[7] = crc & 0xFF;
// 发送数据并启动接收中断
HAL_UART_Abort(hsensor->huart);
hsensor->rx_ok_flag = 0;
hsensor->rx_count = 0;
memset(hsensor->rx_buf, 0, sizeof(hsensor->rx_buf));
if (HAL_UART_Transmit(hsensor->huart, hsensor->tx_buf, 8, 100) != HAL_OK) {
return HAL_ERROR;
}
return HAL_UART_Receive_IT(hsensor->huart, hsensor->rx_buf, 8);
}
// 处理接收数据(内部使用)
static void SensorUart_ProcessData(SensorUartHandleTypeDef *hsensor) {
if (hsensor->rx_count != 8) {
hsensor->error_count++;
hsensor->data.valid = 0;
return;
}
// 校验CRC和功能码
if (CRC16_CheckRx(hsensor->rx_buf, 8) && hsensor->rx_buf[2] == hsensor->func_code) {
hsensor->data.reg_11 = (hsensor->rx_buf[4] << 8) | hsensor->rx_buf[5];
hsensor->data.updated = 1;
hsensor->data.timestamp = HAL_GetTick();
hsensor->data.valid = 1;
hsensor->error_count = 0;
} else {
hsensor->error_count++;
hsensor->data.valid = 0;
}
// 错误计数上限
if (hsensor->error_count > 10) {
hsensor->error_count = 10;
}
}
// 传感器状态机处理(非阻塞)
void SensorUart_Process(SensorUartHandleTypeDef *hsensor) {
uint32_t current_time = HAL_GetTick();
uint32_t elapsed = (current_time >= hsensor->last_op_time) ?
(current_time - hsensor->last_op_time) :
(UINT32_MAX - hsensor->last_op_time + current_time + 1);
switch (hsensor->state) {
case SENSOR_STATE_IDLE:
// 空闲状态:间隔发送请求(10ms更新一次)
if (elapsed >= 10) {
if (SensorUart_SendRequest(hsensor) == HAL_OK) {
hsensor->state = SENSOR_STATE_WAIT_RESP;
hsensor->last_op_time = current_time;
}
}
break;
case SENSOR_STATE_WAIT_RESP:
// 等待响应:检查超时或接收完成
if (hsensor->rx_ok_flag) {
hsensor->rx_ok_flag = 0;
hsensor->state = SENSOR_STATE_PROCESS_DATA;
} else if (elapsed >= hsensor->timeout) {
hsensor->error_count++;
hsensor->data.valid = 0;
hsensor->state = SENSOR_STATE_IDLE;
}
break;
case SENSOR_STATE_PROCESS_DATA:
// 处理数据:校验并更新缓存
SensorUart_ProcessData(hsensor);
hsensor->state = SENSOR_STATE_IDLE;
hsensor->last_op_time = current_time;
break;
default:
hsensor->state = SENSOR_STATE_IDLE;
break;
}
}
// 获取传感器数据
SensorDataCacheTypeDef SensorUart_GetData(SensorUartHandleTypeDef *hsensor) {
SensorDataCacheTypeDef data = hsensor->data;
hsensor->data.updated = 0; // 重置更新标志
return data;
}
// UART接收完成回调
void SensorUart_RxCpltCallback(SensorUartHandleTypeDef *hsensor) {
hsensor->rx_count = 8;
hsensor->rx_ok_flag = 1;
}
#ifndef SOFT_I2C_H
#define SOFT_I2C_H
#include "stm32g0xx_hal.h"
#include "adc_process.h"
#include "sensor_uart.h"
// 配置参数
#define SW_I2C_SLAVE_ADDR 0x48
#define SW_I2C_SCL_PIN GPIO_PIN_6
#define SW_I2C_SDA_PIN GPIO_PIN_7
#define SW_I2C_SCL_PRT GPIOB
#define SW_I2C_SDA_PRT GPIOB
#define SW_I2C_TIMEOUT_MS 500
#define SW_I2C_BUF_SIZE 256
#define SW_I2C_HOST_FRAME_LEN 5
#define SW_I2C_SLAVE_FRAME_LEN 12
#define SW_I2C_FRAME_HEADER1 0x01
#define SW_I2C_FRAME_HEADER2 0xAA
// I2C状态枚举
typedef enum {
I2C_STATE_IDLE = 0,
I2C_STATE_START,
I2C_STATE_DATA,
I2C_STATE_ACK,
I2C_STATE_NACK,
I2C_STATE_STOP
} I2cStateTypeDef;
// I2C读写标志
typedef enum {
I2C_WRITE = 0,
I2C_READ
} I2cRwTypeDef;
// 环形缓冲区结构体
typedef struct {
uint8_t data[SW_I2C_BUF_SIZE];
uint16_t head;
uint16_t tail;
uint16_t count;
} I2cRingBufferTypeDef;
// I2C从机处理结构体(封装所有I2C相关数据)
typedef struct {
I2cStateTypeDef state; // I2C状态
I2cRwTypeDef rw; // 读写标志
uint8_t scl_fall_cnt; // SCL下降沿计数
uint8_t addr_match_flag; // 地址匹配标志
uint32_t start_ms; // 通信起始时间
uint8_t rx_buf[SW_I2C_BUF_SIZE];// 接收缓冲区
uint8_t tx_buf[SW_I2C_BUF_SIZE];// 发送缓冲区
uint8_t rx_idx; // 接收索引
uint8_t tx_idx; // 发送索引
uint8_t host_func_code; // 主机功能码
uint8_t frame_received; // 帧接收完成标志
uint8_t ignore_data; // 忽略数据标志
I2cRingBufferTypeDef rx_debug_buf; // 接收调试缓冲区
I2cRingBufferTypeDef tx_debug_buf; // 发送调试缓冲区
uint8_t last_tx_frame[SW_I2C_SLAVE_FRAME_LEN]; // 上次发送帧缓存
volatile uint8_t frame_updated; // 帧更新标志
// 外部模块句柄(通过初始化传入)
ADC_ProcessHandleTypeDef *hadc_proc;
SensorUartHandleTypeDef *hsensors[SENSOR_ID_MAX];
} SwI2cSlaveHandleTypeDef;
// 初始化I2C从机
HAL_StatusTypeDef SwI2cSlave_Init(SwI2cSlaveHandleTypeDef *hi2c,
ADC_ProcessHandleTypeDef *hadc_proc,
SensorUartHandleTypeDef *hsensors[SENSOR_ID_MAX]);
// I2C超时检查(主循环调用)
void SwI2cSlave_CheckTimeout(SwI2cSlaveHandleTypeDef *hi2c);
// I2C中断处理(EXTI4_15_IRQHandler中调用)
void SwI2cSlave_IRQHandler(SwI2cSlaveHandleTypeDef *hi2c);
// 读取调试缓冲区(对外接口)
int SwI2cSlave_ReadDebugRx(SwI2cSlaveHandleTypeDef *hi2c, uint8_t *byte);
int SwI2cSlave_ReadDebugTx(SwI2cSlaveHandleTypeDef *hi2c, uint8_t *byte);
#endif // SOFT_I2C_SLAVE_H
#include "soft_i2c.h"
#include <string.h>
// 环形缓冲区初始化(内部使用)
static void I2cRingBuffer_Init(I2cRingBufferTypeDef *buf) {
buf->head = 0;
buf->tail = 0;
buf->count = 0;
}
// 环形缓冲区写入(内部使用)
static void I2cRingBuffer_Write(I2cRingBufferTypeDef *buf, uint8_t byte) {
uint32_t primask = __get_PRIMASK();
__disable_irq();
if (buf->count < SW_I2C_BUF_SIZE) {
buf->data[buf->head] = byte;
buf->head = (buf->head + 1) % SW_I2C_BUF_SIZE;
buf->count++;
} else {
// 缓冲区满,覆盖最旧数据
buf->data[buf->head] = byte;
buf->head = (buf->head + 1) % SW_I2C_BUF_SIZE;
buf->tail = (buf->tail + 1) % SW_I2C_BUF_SIZE;
}
__set_PRIMASK(primask);
}
// 环形缓冲区读取(内部使用)
static int I2cRingBuffer_Read(I2cRingBufferTypeDef *buf, uint8_t *byte) {
if (buf->count == 0) {
return -1;
}
*byte = buf->data[buf->tail];
buf->tail = (buf->tail + 1) % SW_I2C_BUF_SIZE;
buf->count--;
return 0;
}
// 配置SDA为输入中断模式(内部使用)
static void SwI2cSlave_SetSdaIt(SwI2cSlaveHandleTypeDef *hi2c) {
GPIO_InitTypeDef gpio = {0};
gpio.Pin = SW_I2C_SDA_PIN;
gpio.Mode = GPIO_MODE_IT_RISING_FALLING;
gpio.Pull = GPIO_PULLUP;
gpio.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(SW_I2C_SDA_PRT, &gpio);
}
// 配置SDA为开漏输出(内部使用)
static void SwI2cSlave_SetSdaOut(SwI2cSlaveHandleTypeDef *hi2c) {
GPIO_InitTypeDef gpio = {0};
gpio.Pin = SW_I2C_SDA_PIN;
gpio.Mode = GPIO_MODE_OUTPUT_OD;
gpio.Pull = GPIO_PULLUP;
gpio.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(SW_I2C_SDA_PRT, &gpio);
}
// 异或校验(内部使用)
static uint8_t SwI2cSlave_CalcXorChecksum(uint8_t *buf, uint8_t len) {
uint8_t checksum = 0;
for (uint8_t i = 0; i < len; i++) {
checksum ^= buf[i];
}
return checksum;
}
// 解析主机帧(内部使用)
static uint8_t SwI2cSlave_ParseHostFrame(SwI2cSlaveHandleTypeDef *hi2c) {
if (hi2c->rx_idx != SW_I2C_HOST_FRAME_LEN) return 0;
if (hi2c->rx_buf[1] != SW_I2C_FRAME_HEADER1 || hi2c->rx_buf[2] != SW_I2C_FRAME_HEADER2) return 0;
uint8_t crc = SwI2cSlave_CalcXorChecksum(&hi2c->rx_buf[1], 3);
if (crc != hi2c->rx_buf[4]) return 0;
hi2c->host_func_code = hi2c->rx_buf[3];
return 1;
}
// 准备发送帧(内部使用)
static void SwI2cSlave_PrepareTxFrame(SwI2cSlaveHandleTypeDef *hi2c) {
uint32_t primask = __get_PRIMASK();
__disable_irq();
// 填充帧头
hi2c->tx_buf[0] = SW_I2C_FRAME_HEADER1;
hi2c->tx_buf[1] = SW_I2C_FRAME_HEADER2;
hi2c->tx_buf[2] = hi2c->host_func_code;
// 清空数据区
memset(&hi2c->tx_buf[3], 0, 8);
// 根据功能码填充数据
switch (hi2c->host_func_code) {
case 0x01: // ADC数据(使用修正后的ADC通道枚举)
hi2c->tx_buf[3] = (AdcProcess_GetAverage(hi2c->hadc_proc, ADC_PROC_CHANNEL_4) >> 8) & 0xFF;
hi2c->tx_buf[4] = AdcProcess_GetAverage(hi2c->hadc_proc, ADC_PROC_CHANNEL_4) & 0xFF;
hi2c->tx_buf[5] = (AdcProcess_GetAverage(hi2c->hadc_proc, ADC_PROC_CHANNEL_5) >> 8) & 0xFF;
hi2c->tx_buf[6] = AdcProcess_GetAverage(hi2c->hadc_proc, ADC_PROC_CHANNEL_5) & 0xFF;
hi2c->tx_buf[7] = (AdcProcess_GetAverage(hi2c->hadc_proc, ADC_PROC_CHANNEL_6) >> 8) & 0xFF;
hi2c->tx_buf[8] = AdcProcess_GetAverage(hi2c->hadc_proc, ADC_PROC_CHANNEL_6) & 0xFF;
hi2c->tx_buf[9] = (AdcProcess_GetAverage(hi2c->hadc_proc, ADC_PROC_CHANNEL_7) >> 8) & 0xFF;
hi2c->tx_buf[10] = AdcProcess_GetAverage(hi2c->hadc_proc, ADC_PROC_CHANNEL_7) & 0xFF;
break;
case 0x02:
{ // 传感器数据
SensorDataCacheTypeDef sensor2 = SensorUart_GetData(hi2c->hsensors[SENSOR_ID_2]);
SensorDataCacheTypeDef sensor3 = SensorUart_GetData(hi2c->hsensors[SENSOR_ID_3]);
SensorDataCacheTypeDef sensor4 = SensorUart_GetData(hi2c->hsensors[SENSOR_ID_4]);
hi2c->tx_buf[3] = sensor2.valid ? (sensor2.reg_11 >> 8) : 0xFF;
hi2c->tx_buf[4] = sensor2.valid ? (sensor2.reg_11 & 0xFF) : 0xFF;
hi2c->tx_buf[5] = sensor3.valid ? (sensor3.reg_11 >> 8) : 0xFF;
hi2c->tx_buf[6] = sensor3.valid ? (sensor3.reg_11 & 0xFF) : 0xFF;
hi2c->tx_buf[7] = sensor4.valid ? (sensor4.reg_11 >> 8) : 0xFF;
hi2c->tx_buf[8] = sensor4.valid ? (sensor4.reg_11 & 0xFF) : 0xFF;
}
break;
default:
hi2c->tx_buf[2] = 0xFF; // 错误标识
break;
}
// 计算校验和
hi2c->tx_buf[11] = SwI2cSlave_CalcXorChecksum(hi2c->tx_buf, 11);
// 保存上次发送帧
memcpy(hi2c->last_tx_frame, hi2c->tx_buf, SW_I2C_SLAVE_FRAME_LEN);
hi2c->frame_updated = 1;
__set_PRIMASK(primask);
}
// 初始化I2C从机
HAL_StatusTypeDef SwI2cSlave_Init(SwI2cSlaveHandleTypeDef *hi2c,
ADC_ProcessHandleTypeDef *hadc_proc,
SensorUartHandleTypeDef *hsensors[SENSOR_ID_MAX]) {
if (hi2c == NULL || hadc_proc == NULL || hsensors == NULL) {
return HAL_ERROR;
}
// 保存外部模块句柄
hi2c->hadc_proc = hadc_proc;
for (uint8_t i = 0; i < SENSOR_ID_MAX; i++) {
hi2c->hsensors[i] = hsensors[i];
}
// 初始化状态和缓冲区
hi2c->state = I2C_STATE_IDLE;
hi2c->rw = I2C_WRITE;
hi2c->scl_fall_cnt = 0;
hi2c->addr_match_flag = 0;
hi2c->start_ms = 0;
hi2c->rx_idx = 0;
hi2c->tx_idx = 0;
hi2c->host_func_code = 0x00;
hi2c->frame_received = 0;
hi2c->ignore_data = 0;
hi2c->frame_updated = 0;
memset(hi2c->rx_buf, 0, sizeof(hi2c->rx_buf));
memset(hi2c->tx_buf, 0, sizeof(hi2c->tx_buf));
memset(hi2c->last_tx_frame, 0, sizeof(hi2c->last_tx_frame));
I2cRingBuffer_Init(&hi2c->rx_debug_buf);
I2cRingBuffer_Init(&hi2c->tx_debug_buf);
// 初始化GPIO
GPIO_InitTypeDef gpio = {0};
__HAL_RCC_GPIOB_CLK_ENABLE();
// SCL引脚:输入中断(上升/下降沿)
gpio.Pin = SW_I2C_SCL_PIN;
gpio.Mode = GPIO_MODE_IT_RISING_FALLING;
gpio.Pull = GPIO_PULLUP;
gpio.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(SW_I2C_SCL_PRT, &gpio);
// SDA引脚:初始为输入中断
SwI2cSlave_SetSdaIt(hi2c);
// 配置中断
HAL_NVIC_SetPriority(EXTI4_15_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);
// 准备默认发送帧
SwI2cSlave_PrepareTxFrame(hi2c);
return HAL_OK;
}
// 超时检查
void SwI2cSlave_CheckTimeout(SwI2cSlaveHandleTypeDef *hi2c) {
if (hi2c->state == I2C_STATE_IDLE) return;
uint32_t current_ms = HAL_GetTick();
uint32_t elapsed = (current_ms >= hi2c->start_ms) ?
(current_ms - hi2c->start_ms) :
(UINT32_MAX - hi2c->start_ms + current_ms + 1);
if (elapsed >= SW_I2C_TIMEOUT_MS) {
// 超时重置
hi2c->state = I2C_STATE_IDLE;
hi2c->rx_idx = 0;
hi2c->tx_idx = 0;
hi2c->frame_received = 0;
hi2c->host_func_code = 0x00;
hi2c->ignore_data = 0;
HAL_GPIO_WritePin(SW_I2C_SDA_PRT, SW_I2C_SDA_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(SW_I2C_SCL_PRT, SW_I2C_SCL_PIN, GPIO_PIN_SET);
SwI2cSlave_SetSdaIt(hi2c);
}
}
// 中断处理函数
void SwI2cSlave_IRQHandler(SwI2cSlaveHandleTypeDef *hi2c) {
// 清除中断标志
if (__HAL_GPIO_EXTI_GET_IT(SW_I2C_SCL_PIN)) {
__HAL_GPIO_EXTI_CLEAR_IT(SW_I2C_SCL_PIN);
}
if (__HAL_GPIO_EXTI_GET_IT(SW_I2C_SDA_PIN)) {
__HAL_GPIO_EXTI_CLEAR_IT(SW_I2C_SDA_PIN);
}
hi2c->start_ms = HAL_GetTick();
uint8_t scl_level = HAL_GPIO_ReadPin(SW_I2C_SCL_PRT, SW_I2C_SCL_PIN);
uint8_t sda_level = HAL_GPIO_ReadPin(SW_I2C_SDA_PRT, SW_I2C_SDA_PIN);
// 处理SDA中断(起始/停止条件)
if (__HAL_GPIO_EXTI_GET_IT(SW_I2C_SDA_PIN)) {
if (sda_level == GPIO_PIN_RESET && scl_level == GPIO_PIN_SET) {
// 起始条件
hi2c->state = I2C_STATE_START;
hi2c->rx_idx = 0;
hi2c->tx_idx = 0;
hi2c->ignore_data = 0;
SwI2cSlave_SetSdaIt(hi2c);
} else if (sda_level == GPIO_PIN_SET && scl_level == GPIO_PIN_SET) {
// 停止条件
hi2c->state = I2C_STATE_IDLE;
hi2c->rx_idx = 0;
hi2c->tx_idx = 0;
hi2c->ignore_data = 0;
SwI2cSlave_SetSdaIt(hi2c);
}
}
// 处理SCL中断(数据传输)
if (__HAL_GPIO_EXTI_GET_IT(SW_I2C_SCL_PIN)) {
if (scl_level == GPIO_PIN_RESET) {
// SCL下降沿
switch (hi2c->state) {
case I2C_STATE_START:
hi2c->scl_fall_cnt = 0;
hi2c->rx_buf[hi2c->rx_idx] = 0;
hi2c->state = I2C_STATE_DATA;
SwI2cSlave_SetSdaIt(hi2c);
break;
case I2C_STATE_DATA:
hi2c->scl_fall_cnt++;
if (hi2c->rw == I2C_READ) {
// 发送数据
SwI2cSlave_SetSdaOut(hi2c);
if (hi2c->tx_idx < SW_I2C_SLAVE_FRAME_LEN) {
uint8_t bit = (hi2c->tx_buf[hi2c->tx_idx] >> (7 - hi2c->scl_fall_cnt)) & 0x01;
HAL_GPIO_WritePin(SW_I2C_SDA_PRT, SW_I2C_SDA_PIN, bit ? GPIO_PIN_SET : GPIO_PIN_RESET);
} else {
HAL_GPIO_WritePin(SW_I2C_SDA_PRT, SW_I2C_SDA_PIN, GPIO_PIN_SET);
}
} else {
SwI2cSlave_SetSdaIt(hi2c);
}
// 8位数据传输完成,准备ACK
if (hi2c->scl_fall_cnt == 8) {
if (hi2c->rw == I2C_WRITE) {
// 地址匹配检查
if (hi2c->rx_idx == 0) {
if ((hi2c->rx_buf[0] & 0xFE) == (SW_I2C_SLAVE_ADDR << 1)) {
hi2c->addr_match_flag = 1;
hi2c->rw = (I2cRwTypeDef)(hi2c->rx_buf[0] & 0x01);
if (hi2c->rw == I2C_READ) {
SwI2cSlave_PrepareTxFrame(hi2c);
}
}
}
// 发送ACK/NACK
SwI2cSlave_SetSdaOut(hi2c);
if (hi2c->addr_match_flag) {
HAL_GPIO_WritePin(SW_I2C_SDA_PRT, SW_I2C_SDA_PIN, GPIO_PIN_RESET);
} else {
HAL_GPIO_WritePin(SW_I2C_SDA_PRT, SW_I2C_SDA_PIN, GPIO_PIN_SET);
}
} else {
SwI2cSlave_SetSdaIt(hi2c);
}
// 调试日志
if (hi2c->rw == I2C_WRITE && hi2c->addr_match_flag) {
I2cRingBuffer_Write(&hi2c->rx_debug_buf, hi2c->rx_buf[hi2c->rx_idx]);
}
if (hi2c->rw == I2C_READ) {
I2cRingBuffer_Write(&hi2c->tx_debug_buf, hi2c->tx_buf[hi2c->tx_idx]);
}
hi2c->state = I2C_STATE_ACK;
}
break;
case I2C_STATE_ACK:
if (hi2c->rw == I2C_WRITE) {
SwI2cSlave_SetSdaIt(hi2c);
HAL_GPIO_WritePin(SW_I2C_SDA_PRT, SW_I2C_SDA_PIN, GPIO_PIN_SET);
// 更新接收索引
if (!hi2c->ignore_data) {
hi2c->rx_idx++;
if (hi2c->rx_idx >= SW_I2C_HOST_FRAME_LEN) {
hi2c->ignore_data = 1;
if (SwI2cSlave_ParseHostFrame(hi2c)) {
hi2c->frame_received = 1;
SwI2cSlave_PrepareTxFrame(hi2c);
}
hi2c->rx_idx = 0;
}
}
if (!hi2c->ignore_data && hi2c->rx_idx < SW_I2C_BUF_SIZE) {
hi2c->rx_buf[hi2c->rx_idx] = 0;
}
hi2c->scl_fall_cnt = 0;
hi2c->state = I2C_STATE_DATA;
} else {
if (hi2c->state == I2C_STATE_NACK) {
HAL_GPIO_WritePin(SW_I2C_SDA_PRT, SW_I2C_SDA_PIN, GPIO_PIN_SET);
hi2c->state = I2C_STATE_IDLE;
SwI2cSlave_SetSdaIt(hi2c);
} else if (hi2c->tx_idx < SW_I2C_SLAVE_FRAME_LEN - 1) {
hi2c->tx_idx++;
hi2c->scl_fall_cnt = 0;
hi2c->state = I2C_STATE_DATA;
}
}
break;
case I2C_STATE_NACK:
hi2c->scl_fall_cnt = 0;
HAL_GPIO_WritePin(SW_I2C_SDA_PRT, SW_I2C_SDA_PIN, GPIO_PIN_SET);
SwI2cSlave_SetSdaIt(hi2c);
hi2c->state = I2C_STATE_IDLE;
break;
default:
hi2c->state = I2C_STATE_IDLE;
break;
}
} else {
// SCL上升沿
if (hi2c->state == I2C_STATE_DATA && hi2c->rw == I2C_WRITE && !hi2c->ignore_data) {
// 读取数据位
if (sda_level == GPIO_PIN_SET) {
hi2c->rx_buf[hi2c->rx_idx] |= (1 << (7 - hi2c->scl_fall_cnt));
}
} else if (hi2c->state == I2C_STATE_ACK && hi2c->rw == I2C_READ) {
// 检测主机ACK/NACK
if (sda_level == GPIO_PIN_SET) {
hi2c->state = I2C_STATE_NACK;
SwI2cSlave_SetSdaIt(hi2c);
} else if (hi2c->tx_idx >= SW_I2C_SLAVE_FRAME_LEN - 1) {
hi2c->state = I2C_STATE_NACK;
SwI2cSlave_SetSdaIt(hi2c);
}
}
}
}
}
// 读取调试接收缓冲区
int SwI2cSlave_ReadDebugRx(SwI2cSlaveHandleTypeDef *hi2c, uint8_t *byte) {
return I2cRingBuffer_Read(&hi2c->rx_debug_buf, byte);
}
// 读取调试发送缓冲区
int SwI2cSlave_ReadDebugTx(SwI2cSlaveHandleTypeDef *hi2c, uint8_t *byte) {
return I2cRingBuffer_Read(&hi2c->tx_debug_buf, byte);
}
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "delay.h"
#include "soft_i2c.h"
#include "stm32g0xx_hal.h"
#include <string.h>
#include <stdio.h>
#include "stm32g0xx_it.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
//typedef uint32_t u32;
//typedef uint16_t u16;
//typedef uint8_t u8;
//typedef const uint8_t uc8;
//
//#ifndef __cplusplus
//typedef enum {FALSE = 0, TRUE = !FALSE} bool;
//#endif
// 模块句柄实例(全局,仅主函数和中断使用)
static ADC_ProcessHandleTypeDef hadc_proc;
static SensorUartHandleTypeDef hsensor2, hsensor3, hsensor4;
static SensorUartHandleTypeDef *hsensors[SENSOR_ID_MAX] = {&hsensor2, &hsensor3, &hsensor4};
static SwI2cSlaveHandleTypeDef hi2c_slave;
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
// 重定向printf到USART1(调试用)
int fputc(int ch, FILE *f) {
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
int __io_putchar(int ch) {
HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, HAL_MAX_DELAY);
return ch;
}
// 定时器3中断回调(ADC数据更新)
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
if (htim == &htim3) {
AdcProcess_HandleDMAData(&hadc_proc);
}
}
// UART接收完成回调(传感器)
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (huart == &huart2) {
SensorUart_RxCpltCallback(&hsensor2);
} else if (huart == &huart3) {
SensorUart_RxCpltCallback(&hsensor3);
} else if (huart == &huart4) {
SensorUart_RxCpltCallback(&hsensor4);
}
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
MX_USART3_UART_Init();
MX_USART4_UART_Init();
MX_TIM3_Init();
MX_TIM2_Init();
/* USER CODE BEGIN 2 */
// 初始化各模块
AdcProcess_Init(&hadc_proc, &hadc1, &hdma_adc1, &htim3);
SensorUart_Init(&hsensor2, SENSOR_ID_2, &huart2, 0x01, 0x03, 0x0B, 500); // 寄存器11=0x0B
SensorUart_Init(&hsensor3, SENSOR_ID_3, &huart3, 0x01, 0x03, 0x0B, 500);
SensorUart_Init(&hsensor4, SENSOR_ID_4, &huart4, 0x01, 0x03, 0x0B, 500);
SwI2cSlave_Init(&hi2c_slave, &hadc_proc, hsensors);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
// 处理3个传感器的状态机(并行非阻塞)
SensorUart_Process(&hsensor2);
SensorUart_Process(&hsensor3);
SensorUart_Process(&hsensor4);
// 处理I2C超时
SwI2cSlave_CheckTimeout(&hi2c_slave);
// 调试日志打印(可选,注释可关闭)
uint8_t byte;
while (SwI2cSlave_ReadDebugRx(&hi2c_slave, &byte) == 0) {
printf("I2C RX: 0x%02X\r\n", byte);
}
while (SwI2cSlave_ReadDebugTx(&hi2c_slave, &byte) == 0) {
printf("I2C TX: 0x%02X\r\n", byte);
}
if (hi2c_slave.frame_updated) {
hi2c_slave.frame_updated = 0;
printf("I2C Prepared TX Frame: ");
for (uint8_t i = 0; i < SW_I2C_SLAVE_FRAME_LEN; i++) {
printf("%02X ", hi2c_slave.last_tx_frame[i]);
}
printf("\r\n");
}
HAL_Delay(10);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
RCC_OscInitStruct.PLL.PLLN = 8;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
检查代码逻辑以及复杂度
最新发布