STM32单片机开发的串口双机模拟汽车电量里程项目,两个STM32单片机进行数据交互,模拟主控与驱动传感器发送数据,可以手动调节数据,并显示屏显示出来。 包括程序源码和protues仿真8.12版本。 程序源码注释详细。 非常适合开发人员,需要可以看下。

最近做了个超有趣的项目——基于STM32单片机开发的串口双机模拟汽车电量里程项目。在这个项目里,两个STM32单片机之间会进行数据交互,模拟主控与驱动传感器发送数据,而且还能手动调节数据,并通过显示屏显示出来。下面就跟大家详细唠唠。

一、项目原理

我们的项目核心在于两个STM32单片机的串口通信。其中一个单片机模拟主控,负责收集数据并发送给另一个模拟驱动传感器的单片机。同时,我们可以通过按键等方式手动调节电量和里程数据,再通过显示屏直观地呈现出来。

二、Protues仿真(8.12版本)

  1. 搭建电路
    - 首先在Protues中放置两个STM32F103C8T6单片机,这是我们常用的型号,资源丰富且容易上手。
    - 连接串口通信电路,将一个单片机的TX引脚连接到另一个单片机的RX引脚,反之亦然,这样就搭建好了串口通信的物理链路。
    - 添加按键用于手动调节数据,这里我们可以使用普通的轻触按键,一端接地,另一端连接到单片机的GPIO口。
    - 显示屏选择LCD1602,它能很好地满足我们显示简单数据的需求。按照引脚定义连接到单片机的GPIO口,注意电源和对比度调节引脚的连接。
  2. 仿真设置

在完成电路搭建后,我们需要对单片机进行设置,加载编译好的hex文件,就能开始仿真啦,观察各个数据的变化和显示情况。

三、程序源码及分析

主控单片机代码

#include "stm32f10x.h"
// 定义按键和LCD相关GPIO口
#define KEY_GPIO_PORT GPIOC
#define KEY_GPIO_CLK  RCC_APB2Periph_GPIOC
#define KEY1_PIN      GPIO_Pin_0
// LCD相关定义省略

void USART_Config(void) {
    USART_InitTypeDef USART_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

    // 使能串口和GPIO时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

    // 配置PA9(TX)为复用推挽输出
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置PA10(RX)为浮空输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 串口基本配置
    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);

    // 使能串口
    USART_Cmd(USART1, ENABLE);
}

void KEY_Config(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    // 使能按键GPIO时钟
    RCC_APB2PeriphClockCmd(KEY_GPIO_CLK, ENABLE);

    // 配置按键引脚为浮空输入
    GPIO_InitStructure.GPIO_Pin = KEY1_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(KEY_GPIO_PORT, &GPIO_InitStructure);
}

int main(void) {
    uint16_t mileage = 0;
    uint8_t power = 100;

    USART_Config();
    KEY_Config();
    // LCD初始化省略

    while (1) {
        if (GPIO_ReadInputDataBit(KEY_GPIO_PORT, KEY1_PIN) == 0) {
            // 按键按下,调节里程
            mileage += 10;
            while (GPIO_ReadInputDataBit(KEY_GPIO_PORT, KEY1_PIN) == 0);
        }
        // 手动调节电量代码省略

        // 将数据发送给从机
        char data[10];
        sprintf(data, "%d,%d", mileage, power);
        for (int i = 0; i < strlen(data); i++) {
            while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
            USART_SendData(USART1, data[i]);
        }

        // LCD显示数据省略
    }
}

在这段代码里,USARTConfig函数负责串口的初始化设置,包括波特率、数据位、停止位等关键参数。KEYConfig函数配置按键引脚。在main函数中,我们初始化了串口和按键,通过按键调节里程数据,再将里程和电量数据打包成字符串通过串口发送出去。

从机单片机代码

#include "stm32f10x.h"
// LCD相关定义省略

void USART_Config(void) {
    USART_InitTypeDef USART_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

    // 使能串口和GPIO时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

    // 配置PA9(TX)为复用推挽输出
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置PA10(RX)为浮空输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 串口基本配置
    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);

    // 使能串口
    USART_Cmd(USART1, ENABLE);
}

int main(void) {
    uint16_t mileage = 0;
    uint8_t power = 0;
    char data[10];
    uint8_t index = 0;

    USART_Config();
    // LCD初始化省略

    while (1) {
        if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE)!= RESET) {
            char temp = USART_ReceiveData(USART1);
            if (temp!= '\0') {
                data[index++] = temp;
            }
            if (temp == '\n') {
                data[index] = '\0';
                sscanf(data, "%d,%d", &mileage, &power);
                index = 0;
            }
        }
        // LCD显示接收到的数据省略
    }
}

从机代码的USART_Config函数和主机类似,负责串口初始化。在main函数中,不断检测串口接收中断,一旦接收到数据,就将数据存储起来,当接收到换行符时,解析出里程和电量数据,并在LCD上显示。

STM32单片机开发的串口双机模拟汽车电量里程项目,两个STM32单片机进行数据交互,模拟主控与驱动传感器发送数据,可以手动调节数据,并显示屏显示出来。 包括程序源码和protues仿真8.12版本。 程序源码注释详细。 非常适合开发人员,需要可以看下。

这个项目对于开发人员来说,无论是在串口通信,还是GPIO控制以及数据处理方面,都能积累不少经验,感兴趣的小伙伴不妨动手试试。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐