2025年4月8日 星期二 乙巳(蛇)年 正月初九 设为首页 加入收藏
rss
您当前的位置:首页 > 电子 > 单片机

基于单片机的简易智能电动车设计

时间:11-06来源:作者:点击数:

一、项目介绍

智能交通工具在现代社会中起着越来越重要的作用,电动车作为一种环保、便捷的交通工具,受到了广泛的关注和应用。本设计基于单片机技术,设计一款简易智能电动车,实现基本的控制和功能,并提供良好的用户体验。

image-20230712103932570
image-20230712103656408

二、硬件选型

【1】主控芯片:STC89C52

  • STC89C52是一款功能强大的单片机,具有51系列兼容性和丰富的外设接口。
  • 它具有8位CPU,可运行高达12MHz的时钟频率,提供了丰富的IO口、定时器和串口等功能,非常适合用于电动车控制。
  • STC89C52具有低功耗和高性能的特点,能够满足电动车系统的控制需求。

【2】电动机驱动芯片:选择L298N驱动芯片

  • 根据电动机的参数,如电压、电流和功率进行匹配选择L298N驱动芯片。
  • 常用的电动机驱动芯片有L298N、TB6612FNG等,都具有较高的工作电压和电流能力,适合于小型电动车的驱动。

【3】电源管理模块:

  • 电源管理模块用于电动车的电源供应和电池管理。
  • 选择TP4056电源管理芯片,TP4056充电管理芯片,用于电池的充电管理和保护。
  • 使用LM2596开关电源芯片,LM2596可以提供稳定的电源电压给各个模块。

【4】用户界面:

  • 用户界面模块采用LCD显示屏和按键元件。
  • LCD显示屏选择LCD1602字符型液晶显示屏,用于显示电动车的状态信息。
  • 按键用于用户的输入和操作。

【5】传感器:

  • 传感器模块用于实时监测电动车的状态和环境信息。
  • 选择速度传感器、温度传感器、倾斜传感器。
  • 速度传感器选择霍尔传感器,用于测量电动车的速度。
  • 温度传感器选择DS18B20数字温度传感器,用于测量电动车的温度。
  • 倾斜传感器选择倾斜传感器模块,用于检测电动车的倾斜状态。

三、系统框架总结

【1】主控单元

主控单元使用STC89C52单片机,负责整个系统的控制和协调。通过编程控制IO口和定时器等功能,实现电动车的速度控制、转向控制和状态监测等操作。主控单元还负责与其他模块之间的通信和数据交换。

【2】电动机驱动

电动机驱动模块使用适当的电机驱动芯片,根据主控单元的指令控制电动机的启动、停止和速度调节。通过PWM信号调节电机的转速,实现电动车的前进、后退和制动等功能。

【3】电源管理

电源管理模块负责电动车的电源供应和电池管理。包括电池充电管理、电池电量检测和电源开关控制等功能。通过合理管理电池的使用和充电,保证电动车的正常运行和安全性。

【4】用户界面

用户界面模块提供给用户操作和显示的接口。采用LCD显示屏和按键元件,用于显示电动车的状态信息和用户输入的指令。用户可以通过按键来控制电动车的启动、停止和速度调节等操作。

【5】传感器

传感器模块用于实时监测电动车的状态和环境信息。选择速度传感器、温度传感器和倾斜传感器。通过传感器获取的数据,可以用于电动车的自动控制和保护。

【6】功能实现

本设计的功能包括电动车的启动和停止、速度调节、转向控制和状态监测等。用户可以通过按键来启动和停止电动车,通过调节速度控制电动车的前进和后退,通过转向控制实现电动车的转向操作。同时,系统可以实时监测电动车的状态,如电池电量、速度和温度等,并进行相应的保护和提示。

四、代码实现

4.1 电机控制代码

  • #include <reg52.h> // 引入STC89C52头文件
  • // 定义IO口连接
  • sbit motorPin1 = P1^0; // 电动机引脚1
  • sbit motorPin2 = P1^1; // 电动机引脚2
  • sbit buttonStart = P2^0; // 启动按钮
  • sbit buttonStop = P2^1; // 停止按钮
  • // 定义全局变量
  • bit isRunning = 0; // 电动车运行状态
  • // 函数声明
  • void delay(unsigned int time);
  • void motorForward();
  • void motorBackward();
  • void motorStop();
  • // 主函数
  • void main() {
  • buttonStart = 1; // 设置启动按钮为输入
  • buttonStop = 1; // 设置停止按钮为输入
  • while (1) {
  • if (buttonStart == 0) { // 按下启动按钮
  • motorForward(); // 电动车前进
  • isRunning = 1; // 设置运行状态为1
  • }
  • if (buttonStop == 0) { // 按下停止按钮
  • motorStop(); // 电动车停止
  • isRunning = 0; // 设置运行状态为0
  • }
  • if (isRunning) {
  • // 电动车正在运行,可以进行其他操作
  • // 可以根据需要添加其他功能的代码
  • }
  • }
  • }
  • // 延时函数
  • void delay(unsigned int time) {
  • unsigned int i, j;
  • for (i = 0; i < time; i++)
  • for (j = 0; j < 120; j++);
  • }
  • // 电动车前进函数
  • void motorForward() {
  • motorPin1 = 1; // 设置电动机引脚1为高电平
  • motorPin2 = 0; // 设置电动机引脚2为低电平
  • }
  • // 电动车后退函数
  • void motorBackward() {
  • motorPin1 = 0; // 设置电动机引脚1为低电平
  • motorPin2 = 1; // 设置电动机引脚2为高电平
  • }
  • // 电动车停止函数
  • void motorStop() {
  • motorPin1 = 0; // 设置电动机引脚1为低电平
  • motorPin2 = 0; // 设置电动机引脚2为低电平
  • }

4.2 LCD1602显示屏驱动代码

  • #include <reg52.h> // 引入STC89C52头文件
  • // 定义LCD1602连接的引脚
  • sbit RS = P1^0; // RS引脚
  • sbit EN = P1^1; // EN引脚
  • sbit D4 = P2^4; // 数据线D4引脚
  • sbit D5 = P2^5; // 数据线D5引脚
  • sbit D6 = P2^6; // 数据线D6引脚
  • sbit D7 = P2^7; // 数据线D7引脚
  • // 函数声明
  • void delay(unsigned int time);
  • void lcdCommand(unsigned char command);
  • void lcdData(unsigned char data);
  • void lcdInit();
  • void lcdDisplayString(char *string);
  • // 主函数
  • void main() {
  • lcdInit(); // 初始化LCD1602显示屏
  • // 显示字符 "20k/h"
  • lcdDisplayString("20k/h");
  • while (1) {
  • // 可以在此处添加其他代码,实现其他功能
  • }
  • }
  • // 延时函数
  • void delay(unsigned int time) {
  • unsigned int i, j;
  • for (i = 0; i < time; i++)
  • for (j = 0; j < 120; j++);
  • }
  • // 发送指令到LCD1602
  • void lcdCommand(unsigned char command) {
  • RS = 0; // 设置RS引脚为低电平,表示发送指令
  • EN = 1; // 设置EN引脚为高电平,使能LCD
  • P2 = command; // 将指令写入数据线
  • delay(1); // 延时一段时间
  • EN = 0; // 设置EN引脚为低电平,禁止LCD
  • }
  • // 发送数据到LCD1602
  • void lcdData(unsigned char data) {
  • RS = 1; // 设置RS引脚为高电平,表示发送数据
  • EN = 1; // 设置EN引脚为高电平,使能LCD
  • P2 = data; // 将数据写入数据线
  • delay(1); // 延时一段时间
  • EN = 0; // 设置EN引脚为低电平,禁止LCD
  • }
  • // 初始化LCD1602
  • void lcdInit() {
  • lcdCommand(0x38); // 初始化,设置显示模式为2行、5x8点阵
  • lcdCommand(0x0C); // 开启显示,关闭光标
  • lcdCommand(0x06); // 设置光标移动方向为右移
  • lcdCommand(0x01); // 清屏
  • }
  • // 在LCD1602显示屏上显示字符串
  • void lcdDisplayString(char *string) {
  • while (*string) {
  • lcdData(*string++);
  • }
  • }

4.3 MPU6050驱动代码

  • #include <reg52.h> // 引入STC89C52头文件
  • // 定义MPU6050连接的引脚
  • sbit SDA = P2^0; // I2C数据线引脚
  • sbit SCL = P2^1; // I2C时钟线引脚
  • // 定义MPU6050的地址
  • #define MPU6050_ADDRESS 0xD0
  • // 函数声明
  • void delay(unsigned int time);
  • void i2cStart();
  • void i2cStop();
  • bit i2cSendByte(unsigned char byte);
  • unsigned char i2cReceiveByte();
  • void mpu6050Init();
  • void mpu6050ReadData(short *accelData, short *gyroData);
  • // 主函数
  • void main() {
  • short accelData[3]; // 存储加速度值的数组
  • short gyroData[3]; // 存储陀螺仪值的数组
  • mpu6050Init(); // 初始化MPU6050模块
  • while (1) {
  • mpu6050ReadData(accelData, gyroData); // 读取加速度值和陀螺仪值
  • // 打印加速度值和陀螺仪值到串口
  • printf("Accelerometer: X=%d, Y=%d, Z=%d\r\n", accelData[0], accelData[1], accelData[2]);
  • printf("Gyroscope: X=%d, Y=%d, Z=%d\r\n", gyroData[0], gyroData[1], gyroData[2]);
  • delay(1000); // 延时一段时间
  • }
  • }
  • // 延时函数
  • void delay(unsigned int time) {
  • unsigned int i, j;
  • for (i = 0; i < time; i++)
  • for (j = 0; j < 120; j++);
  • }
  • // I2C起始信号
  • void i2cStart() {
  • SDA = 1;
  • SCL = 1;
  • delay(1);
  • SDA = 0;
  • delay(1);
  • SCL = 0;
  • }
  • // I2C停止信号
  • void i2cStop() {
  • SDA = 0;
  • SCL = 1;
  • delay(1);
  • SDA = 1;
  • delay(1);
  • }
  • // I2C发送字节
  • bit i2cSendByte(unsigned char byte) {
  • unsigned char i;
  • bit ack;
  • for (i = 0; i < 8; i++) {
  • if ((byte & 0x80) == 0x80)
  • SDA = 1;
  • else
  • SDA = 0;
  • SCL = 1;
  • delay(1);
  • SCL = 0;
  • delay(1);
  • byte <<= 1;
  • }
  • SDA = 1;
  • SCL = 1;
  • ack = SDA;
  • delay(1);
  • SCL = 0;
  • delay(1);
  • return ack;
  • }
  • // I2C接收字节
  • unsigned char i2cReceiveByte() {
  • unsigned char i, byte = 0;
  • SDA = 1;
  • for (i = 0; i < 8; i++) {
  • byte <<= 1;
  • SCL = 1;
  • delay(1);
  • byte |= SDA;
  • SCL = 0;
  • delay(1);
  • }
  • return byte;
  • }
  • // 初始化MPU6050模块
  • void mpu6050Init() {
  • i2cStart();
  • i2cSendByte(MPU6050_ADDRESS);
  • i2cSendByte(0x6B); // PWR_MGMT_1寄存器地址
  • i2cSendByte(0x00); // 将PWR_MGMT_1寄存器写为0,唤醒MPU6050
  • i2cStop();
  • }
  • // 读取MPU6050的加速度值和陀螺仪值
  • void mpu6050ReadData(short *accelData, short *gyroData) {
  • unsigned char i;
  • i2cStart();
  • i2cSendByte(MPU6050_ADDRESS);
  • i2cSendByte(0x3B); // ACCEL_XOUT_H寄存器地址
  • i2cStop();
  • i2cStart();
  • i2cSendByte(MPU6050_ADDRESS | 0x01); // 切换到读模式
  • for (i = 0; i < 6; i++) {
  • if (i < 5)
  • accelData[i] = (i2cReceiveByte() << 8) | i2cReceiveByte();
  • else
  • gyroData[i - 5] = (i2cReceiveByte() << 8) | i2cReceiveByte();
  • if (i < 5)
  • i2cSendByte(0x00); // 给出ACK,继续读取下一个数据
  • else
  • i2cSendByte(0x01); // 给出NACK,停止读取
  • }
  • i2cStop();
  • }

代码实现说明:

【1】引入头文件和定义引脚:

  • 引入了 reg52.h 头文件,该头文件包含了 STC89C52 的寄存器定义和常用函数。
  • 使用 sbit 定义了 MPU6050 模块的 SDA 和 SCL 引脚。

【2】延时函数:

  • delay 函数用于产生一段延时,具体延时时间根据实际情况进行调整。

【3】I2C通信函数:

  • i2cStart 函数用于发送 I2C 总线的起始信号。
  • i2cStop 函数用于发送 I2C 总线的停止信号。
  • i2cSendByte 函数用于通过 I2C 总线发送一个字节的数据,并返回从设备的应答状态。
  • i2cReceiveByte 函数用于通过 I2C 总线接收一个字节的数据。

【4】初始化 MPU6050 模块:

  • mpu6050Init 函数通过 I2C 总线向 MPU6050 发送初始化命令,唤醒 MPU6050 模块。

【5】读取 MPU6050 的加速度值和陀螺仪值:

  • mpu6050ReadData 函数通过 I2C 总线向 MPU6050 发送读取命令,并接收加速度值和陀螺仪值。
  • 通过 i2cSendByte 发送寄存器地址,然后通过 i2cReceiveByte 接收数据。
  • 加速度值和陀螺仪值分别存储在 accelData 和 gyroData 数组中。

【6】主函数:

  • 在 main 函数中,首先声明了存储加速度值和陀螺仪值的数组。
  • 调用 mpu6050Init 函数初始化 MPU6050 模块。
  • 进入无限循环,循环中调用 mpu6050ReadData 函数读取加速度值和陀螺仪值,并通过串口打印输出。
  • 使用 delay 函数进行延时。
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐