【核知坊】:释放青春想象,码动全新视野。
我们希望使用精简的信息传达知识的骨架,启发创造者开启创造之路!!!
由于 Koro 能力有限,文中难免出现错误,如有发现请在评论区指出,Koro 看到后会尽快调整!!!
内容摘要:你是否是即将毕业的电子与信息工程专业接班人?你的毕业设计是否与单片机相关?面对选题是否毫无头绪,无从下手?如果你正被这些问题困扰,不妨看看这篇文章。本文专为初涉嵌入式开发的你而撰写,围绕"如何快速启动一个 STM32 裸机项目"展开,帮助你理清开发流程、打开思路。无论你刚接触 STM32,还是在项目启动阶段卡壳,这里都能为你提供一个清晰的起点。看完这篇文章,你将不再迷茫,能够迅速进入毕业设计状态,迈出关键的第一步,甚至今晚都能睡个好觉 —— 因为你终于知道明天该干什么了。
关键词:STM32 Keil5 毕业设计 C语言
其他相关文章:
⛏正在赶稿中....
1.STM32裸机开发一般流程图

一个以 main.c 为核心的、由多个 .c
和 .h
文件组成的“网状结构”工程 → 经由 编译器和链接器 处理,生成机器能够识别的 二进制文件(如 .hex
或 .bin
) → 通过下载器 烧录到 STM32 芯片中,最终让芯片运行你的程序。
2.直入主题【以STM32F103型号,标准库为例】
2.1 前期准备
开题报告已经可以看出你毕设基本需求了,需求要明确,有什么限制条件,完成什么样的功能。根据需求选择合适的STM32型号,大部分项目使用STM32F103系列就足够了。最常见的就是使用STM32最小系统板与传感器连接,完成完整的系统。
2.2 资料查找
参考论文,常用软件,模块资料,教程等。硬件最好准备齐全,方便直接进行调试。
-
电商客服 ⭐⭐⭐⭐ -------------找到相关店铺,直接问有没有xxx资料
-
AI + 浏览器 ⭐⭐⭐ -------------找下载资源,文章
-
哔哩哔哩 ⭐⭐⭐ -------------评论区有宝藏
-
github|gitee|gitcode ⭐⭐⭐ -----------找项目必备
-
直接买 ⭐⭐ -------------有风险需谨慎
-
微信搜索 ⭐⭐ -------------公众号白嫖
-
QQ xxx交流群 ⭐ -------------大佬们,有xxx资料吗
-
其他渠道(如野火官网)⭐ ⭐ ⭐
小技巧:访问不了的网站可以尝试搜索xxx镜像站,例如谷歌学术镜像站。
2.3 Keil5安装
B站视频教程,海量博客教学文章都可以找到。也就这几步:下载破解版安装包->安装固件库包->破解软件->打开软件并熟悉功开发界面。凡是从客服那获取的与硬件有关的网盘资料里大概率包含Keil5安装包,如果没有就多问几家吧,也可以去野火官网获取。安装CH340串口驱动与其他驱动--------驱动是一个可以识别与操控硬件的软件。
2.4 STM32基本知识
系统时钟:有节奏的滴答器,这是芯片正常运行必备前提。没了时钟,就像人没了心脏。
-
HSI: 内部高速时钟,8MHz,芯片内置,可以作为时钟源头;
-
HSE:外部晶振,一般也是 8MHz,需要芯片引脚连接接晶振电路,在芯片外面,可以作为时钟源头;
-
PLL:倍频器,放大频率(Hz),比如 HSE ×9 → 72MHz,芯片内部电路,可以人为配置;
-
PRE: 分频器,将某个频率源挑选过滤(除法),降低频率(Hz),芯片内部电路,可以人为配置;
-
System Clock(SYSCLK):真正驱动 MCU 运行的主时钟;
system_stm32f10x.c 内配置,大约在110行代码处,或者自定义系统时钟初始化函数。
#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
/* #define SYSCLK_FREQ_HSE HSE_VALUE */
#define SYSCLK_FREQ_24MHz 24000000
#else
/* #define SYSCLK_FREQ_HSE HSE_VALUE */
/* #define SYSCLK_FREQ_24MHz 24000000 */
/* #define SYSCLK_FREQ_36MHz 36000000 */
/* #define SYSCLK_FREQ_48MHz 48000000 */
/* #define SYSCLK_FREQ_56MHz 56000000 */
#define SYSCLK_FREQ_72MHz 72000000
#endif
BUS总线:许多电线,用来传递时钟,数据等信息到各模块,就像人的血管一样,蔓延到手,脚。
中断: 临时打断正在运行的程序,运行完中断函数,返回打断的位置继续运行。就像你在开黑打游戏,你妈突然叫你去洗碗,洗完继续开黑。中断可以嵌套,比如洗碗的时候,你爷爷叫你帮他开电视,开完电视继续洗碗。----------中断函数是有限个的,已经被声明了,你要做的只是填充中断函数里内容。
startup_stm32f10x_hd.s 文件里有全部中断函数名,以XXXX_IRQHandler 固定命名形式,一般在stm32f10x_it.c 里编辑,或者写到编译器找得到的自定义文件里。
// 串口中断服务函数
void USART_IRQHandler(void)
{
uint8_t ucTemp;
if(USART_GetITStatus(USARTx,USART_IT_RXNE)!=RESET)
{
ucTemp = USART_ReceiveData(USARTx);
USART_SendData(USARTx,ucTemp);
}
}
GPIO:可以读电平/输电平的引脚,是芯片和外界的接口,可以用眼睛看到。
外设: MCU 自带的功能模块,电路在芯片里面,外的意思是指这些模块在 ARM Cortex-M(大脑) 核心外部。
常用外设:
外设 | 通俗功能 |
---|---|
USART | 串口通信,打印调试信息、连接蓝牙 |
SPI | 高速通信,连接 OLED 屏、Flash |
I2C | 简洁通信,读取温湿度传感器 |
ADC | 模拟→数字,读取电压、传感器信号 |
DAC | 数字→模拟,比如音频输出 |
PWM(定时器) | 控制舵机、电机转速、LED 亮度,实质控制平均电压大小 |
RTC | 内置时钟模块 |
DMA | 数据高速搬运,绕过CPU,直达快车 |
Time | 精确定时器,指定一些定时操作,就像闹钟提醒干活 |
看门狗 | 异常死机,自动重启机制 |
2.5 C语言基础
为了能基本看懂代码,只需要了解常见的C语言语法即可,寄存器什么的看看就行,因为标准库已经把操作寄存器的函数都准备好了,直接用就好。下面的语法需要注意,如果不理解,请参考结尾章节使用AI学习:
语法 | 通俗简介 | 示例 |
---|---|---|
变量定义 | 给数据起个名字,用来存值 | int a = 5; |
函数定义与调用,声明 | 定义一个动作/功能,方便重复使用 | void LED_On(void) { GPIO_SetBits(GPIOA, GPIO_Pin_0); } |
条件判断 | 根据不同条件执行不同的代码块 | if (a > 0) { do_something(); } else { do_other(); } |
循环语句 | 重复执行一段代码 | for(int i=0; i<10; i++) { LED_Toggle(); } |
数组 | 一组相同类型的变量,按顺序排列 | int arr[5] = {1,2,3,4,5}; |
指针 | 存储变量地址的变量,可用于间接访问或传递大数据 | int *p = &a; *p = 10; |
结构体 | 将多个变量打包成一个整体 | GPIO_InitTypeDef GPIO_InitStructure; |
宏定义 | 类似替换文本的快捷方式,常用于命名常量或简化代码 | #define LED_PIN GPIO_Pin_0 |
头文件引用 | 导入需要使用函数/定义/结构体等 | #include "stm32f10x_gpio.h" |
强制类型转换 | 把一种数据类型“临时伪装”成另一种类型 | (uint32_t)0x40010800 |
结构体指针访问 | 通过指针访问结构体成员,用于控制外设 | USART1->SR & USART_FLAG_TXE |
在项目里,我们经常创建的文件就是 .c 和 .h两种文件,它俩可以看成一对:
📌 .h
就像“菜单目录”,告诉别人有哪些菜(功能)可以用;
📌 .c
就是“厨房操作”,是真正做菜的地方(实现细节)!
文件类型 | 通俗解释 | 主要内容 |
---|---|---|
.h 文件 | 说明书 / 接口定义文件 | 函数声明、宏定义、结构体、引脚名等 |
.c 文件 | 功能实现 / 实际代码逻辑 | 函数的具体实现、变量定义、底层操作等 |
led.h
#ifndef __LED_H
#define __LED_H
// 宏定义:定义引脚/端口
#define LED_PORT GPIOA
#define LED_PIN GPIO_Pin_0
// 函数声明:告诉使用者有哪些函数可以使用,这些函数必须在 led.c 里实现
void LED_Init(void);
void LED_On(void);
void LED_Off(void);
#endif
led.c
#include "led.h" // 包含头文件
void LED_Init(void) {
// 配置 GPIO 引脚
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStruct.GPIO_Pin = LED_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LED_PORT, &GPIO_InitStruct);
}
void LED_On(void) {
GPIO_ResetBits(LED_PORT, LED_PIN);
}
void LED_Off(void) {
GPIO_SetBits(LED_PORT, LED_PIN);
}
为了防止重复包含错误,我们会定义一个常量避免重复定义:
#ifndef __LED_H
#define __LED_H
//代码
#endif
2.6 常用 Keil5 面板功能
常用快捷键:
快捷键 | 功能说明 |
---|---|
Ctrl + F7 | 编译整个项目 |
Ctrl + S | 保存当前文件 |
Ctrl + F | 查找关键字 |
右键+Go To xxxx | 跳转查看某变量,函数源码 |
Ctrl + 滚轮 | 字体放大,缩小 |
编译:,每次改动代码需要下载调试之前,必须编译
新建/打开/保存 :
程序下载到芯片:,需要使用Keil5能识别的烧录器
项目配置: ,魔术棒,主要选芯片型号,输出文件,.h 文件路径配置,下载器配置(可选)
选芯片:
输出文件:
C语言配置:
下载器配置:
常见下载方式:
下载方式 | 接口类型 | 是否需要 BootLoader | 常用工具 | 特点说明 |
---|---|---|---|---|
JTAG/SWD | 调试接口 | ❌ 不需要 | ST-Link Utility、Keil | ✅最常用方式,支持下载+调试,速度快,可靠性高 |
串口下载(USART) | 串口(如 PA9/PA10) | ✅ 需要芯片内置 BootLoader | FlyMcu .bin文件 | ✅适合没有调试器时使用,需设置Boot0=1, Boot1=0 |
仿真器下载 | J-Link、ST-Link | ❌ | Keil、J-Flash 等 | 商业版仿真器功能强大,支持更多芯片 |
2.7 观察项目文件结构
大部分标准库项目都与上面相似,USER下的可以自定义修改文件内容,其他文件夹里的stm32fxxx_xxx形式的文件(标准库源文件)最好不要动,需要的时候打开看就行。什么时候看,看什么?需要使用STM32资源时直接调用标准库内置函数,看函数参数,功能注释,结构体内容,常量。
上图的每个文件都代表 STM32 的一个外设或功能集合,例如需要使用 SPI外设连接一个 LCD 屏幕。你先做的是根据 STM32 参考手册找到有哪几个 SPI,选择一个合适的 SPI。查找它复用的是哪些引脚,按照引脚功能用杜邦线看引脚名称连接好 LCD 屏幕,然后查看SPI需要的引脚特性准备写代码。比如我们使用 SPI1 :
SPI 引脚功能 | 对应引脚 | 方向 | 推荐 GPIO 模式 | 说明 |
---|---|---|---|---|
SCK | PA5 | 输出 | 复用推挽输出(AF_PP) | SPI 时钟线,主机输出 |
MISO | PA6 | 输入 | 浮空输入(IN_FLOATING) | 主机输入,从机输出的数据线 |
MOSI | PA7 | 输出 | 复用推挽输出(AF_PP) | 主机输出,从机输入的数据线 |
NSS | PA4(可选) | 输出/输入 | 推挽输出 / 浮空输入 | 可选:软件控制片选,或硬件控制时配置为输入 |
2.8 编写代码
创建自定义 .c 和 .h 文件,项目里引入 .c。配置号魔术棒里的 C/C++ 选项卡 Include Paths选项添加 .h 文件父文件夹,目的是让编译器找到这个文件。(文件夹已经添加过的,可以不再配置)
初始化代码按照以下顺序编写:
步骤 | 内容 | 说明 |
---|---|---|
① | 开启外设时钟 stm32f10x_rcc.h | RCC_APB2PeriphClockCmd() ,外设没时钟就无法工作 |
② | 配置 GPIO 引脚模式 stm32f10x_gpio.h | 设置为复用推挽输出、浮空输入等模式 |
③ | 编写外设初始化结构体参数 stm32f10x_spi.h | 设置外设的工作模式(主/从、时序等) |
④ | 调用初始化函数 | 初始化外设寄存器,完成配置 |
⑤ | 使能外设 | 启动外设,准备通信 |
⑥ | 编写发送/接收函数(或使用中断/DMA)stm32f10x_exti.h | 根据需求使用轮询、中断或 DMA(可选) |
SPI相关的内置函数直接可以看 stm32f10x_spi.h 底部函数声明:
/** @defgroup SPI_Exported_Functions
* @{
*/
void SPI_I2S_DeInit(SPI_TypeDef* SPIx);
void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct);
void I2S_Init(SPI_TypeDef* SPIx, I2S_InitTypeDef* I2S_InitStruct);
void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct);
void I2S_StructInit(I2S_InitTypeDef* I2S_InitStruct);
void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);
void I2S_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState);
void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT, FunctionalState NewState);
void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState);
void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data);
uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx);
void SPI_NSSInternalSoftwareConfig(SPI_TypeDef* SPIx, uint16_t SPI_NSSInternalSoft);
void SPI_SSOutputCmd(SPI_TypeDef* SPIx, FunctionalState NewState);
void SPI_DataSizeConfig(SPI_TypeDef* SPIx, uint16_t SPI_DataSize);
void SPI_TransmitCRC(SPI_TypeDef* SPIx);
void SPI_CalculateCRC(SPI_TypeDef* SPIx, FunctionalState NewState);
uint16_t SPI_GetCRC(SPI_TypeDef* SPIx, uint8_t SPI_CRC);
uint16_t SPI_GetCRCPolynomial(SPI_TypeDef* SPIx);
void SPI_BiDirectionalLineConfig(SPI_TypeDef* SPIx, uint16_t SPI_Direction);
FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);
void SPI_I2S_ClearFlag(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);
ITStatus SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);
void SPI_I2S_ClearITPendingBit(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);
要看具体信息可以右键+GoTo跳转到 stm32f10x_spi.c 的实现位置:
/** @defgroup SPI_Private_Functions
* @{
*/
/**
* @brief Deinitializes the SPIx peripheral registers to their default
* reset values (Affects also the I2Ss).
* @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral.
* @retval None
*/
void SPI_I2S_DeInit(SPI_TypeDef* SPIx)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
if (SPIx == SPI1)
{
/* Enable SPI1 reset state */
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, ENABLE);
/* Release SPI1 from reset state */
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, DISABLE);
}
else if (SPIx == SPI2)
{
/* Enable SPI2 reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, ENABLE);
/* Release SPI2 from reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, DISABLE);
}
else
{
if (SPIx == SPI3)
{
/* Enable SPI3 reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, ENABLE);
/* Release SPI3 from reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, DISABLE);
}
}
}
看不懂的,直接AI生成(配置代码非常成熟,但需要根据需求微调):我现在需要使用 STM32F103C8T6 的 SPI1 与一个 LCD 通信,帮我编写C语言,Keil5, 标准库初始化代码。
#include "stm32f10x.h"
void SPI1_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
// 开启 GPIOA 和 SPI1 的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE);
// 配置 SCK (PA5) 和 MOSI (PA7) 为复用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置 MISO (PA6) 为浮空输入(可选,LCD 一般不用返回数据)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// SPI1 配置:主机模式,8位数据,低电平空闲,1边沿采样
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // 全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; // 主模式
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // 8位数据
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // 空闲时低电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // 第一个时钟沿采样
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // 软件管理 NSS
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; // 分频系数,调整通信速度
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // 高位先传
SPI_InitStructure.SPI_CRCPolynomial = 7; // CRC 多项式,默认即可
SPI_Init(SPI1, &SPI_InitStructure);
// 使能 SPI1
SPI_Cmd(SPI1, ENABLE);
}
void SPI1_SendByte(uint8_t byte) {
// 等待发送缓冲区空
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
// 发送数据
SPI_I2S_SendData(SPI1, byte);
// 等待接收完成(也可省略)
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
// 读取接收缓冲(清除标志位)
(void)SPI_I2S_ReceiveData(SPI1);
}
2.9 驱动文件(让模块运行起来)
上一节的代码仅仅是初始化了 SPI 通信接口,这相当于只打通了和 LCD 通话的“电话线”。但 LCD 本身是一个复杂的显示模块,它内部有专用的驱动芯片,需要我们通过 SPI 发送一系列“特殊指令”来配置它,比如颜色格式、背景色、刷新方式、显示区域、睡眠模式等等。
这些配置过程通常非常复杂,但你不用从零开始写。这些初始化代码早就有人帮你写好了! 通常会打包成一对文件,例如:LCD.c, LCD.h 。哪里找这些文件呢?电商客服!!!直接找你的卖家,问他要,没有就找它的同行,这些文件一般在例程项目文件夹里,名字非常显眼。
文件准备好,就把它们当作新文件引入到项目了。然后直接复制粘贴里面的内容喂给AI,让他帮你解释,并更具自己的要求进行调整。你要在LCD实现什么功能,请直接使用LCD.h 声明的函数,不够的可以自定义。其底层逻辑就是(其他通信协议类似):用 SPI 发送特定格式的数据(通常来自 LCD 控制芯片的手册),间接控制 LCD 内部寄存器。不同寄存器决定 LCD 的不同行为,最后在屏幕上呈现出不同的效果。
2.10 编译报错怎么办?
请将看不懂的错误直接发送给AI,他会帮你分析原因。但要注意不要被AI带偏,最好的编写习惯是,代码有些改动时,尽早编译,这样你可以提供更多的信息给AI。比如,我在xxx地方添加了xxx代码之后编译xxxx报错。
2.11 编译通过 0 错误,下载芯片后没有预期反应?
问题类型 | 描述 |
---|---|
🧠 程序逻辑错误 | 死循环、分支跳转逻辑混乱,程序卡住或走错分支导致无输出 |
🔁 无限阻塞 | 比如等待某个外设就绪,结果它永远没准备好,程序卡死在 while 里 |
🧹 内存操作错误 | 指针未初始化、数组越界、内存越界写入等,容易引起死机或奇怪行为 |
⚙️ 初始化错误 | 外设参数设置错了(如 SPI 时序、GPIO 模式配置错误),导致功能无响应 |
🔌 硬件接线问题 | 电源、引脚未接好、LCD 或传感器没接上/接错,程序正常但看不到任何效果 |
🔍 输出未调试 | 程序正常跑,但你没设置串口输出/LED 反馈,看不出运行状态,误以为出错了 |
2.12 调试必备程序
功能 | 用处 |
---|---|
Delay_ms | 模拟等待,常用于初始化等待 |
LED_Blink | 判断程序是否运行,调试必备 |
USART + printf | 串口输出信息,实时调试变量和状态 |
3. 如何使用浏览器与生成式AI解决你的STM32开发问题?
对于浏览器和AI两种工具,我的观点:
浏览器搜索提供了广泛的信息来源,适用于探索性学习或需要多角度理解问题,获取最新数据、新闻、论坛和技术文档。但需要花时间筛选和辨别信息的相关性和可靠性,可能会遇到信息过载的情况。通常问题字数较少且会加上一些关键词(怎样xxx,xxx如何xxx,xxx怎么使用,什么是xxxx,为什么xxx,xxx会xxx......)。例如STM32如何下载程序,毕业设计弄不出来会延毕吗等,xxx传感器如何使用。
AI是一种"浓缩版浏览器",它会将你的问题(前提是你的问题非常明确,字数挺多)不断精细化,使用某个专业领域的内容回答你,适合解决具体、明确的问题。它可以节省时间,提高效率,但也可能存在信息滞后或不准确的情况,尤其是在处理需要深入理解或创造性思维的问题。一般使用AI解决一些范围较小的问题,例如帮我规划xxx项目进度,如何解决C语言xxx报错,给我一个USART窗口调试程序,告诉我xxx代码功能,告诉我xxx函数如何使用。噢,对了,请在你提供的信息后面加上一段分隔符(-。.=),然后把要求写下来。例如xxxBUG(1000字符)------------------C语言报错,帮我解决;xxxxxx.............................以上是我提供的方案,请给我一些建议。
每当你有一个问题,你最先做的应当是将问题分解并描述清晰。请记住以下问题表达建议,这其实是一个我经常使用的AI小公式,每次使用它都会加快我找到答案的速度,找不到的话只能自己减少关键词去浏览器搜索,或着问人:
发生时间(可选) + 问题场景 + 错误现象(可选) + 预期结果 + 已尝试的解决方法(可选) + 限制条件(可选)+指令
以下是一个示例:
-
(AI版)我是电子与信息专业的学生,我不知道如何开始我的毕设:基于单片机的个人健康助手的设计。目前我只准备好了一块STM32开发板,xxx型号心率传感器,xxx型号温度传感器,xxx型号重力传感器(问题场景)。我的系统需要完成这些功能:1.该设备需要放置在人的手臂上,需要接触皮肤 2.传感器数据需要通过数据线发送到电脑上显示 3.摔倒警报提示 4.心率,温度参数异常警报提升(预期结果)。老师要求我使用C语言和标准库编写程序(限制条件)。------------------------请根据我的情况帮我规划行动(指令)
-
(浏览器版)基于单片机的个人健康助手
4. 总结
本文简单介绍了STM32单片机开发流程,Keil5基本使用方式,源码编写方式,常见问题解决方式,最后介绍了如何使用AI,浏览器解决开发中的任何问题。
感谢阅览,如果你喜欢该内容的话,可以点赞,收藏,转发。
由于 Koro 能力有限,有任何问题请在评论区内提出,Koro 看到后第一时间回复您!!!
其他精彩内容:
⛏正在赶稿中....