STM32项目实战:协议检测工具

发布于:2025-07-01 ⋅ 阅读:(13) ⋅ 点赞:(0)

目录

使用说明

优化方向


        基于STM32F103C8T6设计了一个多协议检测工具,支持UART、I2C和SPI协议验证,通过串口输出测试结果。

        以下是一个基于STM32F103C8T6的常用协议检测工具代码框架,用于验证外设驱动是否正常工作。支持UART、I2C、SPI协议检测,通过USART1输出结果到串口助手。

#include "stm32f10x.h"
#include <stdio.h>

// 硬件定义
#define LED_PIN GPIO_Pin_13
#define LED_PORT GPIOC
#define TEST_PIN GPIO_Pin_0 // 用于协议检测的通用引脚

// 外设初始化
void init_clock(void) {
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | 
                          RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
}

void init_led(void) {
    GPIO_InitTypeDef gpio;
    gpio.GPIO_Pin = LED_PIN;
    gpio.GPIO_Mode = GPIO_Mode_Out_PP;
    gpio.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(LED_PORT, &gpio);
}

void init_usart(void) {
    // PA9-TX, PA10-RX
    GPIO_InitTypeDef gpio;
    gpio.GPIO_Pin = GPIO_Pin_9;
    gpio.GPIO_Mode = GPIO_Mode_AF_PP;
    gpio.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &gpio);
    
    gpio.GPIO_Pin = GPIO_Pin_10;
    gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &gpio);
    
    USART_InitTypeDef usart;
    usart.USART_BaudRate = 115200;
    usart.USART_WordLength = USART_WordLength_8b;
    usart.USART_StopBits = USART_StopBits_1;
    usart.USART_Parity = USART_Parity_No;
    usart.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
    usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_Init(USART1, &usart);
    
    USART_Cmd(USART1, ENABLE);
}

void init_i2c(void) {
    // PB6-SCL, PB7-SDA
    GPIO_InitTypeDef gpio;
    gpio.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    gpio.GPIO_Mode = GPIO_Mode_AF_OD;
    gpio.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &gpio);
    
    I2C_InitTypeDef i2c;
    i2c.I2C_Mode = I2C_Mode_I2C;
    i2c.I2C_DutyCycle = I2C_DutyCycle_2;
    i2c.I2C_OwnAddress1 = 0x48;
    i2c.I2C_Ack = I2C_Ack_Enable;
    i2c.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    i2c.I2C_ClockSpeed = 100000;
    I2C_Init(I2C1, &i2c);
    
    I2C_Cmd(I2C1, ENABLE);
}

void init_spi(void) {
    // PA5-SCK, PA6-MISO, PA7-MOSI
    GPIO_InitTypeDef gpio;
    gpio.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
    gpio.GPIO_Mode = GPIO_Mode_AF_PP;
    gpio.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &gpio);
    
    gpio.GPIO_Pin = GPIO_Pin_6;
    gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &gpio);
    
    SPI_InitTypeDef spi;
    spi.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    spi.SPI_Mode = SPI_Mode_Master;
    spi.SPI_DataSize = SPI_DataSize_8b;
    spi.SPI_CPOL = SPI_CPOL_Low;
    spi.SPI_CPHA = SPI_CPHA_1Edge;
    spi.SPI_NSS = SPI_NSS_Soft;
    spi.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
    spi.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_Init(SPI1, &spi);
    
    SPI_Cmd(SPI1, ENABLE);
}

// 工具函数
void print(char *str) {
    while(*str) {
        USART_SendData(USART1, *str++);
        while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
    }
}

// 协议检测函数
uint8_t test_uart(void) {
    // 使用USART1自发自收测试
    print("Testing UART...");
    USART_SendData(USART1, 0x55);
    while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
    return (USART_ReceiveData(USART1) == 0x55) ? 1 : 0;
}

uint8_t test_i2c(void) {
    print("Testing I2C...");
    // 尝试启动I2C总线
    I2C_GenerateSTART(I2C1, ENABLE);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
    
    // 发送虚拟设备地址
    I2C_Send7bitAddress(I2C1, 0x00, I2C_Direction_Transmitter);
    
    // 检测ACK失败表示总线正常
    if(I2C_GetFlagStatus(I2C1, I2C_FLAG_AF)) {
        I2C_ClearFlag(I2C1, I2C_FLAG_AF);
        return 1;  // 总线响应正常
    }
    return 0;
}

uint8_t test_spi(void) {
    print("Testing SPI...");
    // MOSI输出测试数据
    SPI_I2S_SendData(SPI1, 0xAA);
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
    
    // 检测回环数据(需短接MOSI和MISO)
    return (SPI_I2S_ReceiveData(SPI1) == 0xAA) ? 1 : 0;
}

int main(void) {
    // 初始化硬件
    init_clock();
    init_led();
    init_usart();
    init_i2c();
    init_spi();
    
    // 测试结果指示器
    GPIO_SetBits(LED_PORT, LED_PIN);
    
    print("\r\n Protocol Tester v1.0\r\n");
    
    while(1) {
        print("\r\n--- Testing Start ---");
        
        // UART测试
        print("\r\nUART: ");
        if(test_uart()) print("OK");
        else print("FAIL");
        
        // I2C测试
        print("\r\nI2C: ");
        if(test_i2c()) print("OK");
        else print("FAIL");
        
        // SPI测试
        print("\r\nSPI: ");
        if(test_spi()) print("OK");
        else print("FAIL");
        
        print("\r\n--- Test Complete ---\r\n");
        
        // LED闪烁指示测试完成
        for(uint8_t i=0; i<3; i++) {
            GPIO_ResetBits(LED_PORT, LED_PIN);
            for(int j=0; j<1000000; j++);
            GPIO_SetBits(LED_PORT, LED_PIN);
            for(int j=0; j<1000000; j++);
        }
    }
}

使用说明:

  1. 接线说明

    • USART:PA9(TX) - 连接USB转串口模块RX
    • I2C:PB6(SCL)/PB7(SDA) - 连接I2C设备
    • SPI:PA5(SCK)/PA6(MISO)/PA7(MOSI) - 测试时短接MISO和MOSI
    • LED:PC13 - 板上用户LED
  2. 测试准备

    • 将代码烧录到STM32F103C8T6
    • 使用串口助手(115200波特率)查看输出
    • 根据测试需求连接外设:
      • UART:无需外部连接
      • I2C:需要连接实际设备(如OLED/EEPROM)
      • SPI:测试时短接MISO和MOSI
  3. 测试输出示例

Protocol Tester v1.0

--- Testing Start ---
UART: OK
I2C: OK
SPI: OK
--- Test Complete ---

优化方向:

  1. 增加更多协议支持:

    // 添加CAN总线测试
    uint8_t test_can(void) {
      // CAN初始化及测试代码
    }
    
    // 添加1-Wire测试
    uint8_t test_onewire(void) {
      // 1-Wire初始化及测试代码
    }
  2. 增加参数化测试:

    void test_i2c_device(uint8_t addr) {
      // 指定地址设备测试
      print("Scanning device at 0x");
      print_hex(addr);
      // ...
    }
  3. 添加详细错误代码:

    if(!test_spi()) {
      print("SPI Error: ");
      if(SPI_I2S_GetFlagStatus(SPI1, SPI_FLAG_MODF))
        print("MODF Error");
      // ...
    }

该工具可快速验证STM32基础外设驱动状态,实际使用时需根据具体硬件调整引脚配置和测试逻辑。测试异常时需结合具体现象和调试工具进一步排查硬件连接及驱动问题。


网站公告

今日签到

点亮在社区的每一天
去签到