C语言模块化编程思维以及直流电机控制(第四天)

在这里插入图片描述


👨‍💻个人主页:@开发者-削好皮的Pineapple!

👨‍💻 hello 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅!

👨‍💻 本文由 削好皮的Pineapple! 原创

👨‍💻 收录于专栏:C语言到基于STM32 的智能矿探小车


请添加图片描述

请添加图片描述

文章目录

    • 前言
    • 🎶一、模块化编程思维
    • 🎶二、直流电机
      • 2.1 电机驱动模块
    • 🎶三、小车运动控制代码实现
      • 3.1 小车控制函数(`car.c`/`car.h`)
      • 3.2 程序下载与运行设置
      • 3.3 速度控制
        • 结束语🥇


前言

今天是实习培训的新一天,学习聚焦于模块化编程思维以及直流电机控制相关知识,包括电机驱动模块的使用、小车运动控制代码的实现以及PWM技术在速度调节中的应用,为后续智能矿探小车的开发进一步夯实基础。


🎶一、模块化编程思维


模块化编程是按照不同功能将程序拆分为对应的源文件(.c)和头文件(.h),以提高代码的可维护性和复用性。

  • 源文件(.c):用于保存函数接口的具体实现。
    例如led.c
    void led_init(void)
    {// 初始化LED的具体代码
    }
    void led_ctrl(...)
    {// 控制LED的具体代码
    }
    
#include "led.h"
#include "stm32f4xx.h"void LED_Init(void)
{// 使能GPIOF和GPIOE外设时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOE, ENABLE);GPIO_InitTypeDef GPIO_InitStruct;// 配置GPIOF的LED引脚(D1、D2)GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;GPIO_Init(GPIOF, &GPIO_InitStruct);// 配置GPIOE的LED引脚(D3、D4)GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;GPIO_Init(GPIOE, &GPIO_InitStruct);// 默认关闭所有LEDGPIO_SetBits(GPIOF, GPIO_Pin_9 | GPIO_Pin_10);GPIO_SetBits(GPIOE, GPIO_Pin_13 | GPIO_Pin_14);
}void LED_Control(LEDNUM led_num, LEDSTA state)
{switch(led_num){case LED_D1:if(state == LED_ON)GPIO_ResetBits(GPIOF, GPIO_Pin_9);elseGPIO_SetBits(GPIOF, GPIO_Pin_9);break;case LED_D2:if(state == LED_ON)GPIO_ResetBits(GPIOF, GPIO_Pin_10);elseGPIO_SetBits(GPIOF, GPIO_Pin_10);break;case LED_D3:if(state == LED_ON)GPIO_ResetBits(GPIOE, GPIO_Pin_13);elseGPIO_SetBits(GPIOE, GPIO_Pin_13);break;case LED_D4:if(state == LED_ON)GPIO_ResetBits(GPIOE, GPIO_Pin_14);elseGPIO_SetBits(GPIOE, GPIO_Pin_14);break;}
}
  • 头文件(.h):用于保存函数声明、构造类型定义、全局变量声明等,且需添加防止重复包含的预处理指令。
    例如led.h
    #ifndef _LED_H  // 如果未定义_LED_H
    #define _LED_H  // 定义_LED_H,防止头文件重复包含// 函数声明
    void led_init(void);
    void led_ctrl(...);// 全局变量声明
    // 构造类型定义#endif
    
#ifndef _LED_H
#define _LED_H#include <stdint.h>  // 添加此头文件以使用uint8_ttypedef enum {LED_D1,LED_D2,LED_D3,LED_D4
} LEDNUM;typedef enum {LED_OFF,LED_ON
} LEDSTA;void LED_Init(void);
void LED_Control(LEDNUM led_num, LEDSTA state);#endif
  • 常见模块示例
    • delay.c/delay.h:实现延时功能,如void delay_ms(uint16_t nms);(毫秒级延时)、void delay_us(uint16_t us);(微秒级延时)。

🎶二、直流电机


2.1 电机驱动模块

  • 接线说明

    • 两个绿色端子:直接连接直流电机。
      在这里插入图片描述

    • 6个排针:

      • VCC:接5V或3.3V(5V驱动时小车力度大,状态改变较难;3.3V驱动时力度小,状态改变相对容易)。
      • GND:接GND(注意正负极不可接反)。
      • 控制引脚:B-1AB-1B用于控制一个电机,A-1AA-1B用于控制另一个电机,具体对应哪个电机需看实物绿色端子的连接。以下是本次实训所用驱动电路板。
        在这里插入图片描述
        引脚依次是:B-1A、B-1B、GND、VCC、A-1A、A-1B
  • 电机转动原理:直流电机由两个引脚驱动,当两个引脚电平状态不同时电机转动。

    • 假设B-1A为高电平、B-1B为低电平时,电机向前转动;则B-1A为低电平、B-1B为高电平时,电机向后转动。
    • B-1AB-1B均为低电平或均为高电平时,电机停止转动。
  • 可用GPIO引脚:在CAMERA处有部分GPIO引脚可用于连接控制,如2脚(GND)、4脚(PD6)、6脚、8脚、10脚…1脚(3V3)、3脚(PB7)、5脚、7脚、9脚…根据原理图(GEC-M4原理图2016-07-29.pdf)可得:
    在这里插入图片描述


🎶三、小车运动控制代码实现


3.1 小车控制函数(car.c/car.h

  • 小车初始化函数
 void car_Init(void)
{//1.时钟使能RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOD , ENABLE);//2.初始化GPIO ---> 推挽输出模式 GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;GPIO_Init(GPIOD, &GPIO_InitStruct);// 配置GPIOE的LED引脚GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7| GPIO_Pin_6;GPIO_Init(GPIOB, &GPIO_InitStruct);//3.默认状态:小车停止GPIO_SetBits(GPIOD, GPIO_Pin_6 | GPIO_Pin_7);//左GPIO_SetBits(GPIOB, GPIO_Pin_6 | GPIO_Pin_7);//右
}
  • 基本运动控制函数
    • 前进:
 int speed = 100;
void car_up(void)		
{//左轮电机前转GPIO_ResetBits(GPIOD, GPIO_Pin_6 );//A-1BGPIO_SetBits(GPIOD, GPIO_Pin_7 );//	A-1A//右轮电机前转GPIO_ResetBits(GPIOB, GPIO_Pin_6 );//B-1AGPIO_SetBits(GPIOB, GPIO_Pin_7 );//B-1Bdelay_ms(speed);GPIO_SetBits(GPIOB, GPIO_Pin_6 | GPIO_Pin_7);//右delay_ms(100-speed);	
}
  • 后退:
void car_back(void)
{//左轮电机后转GPIO_ResetBits(GPIOD, GPIO_Pin_7 );GPIO_SetBits(GPIOD, GPIO_Pin_6 );			//右轮电机后转GPIO_ResetBits(GPIOB, GPIO_Pin_7 );GPIO_SetBits(GPIOB, GPIO_Pin_6 );			
}
  • 左转:
    void car_left(void)
{//左轮不转 (后转)GPIO_SetBits(GPIOD, GPIO_Pin_6 | GPIO_Pin_7);//右轮前进GPIO_ResetBits(GPIOB, GPIO_Pin_6 );GPIO_SetBits(GPIOB, GPIO_Pin_7 );
}
- 右转:
void car_right(void)
{//右轮不转 (后转)GPIO_SetBits(GPIOB, GPIO_Pin_6 | GPIO_Pin_7);//左轮前进GPIO_ResetBits(GPIOD, GPIO_Pin_6 );GPIO_SetBits(GPIOD, GPIO_Pin_7 );
}
  • 停止:
void car_stop(void)
{//右轮和左轮子都不转GPIO_SetBits(GPIOD, GPIO_Pin_6 | GPIO_Pin_7);GPIO_SetBits(GPIOB, GPIO_Pin_6 | GPIO_Pin_7);
}

3.2 程序下载与运行设置

  • 下载程序时BOOT0接3V3,BOOT1接GND,按下复位键,CPU执行引导程序,程序可下载到开发板。
  • 下载完成后BOOT0接GND,BOOT1接GND,重新上电或按复位键,程序重新运行。

3.3 速度控制

  • 简单速度调节(上面已经实现):通过控制电机转动与停止的时间比例来调节速度。

    int speed = 100;
    void car_up(void)
    {// 左轮电机前转// 右轮电机前转(右轮速度调节)B-1A = 1;B-1B = 0;  // 右轮转动delay_ms(speed);B-1B = 1;  // 右轮停止转动delay_ms(100 - speed);
    }
    
  • PWM(脉冲宽度调制):通过调节有效电平时间与整个周期的比例(占空比)来精确控制电机转速、蜂鸣器鸣叫等。

    • 占空比 = 有效电平时间 / 整个周期。
    • 例如:有效电平时间50ms,周期100ms,占空比为50%。
    • 注意:使用PWM调节的周期不能太长。
  • 主函数示例

    int main()
    {while(1){car_up();  // 小车前进}
    }
    
  • 练习目标:调节小车轮子速度,使小车前进1m左右。
    在这里插入图片描述
    在这里插入图片描述

请添加图片描述

结束语🥇

🔥 订阅专栏持续学习:C语言到基于STM32的智能矿探小车
💬 欢迎点赞、收藏、留言讨论,一起攻克嵌入式开发!

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

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

相关文章

【PTA】数据结构与算法0001:1025 反转链表

文章大纲写在前面测试用例ac代码学习代码知识点小结写在前面 实现思路 结构体封装数据 根据order重新排序k区间值迭代翻转 n整除k&#xff0c;则最后地址输出"-1"非整除&#xff0c;最后剩余区间&#xff0c;原序输出。最后地址输出"-1" 题目有难度&…

深入解析 .NET 泛型:从原理到实战优化

在现代软件开发中&#xff0c;代码复用性和性能优化是开发者永恒的追求。.NET 泛型作为一项强大的语言特性&#xff0c;不仅能够帮助我们消除重复代码&#xff0c;还能显著提升代码的类型安全性和运行效率。本文将带你全面了解 .NET 泛型&#xff0c;从基本概念到高级用法&…

Excel 处理软件 内容复制工具:工作表批量复制 + 合并拆分简洁操作零门槛

各位办公小能手们&#xff01;今天给你们介绍一款超牛的软件——Excel内容复制工具。软件下载地址安装包 这可是专门为了让Excel数据处理效率蹭蹭往上涨而设计的辅助软件呢&#xff01;它的主要功能可多啦&#xff0c;能批量复制工作表&#xff0c;还能把好多表格合并到同一个…

【机器学习实战笔记 14】集成学习:XGBoost算法(一) 原理简介与快速应用

《XGBoost算法》 推荐的学习路径&#xff1a; 【快速实现XGBoost、跑通代码】- 第一部分 【快速掌握XGBoost应用、达到自由调参水平】- 第一部分~第三部分 【快速掌握XGBoost原理、面试得以通关】- 第一部分1 第二部分1.2、2.2 第四部分 目录《XGBoost算法》一 XGBoost的基…

.NET AI 模板

引言 随着人工智能技术的快速发展&#xff0c;AI应用开发已成为开发者必备的技能之一。然而&#xff0c;对于许多.NET开发者来说&#xff0c;如何快速上手AI开发仍然是一个挑战。微软推出的.NET AI模板预览版正是为了解决这一问题而生&#xff0c;为开发者提供了构建智能聊天应…

EFK9.0.3 windows搭建

背景 最近某个功能要使用到ELK&#xff08;ElasticSearch、Logstash、Kibana&#xff09;采集日志&#xff0c;对数据进行分析&#xff0c;网上百度了一下&#xff0c;目前推荐不使用Logstash而使用Filebeat ,即EFK。 下载链接 Elasticsearch Kibana Filebeat 安装前提 …

上海新华医院奉贤院区:以元宇宙技术重构未来医疗生态

引言&#xff1a;当医疗遇上元宇宙在数字化转型的浪潮中&#xff0c;上海新华医院奉贤院区以"智慧医院"为定位&#xff0c;率先构建了"元宇宙医院"雏形。通过AI大模型、三维影像分析、AR手术导航等前沿技术的深度融合&#xff0c;医院正在打造一个覆盖全周…

知识竞赛答题pk小程序用户操作手册

知识竞赛答题 PK 小程序用户操作手册 一、注册与登录 用户首次使用答题pk小程序需上传头像&#xff0c;输入昵称&#xff0c;并选择加入团队。如果是企业内部人员使用可开启白名单功能。二、进入答题 PK 模式 登录后&#xff0c;在小程序首页&#xff0c;您可以看到 “单人挑战…

等大小谱聚类

聚类是一种将具有相似特征的数据点进行分组的方法。它广泛应用于探索性数据分析&#xff0c;并已被证明在模式识别、市场和客户细分、推荐系统、数据压缩以及生物数据分析等许多应用中都发挥着重要作用。 尽管聚类算法种类繁多&#xff0c;但没有一种能够生成点数均衡的聚类。…

〔从零搭建〕数据湖平台部署指南

&#x1f525;&#x1f525; AllData大数据产品是可定义数据中台&#xff0c;以数据平台为底座&#xff0c;以数据中台为桥梁&#xff0c;以机器学习平台为中层框架&#xff0c;以大模型应用为上游产品&#xff0c;提供全链路数字化解决方案。 ✨杭州奥零数据科技官网&#xff…

Java 导出pdf 写出demo 1、需要设置自定义页眉和文字 2、可以插入表格 3、可以插入图片

以下是一个使用 iText 7 库实现 PDF 导出的 Java 示例&#xff0c;包含自定义页眉、文字、表格和图片功能&#xff1a; 添加 Maven 依赖 <dependencies><!-- iText 7 Core --><dependency><groupId>com.itextpdf</groupId><artifactId>ite…

Ntfs!LfsReadRestart函数分析得到Ntfs!LFS_RESTART_PAGE_HEADER

第一部分&#xff1a;0: kd> p Ntfs!LfsPinOrMapData0x8c: f71797f6 ff15a40016f7 call dword ptr [Ntfs!_imp__CcPinRead (f71600a4)] 0: kd> t nt!CcPinRead: 80bf9a5a 6a2c push 2Ch 0: kd> kc# 00 nt!CcPinRead 01 Ntfs!LfsPinOrMapData 02 N…

skywalking-agent-docker镜像

FROM centos:7.9.2009 USER root# 定义 Arthas 目录环境变量 ENV ARTHAS_HOME/opt/arthas# 更改 YUM 源并清理缓存 RUN mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo_bak && \rm -rf /etc/yum.repos.d/* && \curl -o /etc/yum.rep…

数据库开发运维的集成:弥合开发与运维之间的鸿沟

在传统的软件开发工作流程中&#xff0c;数据库变更往往是事后才考虑的问题。应用程序代码遵循定义明确的开发运维实践&#xff0c;包括版本控制、自动测试和持续部署&#xff0c;而数据库变更则经常是由数据库管理员手动执行的高风险操作。这种脱节造成了瓶颈&#xff0c;带来…

PiscTrace应用:从 YOLO-Pose 到深蹲与引体向上计数:实时健身动作分析与实现

随着健身行业的发展&#xff0c;越来越多的智能应用涌现&#xff0c;用于帮助健身者更好地记录和分析运动情况。特别是在体能训练中&#xff0c;俯卧撑和引体向上是两个非常常见的动作&#xff0c;它们通常用来锻炼上半身力量和耐力。为了使训练更加科学和高效&#xff0c;实时…

【unity】webCanvas.enabled = false;和webCanvas.gameObject.SetActive(false);的优缺点比较

在 Unity 中&#xff0c;webCanvas.gameObject.SetActive(false) 和 webCanvas.enabled false 是两种不同的隐藏 UI 的方式&#xff0c;它们的核心区别在于作用范围和对组件状态的影响。理解这些差异能帮助你避免初始化失败、性能问题和逻辑错误。 1核心区别 gameObject.SetAc…

深入探索 pnpm:高效磁盘利用与灵活的包管理解决方案

引言 在现代 JavaScript 开发中&#xff0c;依赖管理效率直接影响开发体验。传统工具如 npm 和 yarn 在大型项目中常面临磁盘冗余和性能瓶颈。pnpm&#xff08;Performant npm&#xff09;通过创新的硬链接和符号链接机制&#xff0c;解决了这些痛点。本文将深入解析 pnpm 的核…

Hive MetaStore的实现和优化

在大数据领域&#xff0c;数据管理与存储至关重要&#xff0c;Hive MetaStore&#xff08;HMS&#xff09;作为 Hive 数据仓库的核心组件&#xff0c;承担着元数据管理的关键职责。随着数据规模不断膨胀&#xff0c;其性能与稳定性面临挑战。本文将深入剖析 HMS 的实现机制&…

一文读懂动态规划:多种经典问题和思路

一、动态规划算法的思想与核心概念框架 1. 动态规划的基本思想 动态规划&#xff08;Dynamic Programming, DP&#xff09;是一种通过将复杂问题分解为重叠子问题&#xff0c;并利用子问题的解来高效解决原问题的方法。其核心思想是避免重复计算&#xff0c;通过存储中间结果&a…

阿幸课堂随机点名

代码功能 这个是一个HTML网页端&#xff0c;简单来说就是可以双击之后运行进行点名。 当然&#xff0c;不局限于课堂点名 代码功能 Excel 导入增强&#xff1a; 增加了列选择器&#xff0c;可以指定从哪一列读取学生姓名 增加了起始行选择器&#xff0c;可以跳过标题行或其…