常用开发板接口执行器

0、常用开发环境

1. cubMX

1.STM32CubeMX_GPIO配置

GPIO配置

2.STM32CubeMX_UART配置

UART配置

3.STM32CubeMX_外部中断

外部中断

4.STM32CubeMX_定时器配置

定时器配置

5.STM32CubeMX_PWM配置

PWM配置

6.STM32CubeMX_ADC配置

ADC配置

7.STM32CubeMX_

8.STM32CubeMX_

9.STM32CubeMX_

10.STM32CubeMX_

11.STM32CubeMX_

一、常用板子引脚图

0、arduino系列板子

Arduino NANO – 那些需要了解的地方
在这里插入图片描述

1、arduino UNO

参考:CSDN
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2、STM32C8T6

在这里插入图片描述

1. F103C8T6+MPU6050小项目

F103C8T6通过MPU6050+DMP姿态解算读取角度及温度
参考:STM32F103C8T6最小系统板驱动MPU6050串口打印数据

下图为MPU6050需要用到的引脚(不代表工程中是这么用的)
在这里插入图片描述
MPU6050模块A0接地mpu6050地址0x68,A0为高电平mpu6050的地址为0x69。所以这里选择的A0接地mpu6050地址0x68。

系统性实例:管道机器人P_bot的机载通信驿站
工程文件+源码
请添加图片描述

2. F103C8T6+MPU6050+OLED+匿名上位机显示

参考视频:HAL库MPU6050_DMP移植
C8T6:

  1. UART:PB6->TX;PB7->RX
  2. IIC: PB11->SDA; PB10->SCL
    1.工程文件(cubMX开发的F103C8T6)+源码
    2.工程文件(库函数F103C8T6)+源码
    3.IMU信息获取比较全面的例子
    请添加图片描述

3. 模拟信号接收的程序

  1. chatGPT:基于HAL库模拟信号接收的程序
在这里插入代码片while (1){HAL_ADC_Start(&hadc1); // 启动ADC采样HAL_ADC_PollForConversion(&hadc1, 100); // 等待ADC转换完成uint16_t adc_value = HAL_ADC_GetValue(&hadc1); // 获取采样结果char buffer[32];snprintf(buffer, sizeof(buffer), "ADC Value: %hu\r\n", adc_value);HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), HAL_MAX_DELAY); // 发送采样结果到串口}
}

4. 直流电机PID 速度、位置

PID讲解电赛必备 小白入门
位置PID
在这里插入图片描述
基础PID控制电机(附原码)
速度环
在这里插入图片描述

5. 平衡小车

请添加图片描述
B站教程
在这里插入图片描述
源文件下载:https://download.csdn.net/download/JINGSUWANG/87741468

硬件:
1.STM32C8T6
2.0.96OLED
3.MPU6050
4.DR884(有刷电机驱动)
5.降压稳压模块
6.HC-06蓝牙模块
7.超声波模块
8.红外寻迹模块

功能:
1.直立+速度+转向PID环
2.蓝牙遥控
3.红外寻迹
4.大功率MOS开关X2

在这里插入图片描述
立创开源链接:
开发板为15.24间距的主控板:
https://oshwhub.com/fsxqn/banlancecar_copy
开发板为16.7的主控板:
https://oshwhub.com/fsxqn/banlancecar_copy_copy
pcb底板:
https://oshwhub.com/fsxqn/balancecar_bottom_copy
可以在线浏览

PID调参视频参考:
1.【平衡小车PID】直立环+速度环完整调参过程 (开源)
2.经验总结:

1.调参顺序:直立环 》 速度环 》 转向换(逐渐删除注释去一个个调)
2.直立环:先判断参数极性(正负值),能够削弱倾倒的转向极性正确,直立环先调Kp,调到大幅度低频摆动后开始加入Kd项,调到小车在平衡位置出现小幅度高频抖动为止。
3.速度环:将直立和转向环都注释掉时,转动一侧轮子,另一侧轮子同向转动,参数极性正确;调到水平推动直立的小车,小车能够回到原来的位置为止;如有必要可以回头去增大直立环的Kd值(减小摆幅)。
4.转向环:调到绕Z轴转动小车,小车能够回到之前的朝向为止。

3、ESP32

可以使用使用MicroPython开发ESP32
GPIO可用资源
GPIO 6-11 连接到SPI Flash。
GPIO 34-39 只能作为输入且没有内部上拉,其他的可以作为输入或者输出。
GPIO 20, 24, 28, 29, 30, 31 不对外开放。
GPIO 32,33默认连接到RTC域。可能需要如下设置:

在这里插入图片描述
在这里插入图片描述

3.1、ESP32精简版(ESP32 Dev Module)

ESP32 LoLin32 精简版
ESP32开发板V1.0.0 Rev1 wifi蓝牙 4MB FLASH
在这里插入图片描述
板载led灯由gpio22控制。

相关资料:

1.https://github.com/hallard/lolin32-lite-lora
在这里插入图片描述
可以看到默认的IIC引脚,SPI引脚等
在这里插入图片描述

3.2、ESP8266

  • 注意:
  1. 自带LED为 GPIO2
  2. 烧录程序时需要一直按着flash健!!!!
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

3.3、ESP-01S

  • 详细文章说明
  • 注意:
  1. 自带LED为 GPIO2
  2. 烧录程序时需要一直按着flash健!!!! (即GPIO0 要接下地)烧录好了之后拔下
    在这里插入图片描述
    USB_TTL 和其连接
    在这里插入图片描述
    其在arduino中对应的开发板:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

1. 网络继电器小项目

参考:使用Blinker控制esp01s Relay继电器模块

  • ESP01s 程序
    其中头文件需要从点灯科技官网获取Arduino的SDK
#define BLINKER_WIFI //以WIFI方式接入,BLINKER_BLE以蓝牙方式接入
#include <Blinker.h>
//配置wifi联网模块
char auth[] = "Blinker中申请的密钥";
char ssid[] = "WIFI名字";
char pswd[] = "WIFI密码";
int GPIO = 0;
int pin_state = HIGH;  //用于做输出引脚电平的翻转
BlinkerButton Button1("btn-abc");//Blinker app上设置按钮时按钮名要和此一致
// 按下按键就会执行该函数(回调函数)
void button1_callback(const String & state) {BLINKER_LOG("get button state: ", state);   //该句将在串口打印pin_state = !pin_state;digitalWrite(GPIO, pin_state);if(state == "on"){Blinker.print("switch", "on");//该句将在串口打印Button1.print("on");//该句将用于APP的按键上显示开关状态}if(state == "off"){Blinker.print("switch", "off");//该句将在串口打印Button1.print("off");//该句将用于APP的按键上显示开关状态}Blinker.delay(500);//操作延时
}
void setup() {// 初始化串口Serial.begin(115200);// 初始化控制继电器的GPIO引脚pinMode(GPIO, OUTPUT);digitalWrite(GPIO, LOW);//低电平默认继电器关闭// 初始化WIFI设置Blinker.begin(auth, ssid, pswd);//数据管理,当收到指令的时候会调用该回调函数Button1.attach(button1_callback);
}
//让程序一直运行
void loop() {Blinker.run();
}

在这里插入图片描述

2. ESP01s—0.96OLED

别人的项目仓库地址:下载地址:OLED_I2C驱动
在这里插入图片描述

在这里插入图片描述

接线:
OLED —— ESP01s
scl —— TXD GPIO1
sda —— RXD GPIO3

在这里插入图片描述
在这里插入图片描述

3. OLED & wifi继电器整合

3.4、ESP32——CAM

参考:ESP32 CAM GPIO引脚定义

在这里插入图片描述
和TTL-USB连接
在这里插入图片描述
标注的GND接口好像不行,可以换到左边的GND接口
在这里插入图片描述
自我尝试,好像下载的时候需要TTL 3V3连接开发板的5V,运行的时候再切换到开发板的3V3

注意:
下载的时候 ESP32-cam的io0要接GND,下载结束后,必须断开io0和GND的连接。
在arduino IDE 点击烧录上传,然后需要按一下esp32-cam的reset按键,程序才会下载。下载完成后,断开io0的连线,再按一下reset按键,就退出下载模式了,即可正常使用。

1. 对应小项目例子:

在同一网络下,设备通过网页访问ESP32的视频信息
B站教程:
资源链接:https://pan.baidu.com/s/1Y9-rLLmAKPYzBDcrEyuGMw
提取码:2022
我的网盘:链接:https://pan.baidu.com/s/1sawnFJiOFXbIOLIRqy4cxQ
提取码:ul7o

3.5、树莓派3b

  1. 引脚图
    参考:引脚图
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

二、常用接口(硬件/通信 接口)

0、基础知识

  1. 串行并行
    串行:一次一位,串行口传输方式为数据排成一行、一位一位送出接收也一样;
    并行:一位(比特)时间内可传输一个字符,并行口传输8位数据一次送出.;
    在这里插入图片描述

  2. 同步异步
    同步:同步通信要求接收端时钟频率和发送端时钟(外界时钟)频率一致,发送端发送连续的比特流,传输速度比异步传输快;
    异步:异步通信时不要求接收端时钟和发送端时钟同步,发送端发送完一个字节后,可经过任意长的时间间隔再发送下一个字节;

  3. 串行通信方式:
    在这里插入图片描述

0.1、概述

UART:(Universal Asynchronous Receiver Transmitter:通用异步收发器/异步串行通信口),是一种通用的串行数据总线,用于异步通信,支持全双工。它包括了RS232、RS499、RS423、RS422和RS485等接口标准规范和总线标准规范,即UART是异步串行通信口的总称。

IIC总线协议:I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。
SPI总线协议:SPI是串行外设接口(Serial Peripheral Interface)的缩写。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,如今越来越多的芯片集成了这种通信协议。

RS232接口缺陷:
(1)接口的信号电平值较高( +/-12V),易损坏接口电路的芯片。
(2)传输速率较低,在异步传输时,波特率为20Kbps。
(3)接口使用一根信号线和一根信号返回线而构成共地的传输形式,这种共地传输容易产生共模干扰,所以抗噪声干扰性弱。
(4)传输距离有限,最大传输距离标准值为50英尺,实际上也只能用在50米左右。

RS485是对RS232的改进,特点包括:
①接口电平低,不易损坏芯片。RS485的电气特性:逻辑“1”以两线间的电压差为+(2 ~ 6)V表示,逻辑“0”以两线间的电压差为-(2~6)V表示。接口信号电平比RS232降低了,不易损坏接口电路的芯片。
②传输速率高。10米时,RS485的数据最高传输速率可达35Mbps,在1200m时,传输速度可达100Kbps。
③抗干扰能力强。RS485接口是采用平衡驱动器和差分接收器的组合,抗共模干扰能力增强,即抗噪声干扰性好。
④传输距离远,支持节点多。RS485总线最长可以传输1200m以上(速率≤100Kbps)一般最大支持32个节点,如果使用特制的485芯片,可以达到128个或者256个节点,最大的可以支持到400个节点。
————————————————
原文链接:https://blog.csdn.net/fengge2018/article/details/107592487

1、 UART(硬件接口)

0. 基础知识

  1. 串口和UART区别?
    首先串口、COM口、UART口一般指的是硬件接口
    而TTL、RS-232、RS-485则是逻辑电平0和1的不同表示标准,它们区别如下:
    在这里插入图片描述
    1)和RS232相比,由于RS485采用了差分传输的方式,因此抗干扰能力强很多。TTL抗干扰能力最差。
    2)像STM32这类单片机的USART口,出来的电平都是TTL电平,想要和电脑通讯需要电平转换芯片。
  • 一般用TTL转USB给单片机下载程序
    在这里插入图片描述
  • 两个设备之间采用RS232通讯
    在这里插入图片描述

参考:小肥侠123

  1. USART与UART的区别?
    USART(universal synchronous asynchronous receiver and transmitte): 通用同步异步收发器
    USART是一个串行通信设备,可以灵活地与外部设备进行全双工数据交换。

    UART(universal asynchronous receiver and transmitter): 通用异步收发器
    异步串行通信口(UART)就是我们在嵌入式中常说的串口,它还是一种通用的数据通信议。

区别:

USART是指单片机的一个端口模块,可以根据需要配置成同步模式(SPI,I2C),也可以将其配置为异步模式,后者就是UART。所以说UART姑且可以称之为一个与SPI,I2C对等的“协议”,而USART则不是一个协议,而是更应该理解为一个实体。(摘自知乎-Sean回答)

相比于同步通讯,UART不需要统一的时钟线,接线更加方便。但是,为了正常的对信号进行解码,使用UART通讯的双方必须事先约定好波特率,即单位事件内传输码元的个数。
————————————————
版权声明:本文为CSDN博主「JYU_hsy」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_40774605/article/details/88398709

1.RS232(电平标准)

  1. 通信方式:RS232采用不平衡传输,即单端通信;
  2. 传输距离:适合本地设备之间通信,<20m
  3. 设备数量:一对一通信

2. RS485(电平标准)

  1. 通信方式:RS485采用了(平衡传输)差分传输的方式,因此抗干扰能力强很多;
  2. 传输距离:几十米到上千米;
  3. 设备数量:128个收发器

2. CAN

参考:
0.秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4 CAN!
CAN通信详解
1.简述STM32 CAN总线的设置
2.STM32CUBEMX系列——CAN通讯的配置
3.STM32之CAN —CAN ID过滤器分析
4.再谈STM32的CAN过滤器

  • id 是某条报文的标识符而非节点地址?
  • 过滤器?

STM32常用CAN收发器;TJA1050或者82C250。
理想情况下,可以 达 128 个,当然,使用特定的 芯片,可以达到 256 等等,这是由它自身的驱动能力决定的。​
在 CAN 总线的起止端有一个 120Ω的终端电阻,是用来来做阻抗匹配,以减少回波反射
在这里插入图片描述
在这里插入图片描述

  1. 传输数据
    每次发送数据前,节点都会监听总线的状态,如果总线状态为空闲时,它就会立即向总线上发送自己的数据,这个数据里不仅有数据,还有本身的ID信息或者其他的控制指令,应称为数据包(数据帧),也叫做报文。当报文被传输到其它节点时,只要这些节点按格式去解读,就能还原出原始数据。

    报文: 在原始数据段的前面加上传输起始标签、片选(识别)标签、控制标签,在数据的尾段加上 CRC 校验标签、应答标签和传输结束标签。类似这样的数据包就被称为 CAN 的数据帧。为了更有效地控制通讯,CAN 一共规定了 5 种类型的帧,帧也称为报文。

    五. CAN的协议层

帧的种类
通信是通过以下 5 种类型的帧进行的:
在这里插入图片描述

其中,数据帧和遥控帧有标准格式和扩展格式两种格式。
标准格式有11 个位的标识符(ID),扩展格式有29 个位的ID 。
数据帧
数据帧由 7 个段构成,包括:
(1)帧起始。表示数据帧开始的段。
(2)仲裁段。表示该帧优先级的段。
(3)控制段。表示数据的字节数及保留位的段。
(4)数据段。数据的内容,一帧可发送0~8个字节的数据。
(5)CRC段。检查帧的传输错误的段。
(6)ACK段。表示确认正常接收的段。
(7)帧结束。表示数据帧结束的段。
https://blog.csdn.net/weixin_53762042/article/details/117289970
2. 五种帧类型:在这里插入图片描述
其中数据帧又可分为以下5段
4. 数据帧是在 CAN 通讯中最主要、最复杂的报文,它以一个显性位(逻辑 0)开始,以 7 个连续的隐性位(逻辑 1)结束。在它们之间,
分为仲裁段、
 控制段、
 数据段、
 CRC 段
  ACK 段,

  以标准数据帧为例。
在这里插入图片描述
在这里插入图片描述

3、SPI

1. spi接口是干什么用的?

我们人和人传递信息一般是靠耳朵和嘴巴对吧?Spi通信传递信息是通过接口,来看下图:
在这里插入图片描述

spi接口有4根线,分别是CS、SCLK、MOSI、MISO。SCLK是同步信号,一般由主控来控制。既然是通信,自然是需要有个”对象”,如上图A和B。A是SPI Master,也就是主控,比如说单片机,一般就是主控的角色,主控来负责发送SCLK同步信号通知SPI Slave是否需要进行数据通信。B是SPI Slave,也就是从机,比如说Flash芯片。CS代表片选信号,为什么要用片选呢?因为一个SPI Master可以跟不同的SPI Slave进行通信。

在这里插入图片描述

SPI Master就是通过CS来控制,具体跟哪个SPI Slave通讯,控制CS为低电平就代表选中该SPI Slave。如果说只跟一个从设备通讯,也可以直接把CS串联电阻接地,省的每次都去控制它。MOSI英文全称是Master Output Slave Input,这个一般接主控器件数据输出引脚,从机器件数据输入引脚。MISO英文全称是Slave Input Master Output,这个一般接主控器件数据输入引脚,从机器件数据输出引脚。除此以外,还有一种特殊的用法,就是只用SCLK和MOSI这两个引脚的SPI通信。比如说我们无际单片机编程实战项目课程里有个OLED屏的应用。

在这里插入图片描述
接地了,因为只有一个从设备。我们主要是控制OLED屏去显示内容,并不需要从OLED读取数据,所以MISO也不需要。这种情况是可以只用2根线的。所以,这种协议要从本质上去理解它们,不需要死记硬背要接几个引脚

接法:
经常遇到一些朋友,在设计SPI主机和从机的逻辑互联时,会习惯性地仿照UART上的TXD和RXD交叉连接,而将SPI主机的MISO和从机的MOSI进行逻辑连接,SPI主机的MOSI和从机的MISO进行逻辑连接,结果导致设计错误。这里给大家提供一个不再出错而记忆简单的方法— 理解MISO和MISO缩写的具体含义。
MISO和MOSI的含义以及为何主机从机不能交叉接
信号 MISO = Master In Slave Out,即 在主机这边是输入,在从机那边是输出。
信号 MOSI = Master Out Slave In,即 在主机这边是输出,在从机那边是输入。根据输入接输出,输出接输入的原理,所以,就应该是

SPI主机的 MISO,直接 接 SPI从机的MISO,因为前者是输入,后者是输出。
SPI主机的 MOSI,直接 接 SPI从机的MOSI,因为前者是输出,后者是输入。
也就是,主机的MISO需要接从机的MISO,主机的MOSI需要接从机的MOSI,不能交叉接。

4、JTAG转SWD

在这里插入图片描述

二、单片机之间通信

1、串口通信

1、STM32串口之间的串口通信

参考:2个STM32串口之间的串口通信(RX,TX)
链接:https://pan.baidu.com/s/1HKGYOi58lC9GUnCSVoRyLQ
提取码:qdzy

历程是根据正点和普中的程序结合改写的。

实现的功能:

串口调试助手1通过单片机1的USART3发送数据,单片机1通过USART1传送发来的数据给单片机2的USART1,单片机2通过串口调试助手2接收数据。(具体内容自己看,多说易混淆)
反之亦然。
具体内容看实验现象。

此例程同时还是3个串口的历程,自行增减注释内容即可。
在这里插入图片描述

USB-TTL1的T接单片机1的PB11,USB-TTL1的R接单片机1的PB10;
单片机1的PA9接单片机2的PA10,单片机1的PA10接单片机2的PA9;
USB-TTL2的T接单片机2的PB11,USB-TTL2的R接单片机2的PB10;
在这里插入图片描述

实验现象:
在这里插入图片描述

在这里插入图片描述左边串口调试助手发送"1"给单片机1的USART3,单片机1的USART3触发接收中断,在中断里面用USART1发送”1“给单片机2的USART1,单片机2的USART1触发接收中断,在中断里面用USART3发送”1“给右边串口调试助手。
反之亦然。

2、STM32与Arduino串口通信实验

参考:STM32与Arduino串口通信实验

1. 参考别人

首先说明一下,arduino使用的编码方式是utf8,因此stm32的编码方式也要使用utf8才能发送汉字成功。
然后再说明一下,stm32的串口接收协议里需要接收的数据以0x0d和0x0a结尾,即末尾时\r\n,而arduino的串口协议不需要任何结尾。
stm32的编码方式设置方式为:configuration(小扳手)-> editor -> encoding -> encode in utf-8 without signature
因此为了避免格式错乱,推荐使用英文进行发送!
这里直接演示发送字符串的方式,同理发送字符就是一个字母或数字而已。

一、arduino发送字符串,stm32接收字符串
实验效果为:arduino发送一次数据,灯闪一次;stm32没收到“你好”时,LED2闪烁,收到“你好”时,LED1闪烁,LED2不再闪烁。

1.1 arduino源码

void setup() {Serial.begin(9600);pinMode(13,OUTPUT);
}void loop() {digitalWrite(13,LOW);delay(500);Serial.print("你好\r\n");digitalWrite(13,HIGH);delay(500);
}

注意:stm32是使用了我自建的库函数,是德飞莱尼莫stm32的程序。

1.2 stm32源码

#include "imut_advance.h"void SysInit()
{delay_init();                                                              LEDInit(0);LEDInit(1);                                                                              
}int main(void)
{               char t;  u16 len;       u8 lalal[]="你好";u8 mark=0;delay_init();                                LEDInit(2);LEDInit(3);uart_init(9600);NVICInit(2,0,USART1_IRQn,2);while(1){if(USART_RX_STA&0x8000){                                          len=USART_RX_STA&0x3fff;for(t=0;t                         {if(USART_RX_BUF[t]==lalal[t])mark=1;else {mark=0;break;}                       while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);}if(mark==1){while(1){LED3=!LED3;delay_ms(500);}}USART_RX_STA=0;}                        LED2=!LED2;delay_ms(500);       }
}

二、stm32发送字符串,arduino接收字符串
实验效果为:stm32发送完字符串LED2闪烁,arduino接收到字符串时灯闪烁。

arduino源码

char compare[] = "你好";
char comdata[] = "";//字符串函数
int mark;
void setup()
{Serial.begin(9600);pinMode(13,OUTPUT);}
void loop()
{if(Serial.available()){String comdata = "";//缓存清零while (Serial.available() > 0)//循环串口是否有数据{comdata += char(Serial.read());//叠加数据到comdatadelay(2);//延时等待响应}int i=0;int t;for (t=0;t       {if(comdata==compare)mark=1;else{mark=0;break;}i++;}}if(mark==1){digitalWrite(13,HIGH);delay(500);digitalWrite(13,LOW);delay(500);}
}

二、STM32程序

#include "imut_advance.h"int main()
{delay_init();                                                              LEDInit(2);LEDInit(3);                                                      KeyInit(0);KeyInit(1);KeyInit(2);                                           USARTInit(1,9600);                                                       NVICInit(2,0,USART1_IRQn,2);while(1){       LED2=!LED2;printf("你好");delay_ms(500);}
}

三、接线方式

拔掉STM32PA9和PA10的跳冒,
重点来了,STM32和Arduino的电源都不要插在电脑上,否则串口会被占用,嗯,我插在了树莓派上。
此时两个板子的灯都会闪烁。

2. 自己探索 (STM32F4 & ESP32 串口通信)

  1. 一些经验(踩过的坑)
    1.HAL_UART_Transmit 和 HAL_UART_Transmit_IT区别
    2.HAL_UART_Transmit_IT不能连续使用,如果连续使用一般只有后者能成功发送;
    3.STM32 和 arduino/ESP32 之间只需要连接 Tx & Rx 线即可(两者交叉连接)。

  2. 实验逻辑
    1.ESP32 serial2不断发送“R”
    2.STM32 开启uart8串口接收中断,若接收到的为“R”,则回复“I got ESP message!”
    3.ESP32 受到回复后,将回复打印在电脑串口监视器上。

  • STM32F4程序
//UART8´®¿Ú½ÓÊÕÖжϻص÷º¯Êý
uint16_t FOC_buff[5];
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == UART8)
{uint8_t motor1_message[] = "I got MOTOR1 message!\n";uint8_t end_n = '\n';HAL_UART_Transmit(&huart8,motor1_message,sizeof(motor1_message)/sizeof(motor1_message[0]), 0xFFFF);HAL_UART_Transmit(&huart8,rev, 5, 0xFFFF); HAL_UART_Transmit(&huart8,&end_n, 1, 0xFFFF);memset(rev, 0, 10); HAL_UART_Receive_IT(&huart8, rev, 5);				  //ÖØдò¿ª½ÓÊÕÖжÏ//	if(rev== 'R')   //´®¿ÚÖжϽÓÊÕarduinoµÄÐÅÏ¢³É¹¦£¡
//	{
		uint8_t get_Message[] = "I got ESP message!\n";
		uint8_t end_n = '\n';
		
		HAL_UART_Transmit(&huart8,&rev, 1, 0xFFFF);  
		HAL_UART_Transmit(&huart8,&end_n, 1, 0xFFFF);		HAL_UART_Transmit(&huart8,get_Message,sizeof(get_Message)/sizeof(get_Message[0]), 0xFFFF);
		
		HAL_UART_Receive_IT(&huart8, &rev,1);				  //ÖØдò¿ª½ÓÊÕÖжÏ
		rev = ' ';  
//	}
//	if(rev== 'S')
//	{
//		//HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);
//		HAL_UART_Transmit_IT(&huart8,&rev,1);
//		HAL_UART_Receive_IT(&huart8, &rev,1);
//		
//	}
}
}
  • ESP32程序
 //Serial2========================Serial2  BEGIN==========================>while (Serial2.available()) {   //外界单片机通过串口发来的电流反馈// get the new byte:char inChar = (char)Serial2.read();// add it to the string buffer:received_chars += inChar;// end of user inputif (inChar == '\n') {// execute the user commandcommand = received_chars;//============================2022/11/17 Xwave ADD BEGIN====================/* if (inChar != '\n') received_chars += inChar;else if (inChar == '\n') //当遇到换行符号,将接收到的数据打印{              Serial.println("来自串口的信息:");Serial.println(received_chars);}String motor1_str = received_chars;        int motor1_int = motor1_str.toInt();            //Arduino string 转为intdouble motor1_current = motor1_str.toDouble();   //Arduino string 转为double*///============================2022/11/17 Xwave ADD END====================/* execute the user command *///根据逗号分离两组字符串//想象中双足轮通讯数据格式:高度,指令   指令格式:英文+值commaPosition = command.indexOf(',');//检测字符串中的逗号if(commaPosition != -1)//如果有逗号存在就向下执行{motor1_Serial2_angle = command.substring(0,commaPosition).toDouble();            //一号电机对应的反馈电流motor2_Serial2_angle = command.substring(commaPosition+1, command.length()).toDouble();
//          Serial.print("motor1_current:");
//          Serial.println(motor1_current);
//          Serial.print("motor2_current:");
//          Serial.println(motor2_current);Serial.print("motor1_Serial2_angle:");Serial.println(motor1_Serial2_angle);Serial.print("motor2_Serial2_angle:");Serial.println(motor2_Serial2_angle);}// reset the command buffer received_chars = "";}}  //============================2022/11/17 Xwave ADD BEGIN====================
//串口2 向STM32发送 //char a = 'R';//Serial2.print('R'); if( (sensor.getAngle() > 0.2 || sensor.getAngle() < -0.2) || (sensor1.getAngle() > 0.2 || sensor1.getAngle() < -0.2) ){sum++;if(sum>100){sum = 0;char MOTOR_angle[20];sprintf(MOTOR_angle, "%f,%f", sensor.getAngle(), sensor1.getAngle());Serial2.println(MOTOR_angle); //Serial.println(MOTOR_angle); memset(MOTOR_angle, 0, sizeof(MOTOR_angle));     }}//============================2022/11/17 Xwave ADD END====================      //Serial2========================Serial2  END==========================>

3. STM32串口数据拆分处理的程序

  1. stm32接收到数据“s555s”,分割数据为“555”,然后转化为int型555。
    在这里插入图片描述
  2. 中断接收、轮询发送,队列模式
    在这里插入图片描述
/******************************STM32中断接收处理流程*************************************/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{/*****************************USART 1**********************************/if (huart->Instance == USART1){if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET)    //判断是否是接收中断{Que.queue_busy = 1;    //队列忙碌,写数据中Queue_Push(&Que, (uint8_t)(huart1.Instance->DR&(uint8_t)0x00FF));    //后向入队Que.queue_busy = 0;__HAL_UART_CLEAR_FLAG(&huart1, UART_FLAG_RXNE);    //清中断标志位}}
}/******************************主进程处理*************************************/
void survice_queue(void)
{if (Que.queue_busy == 0)    //队列是否忙碌{/*    获取数据,获取到帧头和帧尾返回最终的帧长度,如果超过FRAME_MAX_SIZE还没获取到帧尾,返回0结束掉*/RecCmdLen = Queue_find_cmd(&Que, buffer, FRAME_MAX_SIZE);}if (RecCmdLen > 8)   //因为设计帧头和帧尾总共8字节,再加上数据长度至少是9个长度{// 获取指令的时候已经校验过帧头尾,所以这里直接处理数据for (uint8_t i = 0; i < RecCmdLen - 8; i ++){printf("%d ", buffer[4 + i]);}printf("\r\n");memset(buffer, 0, FRAME_MAX_SIZE);RecCmdLen = 0;}
}
  1. chatGPT生成代码

基于STM32的串口数据拆分处理的示例程序,假设要接收的数据为数字类型的字符串,以“\r\n”作为结束符:

#include "stm32f1xx_hal.h"#define BUFFER_SIZE 32UART_HandleTypeDef huart1;
char buffer[BUFFER_SIZE];
uint8_t index = 0;void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{if (huart->Instance == USART1){if (index == BUFFER_SIZE - 1){index = 0;}if (buffer[index - 1] == '\r' && buffer[index] == '\n'){//处理接收到的完整字符串buffer[index - 1] = '\0';  //去除结束符//在此处进行字符串转换为数字的操作//... 使用atoi(buffer);  ?index = 0;}else{index++;}HAL_UART_Receive_IT(&huart1, (uint8_t*)&buffer[index], 1);}
}int main(void)
{HAL_Init();__HAL_RCC_GPIOA_CLK_ENABLE();__HAL_RCC_USART1_CLK_ENABLE();GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = GPIO_PIN_9;GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);huart1.Instance = USART1;huart1.Init.BaudRate = 9600;huart1.Init.WordLength = UART_WORDLENGTH_8B;huart1.Init.StopBits = UART_STOPBITS_1;huart1.Init.Parity = UART_PARITY_NONE;huart1.Init.Mode = UART_MODE_TX_RX;huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;huart1.Init.OverSampling = UART_OVERSAMPLING_16;HAL_UART_Init(&huart1);HAL_UART_Receive_IT(&huart1, (uint8_t*)&buffer[index], 1);while (1){}
}

该程序使用HAL库提供的UART接收中断回调函数HAL_UART_RxCpltCallback实现串口数据的异步接收和处理。接收到的数据存储在一个循环缓冲区buffer中,如果接收到了结束符“\r\n”,则将其视为一个完整的字符串进行处理。
在回调函数中,首先判断接收到的数据是否到达缓冲区的末尾,如果是,则重置缓冲区索引index,以便下一次数据接收。然后判断是否接收到了结束符,如果是,则将其替换为字符串结束符\0,表示字符串的结束,并在此处进行字符串转换为数字的操作。最后重启数据接收中断,以便继续接收下一组数据。
在主函数中,初始化串口配置并启动数据接收中断。程序进入死循环,等待中断的触发。

4. 自研STM32串口数据拆分为浮点型方案

在这里插入图片描述

#include <stdio.h>
#include "stdlib.h"
#include "string.h"int main()
{/*  发送端 */float motorA_angle = -1239.9;float motorB_angle = -1234.89;float Go_Back = -1000.1;float Out_Back = -3567.8;char b[32];float  a[4];memset(b, 0, sizeof(b));sprintf(b, "%7.1f%7.1f%7.1f%7.1f\r\n", motorA_angle, motorB_angle, Go_Back, Out_Back);HAL_UART_Transmit(&huart8,(uint8_t*)b,sizeof(b)/sizeof(b[0]), 0xFFFF);/*  接收端 */char motorA[7], motorB[7], G_B[7], O_B[7];HAL_UART_Receive_IT(&huart1, (uint8_t*)b, 1);
for(int i = 0; i < 7; i++)
{
motorA[i] = b[i];      //总结:%7.1f中不会把负号、小数点做一位  因此1234.5、-1234.5 都被看做5位
motorB[i] = b[i+7]; //而字符串数组中会把负号、小数点做一位,  因此1234.5、-1234.5 分别为6位和7位
G_B[i] = b[i+14];     //综上都选数字7 不会出错
O_B[i] = b[i+21];
}a[0] = atof(motorA);a[1] = atof(motorB);a[2] = atof(G_B);a[3] = atof(O_B);printf("b= %s \n",b);printf("a[0]= %7.1f \n", a[0]);printf("a[1]= %7.1f \n", a[1]);printf("a[2]= %7.1f \n", a[2]);printf("a[3]= %7.1f \n", a[3]);return 0;
}

3、Arduino 串口通讯

解析上位机发来的多个变量
Arduino IDE中的Serial函数异常好用,最关键的是indexof,可以提取出规定“标记(如ABC)”后的整数或者浮点数
以下函数实现三个变量的传递

在“串口助手”界面输入A10.25B5C2.35并发送时
x_int 等于10.25
y_int等于5
z_int等于2.35

4. Arduino 串口绘图

Arduino 串口绘图

显示多条曲线

直接打印,数据间隔使用逗号(,),最后使用println打印数据。

Serial.print(a); 
Serial.print(",");
Serial.println(b);

2、CAN通信

1、STM32C8T6 和 robomaste A板(F4)——CAN 通信

1. 参考别人

  1. 基于CubMX IDE 开发:STM32F103C8T6配置CAN 通信
  2. STM32F103C8T6调试CAN通讯
  3. STM32CubeMX 配置CAN总线进行双板通信(STM32F103C8T6)
  4. STM32 CAN过滤器配置详解
  • 不设置过滤器
 void CANFilter_Config(void)
{CAN_FilterTypeDef  sFilterConfig;sFilterConfig.FilterBank = 0;                       //CAN过滤器编号,范围0-27sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;   //CAN过滤器模式,掩码模式或列表模式sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;  //CAN过滤器尺度,16位或32位sFilterConfig.FilterIdHigh = 0;			//32位下,存储要过滤ID的高16位sFilterConfig.FilterIdLow = 0;					//32位下,存储要过滤ID的低16位sFilterConfig.FilterMaskIdHigh = 0;			//掩码模式下,存储的是掩码sFilterConfig.FilterMaskIdLow = 0;sFilterConfig.FilterFIFOAssignment = 0;				//报文通过过滤器的匹配后,存储到哪个FIFOsFilterConfig.FilterActivation = ENABLE;    		//激活过滤器sFilterConfig.SlaveStartFilterBank = 0;if (HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK) {Error_Handler();}}
  • 只接收报文id为0x1ff开头的
void CAN_User_Init(CAN_HandleTypeDef* hcan )   //用户初始化函数
{CAN_FilterTypeDef  sFilterConfig;HAL_StatusTypeDef  HAL_Status;sFilterConfig.FilterActivation = ENABLE;  	//激活过滤器sFilterConfig.FilterBank = 1;                       //过滤器1sFilterConfig.FilterMode =  CAN_FILTERMODE_IDMASK;  //设为掩码模式sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;    //设为32位sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;    //接收到的报文放入到FIFO中sFilterConfig.FilterIdHigh = 0x1ff<<5;   //把基本ID放入到STID中sFilterConfig.FilterIdLow  = 0x1ff0<<5;sFilterConfig.FilterMaskIdHigh =0xffff;sFilterConfig.FilterMaskIdLow  =0xffff;sFilterConfig.SlaveStartFilterBank  = 0;HAL_Status=HAL_CAN_ConfigFilter(hcan, &sFilterConfig);HAL_Status=HAL_CAN_Start(hcan);  //开启CANif(HAL_Status!=HAL_OK){
//	printf("开启CAN失败\r\n");}HAL_Status=HAL_CAN_ActivateNotification(hcan,CAN_IT_RX_FIFO0_MSG_PENDING);if(HAL_Status!=HAL_OK){//printf("开启挂起中段允许失败\r\n");}
}

这样设置也可

  sFilterConfig.FilterIdHigh = 0x1ff<<5;   //把基本ID放入到STID中sFilterConfig.FilterIdLow  = 0;sFilterConfig.FilterMaskIdHigh =0xffff;sFilterConfig.FilterMaskIdLow  =0;

2. 自己探索

原先是robomaste A板和GM6020电机之间进行CAN通信,
电机可以通过拨码设置ID,1到7
电机CAN波特率:1Mbps
而A板的波特率设置却为:X M/3/(9+4+1)=X bps

技术指标

  1. GM6020电机的CAN收发程序未知,要自己实现
  2. 波特率按照1Mbps 还是 X bps
  3. STM32C8T6 CAN端要连接 J1050模块的Rx Tx
  4. C8T6 发送报文的id要注意,报文只能被A板读取,不能被电机读取
  5. C8T6 过滤器要注意,只接收A板报文,不能接收电机报文。

下列文件均放在坚果云中

    1. A板(F427)中CAN发送程序
/*bsp_can.c文件*/
//A板用以下函数向电机发送CAN报文
void set_motor_voltage(uint8_t id_range, int16_t v1, int16_t v2, int16_t v3, int16_t v4)
{CAN_TxHeaderTypeDef tx_header;uint8_t             tx_data[8];//第一个参数为0:标识符0x1FF 控制前四个电机
//第一个参数不为0:标识符0x2FF 控制后三个电机	tx_header.StdId = (id_range == 0)?(0x1ff):(0x2ff);tx_header.IDE   = CAN_ID_STD;tx_header.RTR   = CAN_RTR_DATA;tx_header.DLC   = 8;tx_data[0] = (v1>>8)&0xff;tx_data[1] =    (v1)&0xff;tx_data[2] = (v2>>8)&0xff;tx_data[3] =    (v2)&0xff;tx_data[4] = (v3>>8)&0xff;tx_data[5] =    (v3)&0xff;tx_data[6] = (v4>>8)&0xff;tx_data[7] =    (v4)&0xff;HAL_CAN_AddTxMessage(&hcan1, &tx_header, tx_data,(uint32_t*)CAN_TX_MAILBOX0); 
}
    1. STM32C8T6中CAN接收程序
      参考:基于CubMX IDE 开发:STM32F103C8T6配置CAN 通信
CAN_TxHeaderTypeDef Can_Tx;
CAN_RxHeaderTypeDef Can_Rx;
uint8_t Rxdata[8];
uint8_t Txdata[8] = {0};
extern uint8_t can_rx_finish_flag;//stm32f1xx_it.c中 CAN接收中断函数
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef* hcan1)
{uint8_t i;printf("***********************************************\r\n");HAL_CAN_GetRxMessage(&hcan,CAN_RX_FIFO0,&Can_Rx,Rxdata);can_rx_finish_flag=1;printf("RX ID:0x%X\r\n",Can_Rx.StdId);  printf("RX DATA: %02X%02X%02X%02X%02X%02X%02X%02X\r\n",Rxdata[0],Rxdata[1],Rxdata[2],Rxdata[3],Rxdata[4],Rxdata[5],Rxdata[6],Rxdata[7]);CH3 = (Rxdata[4]<<8) | Rxdata[5];CH4 = (Rxdata[6]<<8) | Rxdata[7];	printf("CH3:%d CH4:%d\r\n", CH3, CH4);
}
/* USER CODE END 1 */
  1. A板(F427)中CAN接收中断程序
//A板接收到电机的CAN消息后执行以下回调函数:
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{CAN_RxHeaderTypeDef rx_header;uint8_t             rx_data[8];if(hcan->Instance == CAN1){HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data); //receive can data}if ((rx_header.StdId >= FEEDBACK_ID_BASE)&& (rx_header.StdId <  FEEDBACK_ID_BASE + MOTOR_MAX_NUM))                  // judge the can id{can_cnt ++;uint8_t index = rx_header.StdId - FEEDBACK_ID_BASE;                  // get motor index by can_idmotor_info[index].rotor_angle    = ((rx_data[0] << 8) | rx_data[1]);motor_info[index].rotor_speed    = ((rx_data[2] << 8) | rx_data[3]);motor_info[index].torque_current = ((rx_data[4] << 8) | rx_data[5]);motor_info[index].temp           =   rx_data[6];}if (can_cnt == 500){can_cnt = 0;LED_GREEN_TOGGLE(); // green led blink indicate can comunication successful }
}

三、板子开发常用语句

1、Arduino框架常用语句

1. 标准模板

#define PIN 12
void setup(){digitalWrite(PIN,HIGH);pinMode(PIN,OUTPUT);
}
void loop(){digitalWrite(PIN,LOW);
}

2. 常见函数

1.常用语句

  1. #define PIN 12
    int PIN 12; //两者都是可以的,int更灵活,define程序运行中不可修改。
  2. 串口使用
    1.串口打印:
Serial.begin(9600);` //打开串口Serial.println("Key Down");Serial.println(a.DEC)  //以十进制输出a的值;Serial.print("Hello warld!\n");// Serial.println() 不能像printf那样格式化输出很多变量,可以用以下方式char R_nums[20];sprintf(R_nums, "R1:%d | R2:%d", val1, val2);Serial.println(R_nums); memset(R_nums, 0, sizeof(R_nums)); //或者用笨方法,多行Serial.println()
Serial.print(val1);
Serial.print(" | ");
Serial.println(val2);

2.串口输入:

使用Serial.available()来检测串口缓冲区中是否有可读数据,然后再使用Serial.read()读取数据;

  if(Serial.available()){while(n--){c = Serial.read();Serial.print(c);  }}
  1. pinMode(pin, mode),配置引脚模式

pin:为引脚的编号
mode:该引脚的模式,
INPUT:输入模式,
OUTPUT:输出模式, 在此模式下digitalWrite和digitalRead都可以使用。
INPUT_PULLUP:输入上拉模式

  1. digitalWrite(pin,value); //定义引脚的电平
    >value:表示为HIGH(高电平)或LOW(低电平)
    int val;
    val = digitalRead(7); // 读出脚位 7 的值并指定给 val
  • 例:
#define LED PB5       //定义LED引脚为13
#define BUTTON PE3    //定义按钮开关引脚为12
int val = 0;        //变量val用来储存按钮状态
int old_val = 0;    //暂存val变量的上一个时间单位int state = 0;       //0表示LED关闭,1表示打开void setup(){pinMode(LED, OUTPUT);     //设定LED引脚为输出状态pinMode (BUTTON,INPUT);   //设定按钮引脚为输入状态
}void loop(){val = digitalRead(BUTTON); //读取按钮状态并储存//检查按钮的变化情况
if(val == HIGH){digitalWrite(LED,HIGH);}else{digitalWrite(LED,LOW); 
}
}
  1. analogWrite(pin, value); //数字IO口PWM输出函数

pin:对于 ATmega168芯片的Arduino(包括Mini或BT),
该函数可以工作于 3, 5, 6, 9, 10和 11号接口
value表示为0~255,对应0 到 100%占空比,同时也对应0~5V电压。
int analogRead(pin)
val = analogRead(2); //读出类比脚位 2 的值并赋值给 val
#如果要这个引脚输出的话,记得要在setup()函数里面声明
pinMode(4,OUTPUT); int analogRead(pin)前面也可以设置引脚模式。
通过使用**analogRead()**函数,我们可以读取施加到其中
一个引脚的电压。比如可以读模拟传感器(10位AD,0~5V表示为0~1023)。

analogWrite(pin,val)往指定pin引脚写入数据
例如analogWrite(4,520),表示给D4这个角写入占空比为520/1024的pwm波。
这里要说明一下,analogWrite()默认的频率是1khz,默认占空数值是1024。
如果要这个引脚输出的话,记得要在setup()函数里面声明
pinMode(4,OUTPUT);

analogWriteRange(new_range)
可以改变占空数值,默认是1024,可以改成2048,这样精度就提高了1倍,其实也只是控制输出而已,实际我感觉没卵用。

analogWriteFreq(new_frequency)
设置新的pwm频率,analogWrite()默认是1khz,可以设置成别的,其实改变的是周期。
ESP32在arduino中没有提供PWM例程,没有像Arduino 官方板子之类的有analogWrite方法
参考:CSDN

  1. delay(ms); // 延时函数
    delayMicroseconds (us) ; //us 是要暂停的微秒数(无符号整型)。
  2. val = abs(-5); // abs(x)计算绝对值,注意不要在括号里写计算式。

2.Arduino中断

  1. <RESET中断><时钟中断><外部中断>
    (1)RESET中断,就是当RESET管脚接低电平,则中止当前程序,重启CPU
    (2)时钟中断,是指设定CPU内部定时器后,当到达指定时间,将产生中断请求。常用于定时。
    (3)外部中断,就是当CPU的外部中断管脚电平变动时,将产生中断请求。
    常用于键盘输入、串口通信等。

  2. 外部中断

  • attachInterrupt()函数的语法介绍
attachInterrupt( digitalPinToInterrupt(pin) , function, mode)

(1)digitalPinToInterrupt(pin) :取得引脚pin的中断号
(2)function:中断发生时调用的函数,此函数必须不带参数和不返回任何值。该函数称为中断服务程序。
(3)mode:定义何时发生中断以下四个contstants预定有效值:
LOW 当引脚为低电平时,触发中断
CHANGE 当引脚电平发生改变时,触发中断
RISING 当引脚由低电平变为高电平时,触发中断
FALLING 当引脚由高电平变为低电平时,触发中断.

3. string to int/float/double

arduino通过串口接收到的字符串数据需要转化为其他类型,才能用于其功能实现。

//字定义需要转换的字符串数据String my_str = "12345.123";//字符串转换成整型数据;int my_int = my_str.toInt();Serial.println(my_int);//字符串转换成Float类型Serial.println(my_str.toFloat());//字符串转换成Double类型Serial.println(my_str.toDouble();//整型转换成字符串,int ty = 1000;String mystr=String(ty);Serial.println(mystr+mystr);

4. ESP32 arduino PWM 驱动SG90舵机

ESP32精简版有更简洁的方法
参考:CSDN1ESP-Arduino(四) PWM波形控制输出

可用于驱动舵机,改一下也可用于LED调光
连接方式:
红线—5v
黑线—GND
黄线—PIN16

#include <Arduino.h>
//通过ESP32的 LEDC 来实现PWM
int freq = 50;      // 频率(20ms周期)
int channel = 8;    // 通道(高速通道(0 ~ 7)由80MHz时钟驱动,低速通道(8 ~ 15)由 1MHz 时钟驱动。)
int resolution = 8; // 分辨率
const int led = 16;int calculatePWM(int degree)
{ //0-180度//20ms周期,高电平0.5-2.5ms,对应0-180度角度const float deadZone = 6.4;//对应0.5ms(0.5ms/(20ms/256))const float max = 32;//对应2.5msif (degree < 0)degree = 0;if (degree > 180)degree = 180;return (int)(((max - deadZone) / 180) * degree + deadZone);
}void setup()
{Serial.begin(9600);ledcSetup(channel, freq, resolution); // 设置通道ledcAttachPin(led, channel);          // 将通道与对应的引脚连接
}void loop()
{for (int d = 0; d <= 180; d += 10){ledcWrite(channel, calculatePWM(d)); // 输出PWMSerial.printf("value=%d,calcu=%d\n", d, calculatePWM(d));delay(1000);}  
}

LED控制(LEDC)外围设备主要用于控制LED的强度,尽管它也可以用于生成PWM信号用于其他目的。它具有16个通道,可以生成独立的波形,这些波形可以用于驱动RGB LED器件。

5、string -> int/double

      String motor1_str = received_chars;        int motor1_int = motor1_str.toInt();            //Arduino string 转为intdouble motor1_current = motor1_str.toDouble();   //Arduino string 转为double

四、常见执行器/模块

1、舵机

1.PWM对舵机的控制

参考:yushuir

舵机的控制就是通过一个固定的频率,给其不同的占空比的,来控制舵机不同的转角

舵机的频率一般为频率为50HZ(周期:20ms),也就是一个20ms左右的时基脉冲,而脉冲的高电平部分一般为0.5ms-2.5ms范围(也就是占空比2.5%-12.5%)。来控制舵机不同的转角

500-2500us的PWM高电平部分对应控制180度舵机的0-180度

以180度角度伺服为例,那么对应的控制关系是这样的:
0.5ms--------------0度;
1.0ms------------45度;
1.5ms------------90度;
2.0ms-----------135度;
2.5ms-----------180度;

在这里插入图片描述

2、0.96寸OLED

在这里插入图片描述

1. 用STM32C8T6控制其显示IMU信息

  • STM32C8T6程序:
    oled.h、oled.c文件
//加入头文件
#include "oled.h"int main(void)
{unsigned char BMP[300];OLED_Init();OLED_Clear();OLED_ShowString(0, 0, "P_bot: by XWAVE", 16);OLED_Clear();OLED_ShowString(0, 0, "P_bot:>", 16);HAL_Delay(500);//...OLED_ShowString(0, 0, "P_bot:>>>>ready", 16);HAL_Delay(500);OLED_Clear();while (1){char IMU_str1[100];char IMU_str2[100];memset(IMU_str1, 0, sizeof(IMU_str1));memset(IMU_str2, 0, sizeof(IMU_str2));sprintf(IMU_str1, "X:%6.1f¡ãY:%4.1f¡ã\r\n", roll, pitch);sprintf(IMU_str2, "Z:%6.1f¡ãT:%2.f¡ãC\r\n", yaw, temp/100);//屏幕上打印变量OLED_ShowString(0, 2, IMU_str1, 10);OLED_ShowString(0, 3, IMU_str2, 10);}}

3、L298N电机驱动模块

参考:基于stm32的减速直流电机PID算法控制
在这里插入图片描述

1.模块可驱动两路直流电机,输出A和B各接一直流电机即可;
2.若使用12V供电,将12V供电端口及GND接上电源正负即可,同时5V供电端可以作为最小系统板的输入电源;
3.若不需要使用PWM调速,只需要控制电机正反转,则逻辑A与B跳线帽插上即可,相当于始终使能;
4.若需要使用PWM调速,需将跳线帽拔起,将使能端接上单片机IO口。(定时器IO口,PWM输出模式);
5.逻辑输入四个端口IN1、IN2、IN3、IN4接单片机四个IO口,每两个端口控制的一路电机。
6.该驱动板最大功率:25W

温馨提示:不建议新手或者资金有限的情况下,使用电机驱动模块直连成品开发板,很容易烧坏。(在中间加一个降压稳压模块)

    原因:(1) 由于电机的特性,电机在堵转或者高负载下,电流会增大,可能会影响到单片机。(2)新手玩单片机可能出现短路等情况,很容易板子冒烟;

L298N的转动逻辑图:
在这里插入图片描述

4、蓝牙模块

在这里插入图片描述

HC-05(ZS-040)蓝牙模块使用详情
亲测后上述教程纠正如下:

  1. 通电前按住按钮再通电进入AT模式;
  2. 进入AT模式是慢闪的,在任意模式中与手机连接成功之前是快闪;

五、常用接插件

1. 小接插件

(排针的孔间距为2.54mm)
VH:3.96mm
XH:2.54mm
GH:1.25mm(DJI GM6020 CAN 通信接插件)
JST:1.25mm
HY:2.0mm

在这里插入图片描述
在这里插入图片描述

2. 大功率接插件

XT30 2P/3P

在这里插入图片描述

SM: 2.54mm
JST
工控机端子:2EDGKD:2.5/LC10N:3.81/2EDGKD:5.08mm
在这里插入图片描述

六、立创使用攻略

1. 开源项目打板

  1. 在网页版立创EDA的开源广场找到收藏量高的项目
  2. 在编辑器打开项目
  3. 在PCB页面“G”标签检查并提交PCB订单
  4. 在嘉立创网页领取优惠券(每个账户每月两张)可打板最大10*10cm,最多四层的五块板子;
  5. 使用优惠券提交订单,支付,便可在公众号追踪订单进度;

2. 自己画板打板

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

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

相关文章

【LabVIEW FPGA图形化】IP集成节点:IIC通信实验

目录 一、前情提要二、FPGA蔡氏定律三、LabVIEW FPGA IP集成节点网表文件的编写四、IIC时序仿真五、FPGA图形化程序编写总结 一、前情提要 上一节内容介绍了图形化FPGA的USB通信&#xff0c;USB通信主要用于FPGA与上位机之间的通信&#xff0c;对于器件&#xff08;芯片&#…

人工智能前沿知识

本来想着初试完学习一下李沐大神的《动手学深度学习》这本书的&#xff0c;但是时间仓促&#xff0c;完全来不及。只能先自行了解一些知识&#xff0c;之后再深入了解。 这里为面试应答&#xff0c;问了chatgpt一些关于AI前沿的知识&#xff1a; 还需要再了解一番&#xff1a;…

Squid代理服务器应用及配置(图文详解)

Squid缓存代理 Squid代理服务器代理的工作机制代理的基本类型传统代理透明代理反向代理 使用代理的好处 实验环境部署squid代理安装关闭防护墙安装依赖环境编译安装Squid脚本解释创建软连接及用户&#xff0c;改组 修改Squid的配置文件squid检查启动 编写Squid服务脚本服务启动…

chatgpt赋能python:Python方法重写:提升代码复用性和性能优化

Python方法重写&#xff1a;提升代码复用性和性能优化 Python是一门简洁、易读易写的语言&#xff0c;但在实际的编程开发中&#xff0c;我们往往会遇到代码复用性不高、性能不够优化等问题。而方法重写是一种有效的方式来解决这些问题。 什么是方法重写&#xff1f; 方法重…

chatgpt如何联网?访问2021年之后的信息

介绍 一般来说&#xff0c;chatgpr稚嫩恶搞访问2021年之前的事。 chatgpt如何联网&#xff1f; 如何访问2021年之后的信息&#xff1f; 方法 打开edge浏览器啊&#xff0c;添加拓展 “webchatgpt” 举例子

白痴学日语系列之模拟题

题型一、单词 汉字对应的假名 1、小卖部 2、杂志 3、礼物 おみやげ 4、公司职员 5、老师 假名对应的汉字 6、社长&#xff0c;总经理 7、星期六 8、房间 9、迟到 10、下个月 选平假名对应的片假名 11、美国 12、足球 13、出租车 14、百货商场 15、便利店 题型二、选择题 1…

白痴学日语系列之初识日语(三)

每日记单词 足/脚[あし]2 a shi 脚&#xff1b;腿 【记】あ&#xff08;恶&#xff09;し&#xff08;像&#xff09;→身上脏的地方→腿&#xff1b;脚 联想记忆&#xff0c;阿西吧&#xff08;阿西吧&#xff0c;意思类似于我去&#xff0c;是表示对某一事件或者某一事物感…

chatgpt赋能python:PythonRPG游戏:带你进入主角的魔幻冒险世界

Python RPG游戏&#xff1a;带你进入主角的魔幻冒险世界 Python是一种广泛使用的高级编程语言&#xff0c;被用于开发各种应用程序和游戏。其中&#xff0c;RPG游戏是其中最受欢迎的游戏之一。Python的各种优点使其成为开发RPG游戏的一个理想选择。在这篇文章中&#xff0c;我…

游戏思考26:游戏服务器压力测试文档(新增linux相关命令,02/10未完待续)

文章目录 一、压力测试关注点二、计算最耗时的加载操作1&#xff09;从数据库读取数据&#xff0c;对加载的类型进一步划分各种类型&#xff0c;计算最耗时操作2&#xff09;查看CPU随着在线人数的变化所占百分比3&#xff09;查看内存变化4&#xff09;备注 三、MMORPG服务器对…

C语言——飞机游戏

目录 前言 一、飞机游戏的代码 二、代码解析 1、代码重构 1&#xff09;主函数 2&#xff09;其它函数 2、新的子弹 3、敌机 1&#xff09;静止的敌机 2&#xff09;敌机的移动 3&#xff09;击中敌机 4、清屏功能 总结 前言 代码参考了《C语言课程设计与游戏开发…

谈一谈游戏AI - 综述

成功者总是善于发现 “可学之处”&#xff0c;执着精进&#xff1b;失败者总是善于发现 “不可学之处”&#xff0c;怨天尤人。 郑重说明&#xff1a;本文适合对游戏开发感兴趣的小白初学者&#xff0c;本人力图将事物用简单的语言表达清楚&#xff0c;但水平有限&#xff0c;能…

安卓版ChatGPT要上线了!

Datawhale干货 最新&#xff1a;ChatGPT安卓版&#xff0c; 来源&#xff1a;机器之心 自发布以来&#xff0c;ChatGPT 一直受到高度关注&#xff0c;在全球范围内吸引了大量用户。有机构统计认为&#xff0c;早在今年 1 月&#xff0c;ChatGPT 的用户量就已经超过了一亿。彼时…

必看!大语言模型调研汇总!!

作者&#xff1a;guolipa 知乎 自从ChatGPT出现之后&#xff0c;各种大语言模型是彻底被解封了&#xff0c;每天见到的模型都能不重样&#xff0c;几乎分不清这些模型是哪个机构发布的、有什么功能特点、以及这些模型的关系。比如 GPT-3.0 和 GPT 3.5 就有一系列的模型版本…

一网打尽!国内外50多个大模型调研汇总

因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享 点击关注#互联网架构师公众号&#xff0c;领取架构师全套资料 都在这里 0、2T架构师学习资料干货分 上一篇&#xff1a;ChatGPT研究框架&#xff08;80页PPT&#xff0c;附下载&#xff09;…

大语言模型调研汇总

自从ChatGPT出现之后,各种大语言模型是彻底被解封了,每天见到的模型都能不重样,几乎分不清这些模型是哪个机构发布的、有什么功能特点、以及这些模型的关系。比如 GPT-3.0 和 GPT 3.5 就有一系列的模型版本和索引,还有羊驼、小羊驼、骆驼 ...... 于是浅浅的调研了一下比较有…

总结从T5、GPT-3、Chinchilla、PaLM、LLaMA、Alpaca等近30个最新模型

自从ChatGPT出现之后&#xff0c;各种大语言模型是彻底被解封了&#xff0c;每天见到的模型都能不重样&#xff0c;几乎分不清这些模型是哪个机构发布的、有什么功能特点、以及这些模型的关系。比如 GPT-3.0 和 GPT 3.5 就有一系列的模型版本和索引&#xff0c;还有羊驼、小羊驼…

一网打尽!国内外大模型调研汇总

作者 | guolipa 整理 | NewBeeNLP https://zhuanlan.zhihu.com/p/614766286 大家好&#xff0c;这里是 NewBeeNLP。 自从ChatGPT出现之后&#xff0c;各种大语言模型是彻底被解封了&#xff0c;每天见到的模型都能不重样&#xff0c;几乎分不清这些模型是哪个机构发布的、有什…

学习笔记借助chatGPT生成excel统计公式

要求&#xff1a;通过Excel公式提取ExcelB列表格中邮箱名称&#xff08;之前的字符&#xff09; 知道老板要求后&#xff0c;我们就需要写出对应的提取公式&#xff0c;可是对于Excel公式使用不熟练的人来说&#xff0c;这个公式如何写呢&#xff1f;这时候我们就需要借助chatG…

《辉煌优配》6G技术推进下,CPO引领光通信发展新方向

3月1日&#xff0c;中国工业和信息化部部长金壮龙在国务院新闻办新闻发布会上表明&#xff0c;工信部将研究制定未来产业开展行动计划&#xff0c;加快布局人形机器人、元宇宙、量子科技等前沿范畴&#xff0c;全面推动6G技能研制。2月27日&#xff0c;2023年世界移动通讯大会&…

动态销售看板图表 | 汇总不同部门数据,一键切换部门

背景&#xff1a;公司有五十多个子部门&#xff0c;每个sheet存储着每个部门的所有数据&#xff08;不sheet表格结构需要保持一致&#xff09;&#xff0c;如果想将每个部门月至今的销售数据做成图表&#xff0c;怎么办&#xff1f;50多个sheet逐一添加图表&#xff1f;当然不&…