基于STM32设计的出租车计费系统

一、项目介绍

在城市交通中,出租车是一种常见的交通工具。为了方便乘客和司机之间的交易,出租车计费系统被广泛应用于出租车行业。系统能够自动计算乘客的费用,提供准确、方便的计费服务,并且能够记录乘客的行驶数据,方便后续查询和管理。

传统的出租车计费方式是基于人工计算,司机根据里程和时间进行估算并告知乘客费用。然而,这种计费方式容易存在误差和争议,并且对司机和乘客都不够方便和透明。因此,出租车行业迫切需要一种更加准确、高效和可靠的计费系统。

基于此背景,本项目设计和开发一种基于STM32微控制器的出租车计费系统,以替代传统的人工计费方式。该系统将利用STM32微控制器的强大处理能力和丰富的外设接口,集成各种功能模块,实现自动计算乘客费用、显示计费信息等功能。

通过该出租车计费系统,乘客只需在上车时按下对应按钮,系统将自动开始计费,并在显示屏上实时显示行驶时间、里程和费用等信息。乘客还可以通过按键输入特殊情况,如堵车或夜间行驶,以便系统进行相应的额外计费。当乘客下车时,系统将自动停止计费,并显示最终费用。同时,系统还将记录乘客的行驶数据以备查询和管理。

image-20230625095240766

image-20230625095227080

image-20230625094541137

项目源码下载,可以了解这里:

https://blog.csdn.net/xiaolong1126626497/category_10192120.html

二、系统设计思路

2.1 系统架构

出租车计费系统的主要组成部分包括:STM32微控制器、LCD显示屏、按键、计时电路、收费器和外部存储器。整个系统的架构如下:

  • STM32微控制器:采用STM32F103RCT6作为系统的控制核心,负责接收并处理来自各个模块的输入信号,并控制液晶显示屏上的信息显示和收费器的操作。
  • LCD显示屏:采用1.44寸LCD显示屏,用于显示当前的计费信息,包括行驶时间、里程和费用等。
  • 按键:用于输入乘客上车和下车的时间以及其他特殊情况,如堵车、夜间行驶等。
  • 计时电路:用于准确地测量行驶时间。
  • 收费器:负责根据计费规则和实时数据计算乘客的费用。
  • 外部存储器:用于存储行驶数据和计费规则。

2.2 系统功能

出租车计费系统具有以下主要功能:

  • 实时计算行驶时间和里程。
  • 根据计费规则自动计算乘客费用。
  • 在LCD显示屏上显示当前的计费信息。
  • 支持特殊情况的额外计费,如堵车、夜间行驶等。
  • 存储行驶数据和计费规则以备查询和更新。

三、代码设计

3.1 LCD显示屏代码

#include "stm32f10x.h"// 定义LCD引脚连接
#define LCD_RS_PIN  GPIO_Pin_0
#define LCD_RS_PORT GPIOA
#define LCD_RW_PIN  GPIO_Pin_1
#define LCD_RW_PORT GPIOA
#define LCD_E_PIN   GPIO_Pin_2
#define LCD_E_PORT  GPIOA
#define LCD_D4_PIN  GPIO_Pin_3
#define LCD_D4_PORT GPIOA
#define LCD_D5_PIN  GPIO_Pin_4
#define LCD_D5_PORT GPIOA
#define LCD_D6_PIN  GPIO_Pin_5
#define LCD_D6_PORT GPIOA
#define LCD_D7_PIN  GPIO_Pin_6
#define LCD_D7_PORT GPIOA// 定义命令和数据的宏
#define LCD_COMMAND 0
#define LCD_DATA    1// 延时函数,用于产生适当的延时
void Delay(uint32_t nCount) {for (; nCount != 0; --nCount) {}
}// 发送命令或数据到LCD函数
void LCD_Send(uint8_t byte, uint8_t mode) {GPIO_WriteBit(LCD_RS_PORT, LCD_RS_PIN, (mode == LCD_DATA) ? Bit_SET : Bit_RESET);GPIO_WriteBit(LCD_RW_PORT, LCD_RW_PIN, Bit_RESET);GPIO_WriteBit(LCD_D4_PORT, LCD_D4_PIN, (byte >> 4) & 0x01 ? Bit_SET : Bit_RESET);GPIO_WriteBit(LCD_D5_PORT, LCD_D5_PIN, (byte >> 5) & 0x01 ? Bit_SET : Bit_RESET);GPIO_WriteBit(LCD_D6_PORT, LCD_D6_PIN, (byte >> 6) & 0x01 ? Bit_SET : Bit_RESET);GPIO_WriteBit(LCD_D7_PORT, LCD_D7_PIN, (byte >> 7) & 0x01 ? Bit_SET : Bit_RESET);GPIO_WriteBit(LCD_E_PORT, LCD_E_PIN, Bit_SET);Delay(1000);GPIO_WriteBit(LCD_E_PORT, LCD_E_PIN, Bit_RESET);GPIO_WriteBit(LCD_D4_PORT, LCD_D4_PIN, (byte >> 0) & 0x01 ? Bit_SET : Bit_RESET);GPIO_WriteBit(LCD_D5_PORT, LCD_D5_PIN, (byte >> 1) & 0x01 ? Bit_SET : Bit_RESET);GPIO_WriteBit(LCD_D6_PORT, LCD_D6_PIN, (byte >> 2) & 0x01 ? Bit_SET : Bit_RESET);GPIO_WriteBit(LCD_D7_PORT, LCD_D7_PIN, (byte >> 3) & 0x01 ? Bit_SET : Bit_RESET);GPIO_WriteBit(LCD_E_PORT, LCD_E_PIN, Bit_SET);Delay(1000);GPIO_WriteBit(LCD_E_PORT, LCD_E_PIN, Bit_RESET);Delay(1000);
}// 初始化LCD函数
void LCD_Init(void) {Delay(45000);LCD_Send(0x30, LCD_COMMAND);Delay(4500);LCD_Send(0x30, LCD_COMMAND);Delay(150);LCD_Send(0x30, LCD_COMMAND);Delay(150);LCD_Send(0x20, LCD_COMMAND);Delay(150);LCD_Send(0x28, LCD_COMMAND);Delay(150);LCD_Send(0x08, LCD_COMMAND);Delay(150);LCD_Send(0x01, LCD_COMMAND);Delay(150);LCD_Send(0x06, LCD_COMMAND);Delay(150);LCD_Send(0x0C, LCD_COMMAND);Delay(150);
}// 在指定位置显示数字函数
void LCD_DisplayNumber(uint8_t number, uint8_t x, uint8_t y) {uint8_t data = 0x30 + number;  // 转换数字为对应的ASCII码if (x >= 0 && x < 16 && y >= 0 && y < 2) {uint8_t addr = 0x80 + (y * 0x40) + x;LCD_Send(addr, LCD_COMMAND);LCD_Send(data, LCD_DATA);}
}int main(void) {// 初始化GPIO和LCDRCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = LCD_RS_PIN | LCD_RW_PIN | LCD_E_PIN | LCD_D4_PIN | LCD_D5_PIN | LCD_D6_PIN | LCD_D7_PIN;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);LCD_Init();while (1) {// 在第一行第一列显示数字1LCD_DisplayNumber(1, 0, 0);}
}

3.2 计时代码

通过定时器2实现了收费计时功能,并在串口上打印出计时的实时时间。通过按下’S’键启动计时器,按下’Q’键停止计时器。每隔500毫秒,在串口上打印出实时时间。

#include "stm32f10x.h"
#include <stdio.h>// 定义计时状态
typedef enum {TIMER_STOPPED,TIMER_RUNNING
} TimerState;TimerState timerState = TIMER_STOPPED; // 计时器初始状态为停止
uint32_t startTime = 0; // 开始计时的时间// 初始化定时器2
void Timer2_Init(void) {RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_TimeBaseStructure.TIM_Prescaler = 7200 - 1; // 设置预分频值,产生1ms的时间基准TIM_TimeBaseStructure.TIM_Period = 1000 - 1;  // 设置计数器的重载值,每1秒中断一次TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);TIM_Cmd(TIM2, ENABLE);NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}// 开始计时
void StartTimer(void) {if (timerState == TIMER_STOPPED) {startTime = TIM_GetCounter(TIM2); // 记录开始计时的时间timerState = TIMER_RUNNING;}
}// 停止计时
void StopTimer(void) {if (timerState == TIMER_RUNNING) {timerState = TIMER_STOPPED;}
}// 获取实时时间,返回单位为毫秒
uint32_t GetElapsedTime(void) {if (timerState == TIMER_RUNNING) {return TIM_GetCounter(TIM2) - startTime;} else {return 0;}
}// 初始化串口1
void USART1_Init(void) {RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; // TX引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);USART_InitTypeDef USART_InitStructure;USART_InitStructure.USART_BaudRate = 115200;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_Tx;USART_Init(USART1, &USART_InitStructure);USART_Cmd(USART1, ENABLE);
}// 重定向printf函数到串口输出
int fputc(int ch, FILE *f) {if (ch == '\n') {USART_SendData(USART1, '\r');while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);}USART_SendData(USART1, ch);while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);return ch;
}int main(void) {// 初始化定时器和串口Timer2_Init();USART1_Init();printf("Press 'S' to start the timer.\r\n");printf("Press 'Q' to stop the timer.\r\n");while (1) {if (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET) {uint8_t rxData = (uint8_t)USART_ReceiveData(USART1);if (rxData == 'S' || rxData == 's') {StartTimer();printf("Timer started.\r\n");} else if (rxData == 'Q' || rxData == 'q') {StopTimer();printf("Timer stopped.\r\n");}}// 每隔500毫秒打印实时时间if (GetElapsedTime() >= 500) {printf("Elapsed time: %lu ms\r\n", GetElapsedTime());startTime = TIM_GetCounter(TIM2); // 更新开始计时的时间}}
}// 定时器2中断处理函数
void TIM2_IRQHandler(void) {if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {TIM_ClearITPendingBit(TIM2, TIM_IT_Update);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/27131.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

flink kafka消费者如何处理kafka主题的rebalance

背景&#xff1a; 我们日常使用kafka客户端消费kafka主题的消息时&#xff0c;当消费者退出/加入消费者组&#xff0c;kafka主题分区数有变等事件发生时&#xff0c;都会导致rebalance的发生&#xff0c;此时一般情况下&#xff0c;如果我们不自己处理offset&#xff0c;我们不…

django处理分页

当数据库量比较大的时候一定要分页查询的 在django中操作数据库进行分页 queryset models.PrettyNum.objects.all() #查询所有 queryset models.PrettyNum.objects.all()[0:10] #查询出1-10列 queryset models.PrettyNum.objects.filter(mobile__contains136)[0:10] …

python-opencv对极几何 StereoRectify

OpenCV如何正确使用stereoRectify函数 函数介绍 用于双目相机的立体校正环节中&#xff0c;这里只谈谈这个函数怎么使用&#xff0c;参数具体指哪些函数参数 随便去网上一搜或者看官方手册就能得到参数信息&#xff0c;但是&#xff01;&#xff01;相对关系非常容易出错&…

机器学习深度学习——池化层

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——卷积的多输入多输出通道 &#x1f4da;订阅专栏&#xff1a;机器学习&&深度学习 希望文章对你们…

1. Git基础知识

文章目录 Git基础知识一、集中式与分布式二、中心服务器三、工作流四、分支实现五、冲突六、Fast forward七、储藏&#xff08;Stashing&#xff09;八、SSH 传输设置九、.gitignore 文件十、Git 命令一览十一、和远端仓库交互 Git基础知识 一、集中式与分布式 Git 属于分布式…

【单片机】51单片机,晨启科技,板子引脚对应关系

一般引脚: sbit beepP2^4; //将单片机的P2.4端口定义为beep.本口用于屏蔽上电后蜂鸣器响 sbit ledP1^0; //将单片机的P1.0端口定义为led&#xff0c;用于点亮LED-D1 sbit DIG1P0^0; //数码管位选1 sbit DIG2P0^1; //数码管位选2P10xFF;//初始化P1引脚全部置高&a…

【第一阶段】kotlin的when表达式

1.Java 的if /when是语句 kotlin的if/when是表达式&#xff0c;表达式是有返回值的 java中void是个关键字&#xff0c;Unit在kotlin中是个类 2.当使用when语句的时候必须有一个不满足的值即else: fun main() {var week:Int5val info when(week){1->"今天是星期一"…

Transformer学习笔记

Transformer学习笔记 前言前提条件相关介绍Transformer总体架构编码器&#xff08;Encoder&#xff09;位置编码&#xff08;Positional Encoding&#xff09;get_attn_pad_mask函数&#xff08;Padding Mask&#xff09;EncoderLayerMultiHeadAttentionScaledDotProductAttent…

项目出bug,找不到bug,如何拉回之前的版本

1.用gitee如何拉取代码 本文为转载于「闪耀太阳a」的原创文章原文链接&#xff1a;https://blog.csdn.net/Gufang617/article/details/119929145 怎么从gitee上拉取代码 1.首先找到gitee上想要拉取得代码URL地址 点击复制这里的https地址 1 ps:&#xff08;另外一种方法&…

xcode打包导出ipa

转载&#xff1a;xcode打包导出ipa 目录 转载&#xff1a;xcode打包导出ipa 第一步&#xff1a;注册苹果开发者账号 第二步&#xff1a;下载APP Uploader 第三步&#xff1a;使用xcode打包导出ipa文件&#xff0c;供其他人内测 众所周知&#xff0c;在开发苹果应用时需要使…

Leetcode31 下一个排列

解题思路&#xff1a; 算法过程的第二步&#xff0c;可以变为将[j,end]排序&#xff0c;然后从[j,end)和i进行比较&#xff0c;在区间j,end区间第一个大于nums[i]后&#xff0c;交换即可 public void nextPermutation(int[] nums) {int len nums.length - 1;for(int i len;i…

【电机绘图】:插补算法(一)—直线插补—逐点比较法

今日介绍学习一种使用电机作画、绘图、加工零件时需要使用的算法 &#xff1a; 插补算法 本文提供直线插补的概念基础&#xff0c;基本思路分析&#xff0c;C语言实现等&#xff0c;代码会直接贴出&#xff01; 插补算法是指在数值计算或数据处理中&#xff0c;根据已有的数据…

单例模式(C++)

定义 保证一个类仅有一个实例&#xff0c;并提供一个该实例的全局访问点。 应用场景 在软件系统中&#xff0c;经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例&#xff0c;才能确保它们的逻辑正确性、以及良好的效率。如何绕过常规的构造器&#xff0c;提供一种…

Babel编译与Webpack

目录 Babel初识BabelBabel 使用方式使用 Babel 前的准备工作 WebpackWebpack介绍Webpack初体验Webpack核心概念入口&#xff08;entry&#xff09;出口&#xff08;output&#xff09;加载 (loader)插件&#xff08;plugins&#xff09; Babel Babel官网: https://babeljs.io/…

【Hystrix技术指南】(6)请求合并机制原理分析

[每日一句] 也许你度过了很糟糕的一天&#xff0c;但这并不代表你会因此度过糟糕的一生。 [背景介绍] 分布式系统的规模和复杂度不断增加&#xff0c;随着而来的是对分布式系统可用性的要求越来越高。在各种高可用设计模式中&#xff0c;【熔断、隔离、降级、限流】是经常被使…

小白到运维工程师自学之路 第六十四集 (dockerfile构建tomcat、mysql、lnmp、redis镜像)

一、tomcat&#xff08;更换jdk&#xff09; mkdir tomcat cd tomcat/ tar xf jdk-8u191-linux-x64.tar.gz tar xf apache-tomcat-8.5.40.tar.gzvim Dockerfile FROM centos:7 MAINTAINER Crushlinux <syh163.com> ADD jdk1.8.0_191 /usr/local/java ENV JAVA_HOME /us…

国内大模型在局部能力上已超ChatGPT

中文大模型正在后来居上&#xff0c;也必须后来居上。 数科星球原创 作者丨苑晶 编辑丨大兔 从GPT3.5彻底出圈后&#xff0c;大模型的影响力开始蜚声国际。一段时间内&#xff0c;国内科技公司可谓被ChatGPT按在地上打&#xff0c;毫无还手之力。 彼时&#xff0c;很多企业…

怎么快速搭建BI?奥威BI系统做出了表率

搭建BI系统有两大关键&#xff0c;分别是环境搭建和数仓建设。这两点不管是哪一个都相当地费时费力&#xff0c;那要怎么才能快速搭建BI平台&#xff0c;顺利实现全企业数字化运营决策&#xff1f;奥威BI系统方案&#xff0c;你值得拥有&#xff01; 奥威BI系统方案&#xff0…

三种方法实现tab栏切换(CSS方法、JS方法、Vue方法)

一、需求 给下图的静态页面添加tab栏切换效果 二、CSS方法 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"v…

云知识库软件的推荐清单,你看看你喜欢哪一个?

在选择云知识库软件时&#xff0c;有很多因素需要考虑&#xff0c;如功能、易用性、可定制性、安全性、价格等。下面是一些我喜欢的云知识库软件推荐清单&#xff1a; Confluence&#xff1a; Confluence是一款由Atlassian开发的知识管理和协作工具。它提供了强大的编辑和协作…