STM32 零基础可移植教程 08:串口接收一个字节,先把 RX 中断跑通

STM32 零基础可移植教程 08:串口接收一个字节,先把 RX 中断跑通

上一篇我们把 USART 串口打印跑通了。

板子已经能通过 printf() 往电脑发信息,这一步非常重要。以后 ADC 采样值、I2C 错误码、CAN 状态、程序运行位置,都可以通过串口打印出来。

但串口不应该只会"说话"。

很多时候,我们还希望电脑能给 STM32 发命令。

比如:

  • 发一个字符,让 LED 翻转;

  • 发一条命令,让蜂鸣器响一下;

  • 发一个参数,修改 PWM 占空比;

  • 发一行文本,做一个简单的调试控制台。

这些功能的第一步,不是直接写命令解析,而是先把最小接收链路跑通。

这一篇只做一个明确目标:

bash 复制代码
电脑通过串口发送 1 个字节,STM32 用 RX 中断接收,然后把这个字节打印回来

先别急着收一整行,也先别上 DMA。先让一个字节稳定进来。

本篇目标

最终现象:

bash 复制代码
串口助手发送:A


STM32 返回:

RX: A, hex: 0x41

如果发送:

bash 复制代码
1

STM32 返回:

bash 复制代码
RX: 1, hex: 0x31

本篇用到的外设:

bash 复制代码
USART

USART interrupt

GPIO Alternate Function

NVIC

本篇跑通标准:

  • Keil 编译通过;

  • 程序能下载到开发板;

  • 串口助手能看到启动打印;

  • 串口助手发送 1 个字符后,STM32 能回显这个字符;

  • 能说清楚为什么要先调用 HAL_UART_Receive_IT()

  • 能说清楚为什么回调函数里要重新开启下一次接收;

  • 能说清楚中断里为什么不建议直接写一堆业务逻辑。

本篇只讲单字节中断接收。

不讲一行命令,不讲环形缓冲,不讲 DMA,不讲 IDLE。这些都很重要,但放到后面一篇一篇拆。

准备工作

你需要准备:

|

项目

|

说明

|

| --- | --- |

|

STM32 开发板

|

任意 STM32 开发板都可以

|

|

下载器

|

ST-LINK/V2 或板载 ST-LINK

|

|

USB 转 TTL 模块

|

如果开发板没有板载 USB 串口,需要外接

|

|

串口助手

|

支持发送单个字符即可

|

|

原理图

|

确认 USART TX/RX 接到哪个引脚

|

|

上一篇 USART 工程

|

建议直接从第 07 篇复制

|

建议从上一篇工程复制一份,改名为:

bash 复制代码
08_usart_rx_interrupt

因为上一篇已经完成了:

  • USART 基本配置;

  • 串口接线;

  • printf() 重定向;

  • 串口助手参数设置。

这一篇在它的基础上加 RX 中断,思路最清楚。

硬件连接

串口接收必须把 RX 也接上。

连接关系仍然是交叉连接:

|

STM32

|

USB 转 TTL

|

| --- | --- |

|

USART_TX

|

RXD

|

|

USART_RX

|

TXD

|

|

GND

|

GND

|

这三个点一个都别省。

上一篇只做打印时,理论上只接 STM32 TX 到 USB-TTL RX 也能看到输出。

但这一篇要让电脑发数据给 STM32,所以必须接:

bash 复制代码
USB-TTL TXD -> STM32 USART_RX

也就是电脑这边发出来的数据,要进 STM32 的 RX 引脚。

再强调一次:

bash 复制代码
GND 必须共地

如果 GND 没接,串口可能完全没反应,也可能偶尔能收到一些奇怪字符。这种问题最容易把新手带偏。

先理解 RX 中断流程

很多新手第一次写串口接收中断,会以为只要在 CubeMX 里勾选中断就行。

结果程序下载后,电脑发什么都没反应。

这里有一个关键点:

bash 复制代码
打开 USART 中断,不等于已经开始接收

你还要在代码里主动调用一次:

bash 复制代码
HAL_UART_Receive_IT(&huart1, &rx_byte, 
1
);

它的意思是:

bash 复制代码
从现在开始,帮我用中断方式接收 1 个字节

等 1 个字节真的收到了,HAL 会走到回调函数:

bash 复制代码
HAL_UART_RxCpltCallback()

注意,这里还有第二个坑:

bash 复制代码
HAL_UART_Receive_IT() 接收一次,就只管这一次

如果你只调用一次,STM32 收到第一个字节后,后面的字节就不一定继续收了。

所以我们要在接收完成回调里重新开启下一次接收:

bash 复制代码
HAL_UART_Receive_IT(&huart1, &rx_byte, 
1
);

本篇的流程可以理解成:

bash 复制代码
初始化 USART

  -> 开启一次中断接收

  -> 电脑发送 1 个字节

  -> USART 触发中断

  -> HAL_UART_IRQHandler()

  -> HAL_UART_RxCpltCallback()

  -> 记录收到的数据

  -> 重新开启下一次接收

  -> main while 里读取数据并打印

为什么不直接在中断回调里 printf()

因为中断里应该尽量少做事。

这一篇我们采用一个更稳的习惯:

bash 复制代码
中断里只记录事件

主循环里处理业务

这个习惯后面写按键中断、定时器中断、DMA 回调都会用到。

CubeMX 配置步骤

1. 保留上一篇 USART 基本配置

先确认 USART 仍然配置为:

bash 复制代码
Mode: Asynchronous

Baud Rate: 115200

Word Length: 8 Bits

Parity: None

Stop Bits: 1

Hardware Flow Control: None

也就是常说的:

bash 复制代码
115200, 8N1

串口助手也要保持一样。

如果你用的是 USART1,常见引脚是:

bash 复制代码
PA9  -> USART1_TX

PA10 -> USART1_RX

如果你用的是 USART2,常见引脚可能是:

bash 复制代码
PA2 -> USART2_TX

PA3 -> USART2_RX

不要死记这个引脚。

真正要看的还是开发板原理图和 CubeMX 里的 Pinout。

2. 打开 USART 中断

进入:

bash 复制代码
Connectivity -> USARTx -> NVIC Settings

勾选:

bash 复制代码
USARTx global interrupt

如果是 USART1,就是:

bash 复制代码
USART1 global interrupt

如果是 USART2,就是:

bash 复制代码
USART2 global interrupt

为什么要勾这个?

因为串口收到数据后,需要通过中断进入 HAL 的串口中断处理函数。

如果这里没打开,HAL_UART_Receive_IT() 虽然调用了,但收到字节后不会正常进回调。

3. 生成 Keil 工程

点击:

bash 复制代码
GENERATE CODE

然后打开 Keil。

如果 CubeMX 提示要覆盖生成代码,确认你自己的代码都写在 USER CODE 区域里,再生成。

Keil 工程生成和编译

打开 Keil 后,先编译一次:

bash 复制代码
Build / F7

确认输出:

bash 复制代码
0 Error(s)

然后打开 CubeMX 生成的中断文件。

STM32F1 常见是:

bash 复制代码
Core/Src/stm32f1xx_it.c

其他系列可能是:

bash 复制代码
Core/Src/stm32f4xx_it.c

Core/Src/stm32g0xx_it.c

Core/Src/stm32h7xx_it.c

找到 USART 的中断函数,例如 USART1:

bash 复制代码
void USART1_IRQHandler(void)
{

  
/* USER CODE BEGIN USART1_IRQn 0 */


  
/* USER CODE END USART1_IRQn 0 */

  HAL_UART_IRQHandler(&huart1);

  
/* USER CODE BEGIN USART1_IRQn 1 */


  
/* USER CODE END USART1_IRQn 1 */

}

这里最关键的是:

bash 复制代码
HAL_UART_IRQHandler(&huart1);

它会帮你处理 HAL 内部状态,最后在接收完成时调用:

bash 复制代码
HAL_UART_RxCpltCallback()

如果你的中断函数里没有 HAL_UART_IRQHandler(),那后面的回调就不会正常发生。

一般 CubeMX 会自动生成,不需要你手写。

完整代码

这一篇继续使用应用层封装。

新建或覆盖这两个文件:

bash 复制代码
Core/Inc/app_uart.h

Core/Src/app_uart.c

如果你从上一篇复制工程,可以直接在上一篇 app_uart 的基础上增加接收相关函数。

1. Core/Inc/app_uart.h

Core/Inc 目录下新建:

bash 复制代码
app_uart.h

写入:

bash 复制代码
#ifndef APP_UART_H

#define APP_UART_H


#include "main.h"

#include <stdint.h>


void App_UART_Init(void)
;

void App_UART_Print(const char *text)
;

void App_UART_PrintBytes(const uint8_t *data, uint16_t len)
;

HAL_StatusTypeDef App_UART_StartReceiveIT(void)
;

void App_UART_OnRxCplt(UART_HandleTypeDef *huart)
;

uint8_t App_UART_ReadByte(uint8_t *data)
;


#endif

这里新增了 3 个函数:

|

函数

|

作用

|

| --- | --- |

| App_UART_StartReceiveIT() |

开启第一次中断接收

|

| App_UART_OnRxCplt() |

给 HAL 回调调用,记录收到的数据

|

| App_UART_ReadByte() |

主循环读取是否收到新字节

|

2. Core/Src/app_uart.c

Core/Src 目录下新建:

bash 复制代码
app_uart.c

写入:

bash 复制代码
#include "app_uart.h"

#include <stdio.h>

#include <string.h>


/* * Default USART handle is huart1. * If your project uses USART2, define APP_UART_HANDLE as huart2. */

#ifndef APP_UART_HANDLE

#define APP_UART_HANDLE huart1

#endif


extern
 UART_HandleTypeDef APP_UART_HANDLE;


static
uint8_t
 s_rx_it_byte = 
0
;

static
uint8_t
 s_rx_data = 
0
;

static
volatile
uint8_t
 s_rx_ready = 
0
;


void App_UART_Init(void)
{

    s_rx_it_byte = 
0
;

    s_rx_data = 
0
;

    s_rx_ready = 
0
;

}


void App_UART_Print(const char *text)
{

    
if
 (text == 
NULL
)

    {

        
return
;

    }


    HAL_UART_Transmit(&APP_UART_HANDLE,

                      (
uint8_t
 *)text,

                      (
uint16_t
)
strlen
(text),

                      HAL_MAX_DELAY);

}


void App_UART_PrintBytes(const uint8_t *data, uint16_t len)
{

    
if
 ((data == 
NULL
) || (len == 
0u
))

    {

        
return
;

    }


    HAL_UART_Transmit(&APP_UART_HANDLE,

                      (
uint8_t
 *)data,

                      len,

                      HAL_MAX_DELAY);

}


HAL_StatusTypeDef App_UART_StartReceiveIT(void)
{

    
return
 HAL_UART_Receive_IT(&APP_UART_HANDLE, &s_rx_it_byte, 
1u
);

}


void App_UART_OnRxCplt(UART_HandleTypeDef *huart)
{

    
if
 (huart == 
NULL
)

    {

        
return
;

    }


    
if
 (huart->Instance != APP_UART_HANDLE.Instance)

    {

        
return
;

    }


    s_rx_data = s_rx_it_byte;

    s_rx_ready = 
1u
;


    (
void
)HAL_UART_Receive_IT(&APP_UART_HANDLE, &s_rx_it_byte, 
1u
);

}


uint8_t App_UART_ReadByte(uint8_t *data)
{

    
if
 (data == 
NULL
)

    {

        
return
0u
;

    }


    
if
 (s_rx_ready == 
0u
)

    {

        
return
0u
;

    }


    __disable_irq();

    *data = s_rx_data;

    s_rx_ready = 
0u
;

    __enable_irq();


    
return
1u
;

}


int fputc(int ch, FILE *f)
{

    
uint8_t
 data = (
uint8_t
)ch;


    HAL_UART_Transmit(&APP_UART_HANDLE, &data, 
1u
, HAL_MAX_DELAY);


    
return
 ch;

}

这里有几个点要看懂。

第一,默认串口句柄是:

bash 复制代码
#define APP_UART_HANDLE huart1

如果你的工程用的是 USART2,就改成:

bash 复制代码
#define APP_UART_HANDLE huart2

第二,真正交给 HAL 接收的是这个变量:

bash 复制代码
static
 
uint8_t
 s_rx_it_byte = 
0
;

收到一个字节后,我们把它复制到:

bash 复制代码
static
 
uint8_t
 s_rx_data = 
0
;

然后把标志位置 1:

bash 复制代码
s_rx_ready = 
1u
;

主循环通过 App_UART_ReadByte() 读取这个标志。

第三,回调里重新开启下一次接收:

bash 复制代码
(
void
)HAL_UART_Receive_IT(&APP_UART_HANDLE, &s_rx_it_byte, 
1u
);

这行非常重要。

少了它,常见现象是:

bash 复制代码
只收到第一个字节,后面再发就没反应

3. 把 app_uart.c 加入 Keil 工程

如果你手动新建 .c 文件,Keil 不一定会自动编译它。

在 Keil 工程树里右键:

bash 复制代码
Application/User/Core

选择:

bash 复制代码
Add Existing Files to Group 'Application/User/Core'

然后添加:

bash 复制代码
Core/Src/app_uart.c

如果忘了这一步,可能会报:

bash 复制代码
undefined symbol App_UART_StartReceiveIT

undefined symbol App_UART_ReadByte

这不是函数写错了,而是 .c 文件没参与编译。

main.c 调用方式

下面开始改 main.c

老规矩:尽量写在 USER CODE 区域里。

1. Includes 区域

找到:

bash 复制代码
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

改成:

bash 复制代码
/* USER CODE BEGIN Includes */

#include "app_uart.h"

#include <stdio.h>

/* USER CODE END Includes */

<stdio.h> 是给 printf() 用的。

2. 初始化区域

main() 里先确认 CubeMX 生成的初始化顺序。

你应该能看到类似:

bash 复制代码
MX_GPIO_Init();

MX_USART1_UART_Init();

如果你用的是 USART2,就是:

bash 复制代码
MX_USART2_UART_Init();

然后在:

bash 复制代码
/* USER CODE BEGIN 2 */

/* USER CODE END 2 */

里面添加:

bash 复制代码
/* USER CODE BEGIN 2 */

App_UART_Init();

App_UART_StartReceiveIT();

printf
(
"USART RX interrupt test start\r\n"
);

/* USER CODE END 2 */

顺序不要反。

必须先执行:

bash 复制代码
MX_USART1_UART_Init();

再执行:

bash 复制代码
App_UART_StartReceiveIT();

因为 USART 外设和句柄要先初始化好,后面才能开启中断接收。

3. while 循环区域

找到:

bash 复制代码
while
 (
1
)

{

  
/* USER CODE END WHILE */


  
/* USER CODE BEGIN 3 */

  
/* USER CODE END 3 */

}

改成:

bash 复制代码
while
 (
1
)

{

/* USER CODE END WHILE */


/* USER CODE BEGIN 3 */

uint8_t
 rx_data = 
0
;


if
 (App_UART_ReadByte(&rx_data) != 
0u
)

  {

    
printf
(
"RX: %c, hex: 0x%02X\r\n"
, rx_data, rx_data);

  }


  HAL_Delay(
10
);

/* USER CODE END 3 */

}

这段代码的意思是:

bash 复制代码
主循环不断检查有没有收到新字节

如果收到了,就打印字符和十六进制值

比如收到字符 A

bash 复制代码
字符显示:A

十六进制:0x41

为什么还要打印十六进制?

因为有些字符看不见,比如回车、换行、空格。

只打印 %c 时,你可能看不出来到底收到的是啥;打印 0x%02X 更适合排查。

4. 添加 HAL 接收完成回调

找到 main.c 下面的:

bash 复制代码
/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

在里面添加:

bash 复制代码
/* USER CODE BEGIN 4 */

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{

  App_UART_OnRxCplt(huart);

}

/* USER CODE END 4 */

注意:如果你的工程里已经有 HAL_UART_RxCpltCallback(),不要再写第二个同名函数。

你要把这句合并进去:

bash 复制代码
App_UART_OnRxCplt(huart);

C 语言里同一个函数不能定义两次。

编译、下载和验证

代码加完后,先编译:

bash 复制代码
Build / F7

确认:

bash 复制代码
0 Error(s)

然后下载程序。

打开串口助手,参数保持:

bash 复制代码
115200, 8N1

复位开发板后,先看启动信息:

bash 复制代码
USART RX interrupt test start

然后在串口助手发送区输入:

bash 复制代码
A

点击发送。

正常情况下,接收区会显示:

bash 复制代码
RX: A, hex: 0x41

再发:

bash 复制代码
B

应该显示:

bash 复制代码
RX: B, hex: 0x42

如果你发送的是中文,这篇先不建议这么测。

中文通常是多个字节,而且还涉及编码问题。我们现在只验证单字节接收,先用英文、数字、符号。

移植到其他板子的修改点

这篇的移植点主要有 8 个。

|

要改的地方

|

为什么要改

|

在哪里改

|

| --- | --- | --- |

|

USART 实例

|

板载 USB 串口可能接 USART1/2/3

|

CubeMX Connectivity

|

|

TX/RX 引脚

|

不同芯片复用引脚不同

|

CubeMX Pinout 和原理图

|

|

USART global interrupt

|

中断接收必须打开 NVIC

|

CubeMX USART NVIC Settings

|

|

串口句柄

| huart1

huart2huart3 不同

| app_uart.c

APP_UART_HANDLE

|

|

IRQHandler

|

不同 USART 对应不同中断函数

| stm32xx_it.c |

|

波特率

|

两端必须一致

|

CubeMX 和串口助手

|

|

接线

|

RX 必须接 USB-TTL TX

|

硬件连接

|

|

回调合并

|

工程里可能已有 HAL 回调

| main.c

USER CODE BEGIN 4

|

换板子的推荐顺序:

  1. 看原理图,确认电脑串口接到哪个 USART;

  2. CubeMX 里配置对应 USART 为 Asynchronous

  3. 设置 115200、8N1;

  4. 打开对应 USART 的 global interrupt;

  5. 生成代码后确认 stm32xx_it.c 里有 HAL_UART_IRQHandler(&huartx)

  6. app_uart.c 里把 APP_UART_HANDLE 改成实际句柄;

  7. main.c 初始化后调用 App_UART_StartReceiveIT()

  8. HAL_UART_RxCpltCallback() 里调用 App_UART_OnRxCplt(huart)

  9. 串口助手发单个英文字符验证。

常见问题排查

在这里我先来回答一个大家问得比较多的问题,为什么一遇到串口相关的项目,Keil中就必须要勾选 use MicroLIB呢?

这是 Keil MDK 中 MicroLIB 与标准 C 库的 printf 底层实现路径不同 导致的。 MicroLIB 是 ARM 专门为嵌入式 MCU 裁剪的轻量库。它的 printf 实现非常精简:

bash 复制代码
  printf → 格式化字符串 → 逐字符调用 fputc → UART 发送

你只需要实现 fputc,printf 就直接输出到了串口。

而标准 C 库 的 printf 走的是完整 POSIX 风格的 I/O 层:

bash 复制代码
  printf → fprintf(stdout) → _write(fd=1) → 需要实现更多 syscall

你在 app_uart.c 里写的 fputc 虽然也被编译进去,但标准库的 printf 并不直接依赖它 -- 它走的是 _write 系统调用。

所以你的 fputc 压根没被 printf 调用到,数据没有经过 HAL_UART_Transmit,自然串口上看不到任何东西。

所以如果有的小伙伴在写完代码烧录之后发现串口没有任何反应,可以查一下这个问题。

1. 串口能打印启动信息,但发字符没反应

这种情况说明 TX 打印链路是通的,但 RX 接收链路有问题。

优先检查:

|

优先检查

|

具体方法

|

| --- | --- |

|

RX 线有没有接

|

USB-TTL TXD 要接 STM32 RX

|

|

GND 有没有共地

|

STM32 GND 和 USB-TTL GND 必须相连

|

|

CubeMX 是否打开 USART global interrupt

|

USART 的 NVIC Settings 里勾选

|

|

是否调用 App_UART_StartReceiveIT()

|

必须在 USART 初始化后调用

|

|

回调函数是否添加

| HAL_UART_RxCpltCallback()

里调用 App_UART_OnRxCplt()

|

| APP_UART_HANDLE

是否正确

|

USART2 工程不能还写 huart1

|

先不要怀疑电脑,也不要一上来改一堆代码。按这个顺序查,通常很快能定位。

2. 只能收到第一个字符,后面没反应

这是串口中断接收最经典的坑。

原因通常是:

bash 复制代码
收到一个字节后,没有重新开启下一次接收

检查 App_UART_OnRxCplt() 里有没有:

bash 复制代码
(
void
)HAL_UART_Receive_IT(&APP_UART_HANDLE, &s_rx_it_byte, 
1u
);

没有这行,就只能收一次。

3. 编译报 huart1 未定义

说明你的工程里没有 huart1

可能你配置的是 USART2,CubeMX 生成的是:

bash 复制代码
UART_HandleTypeDef huart2;

解决方法:

app_uart.c 里的:

bash 复制代码
#define APP_UART_HANDLE huart1

改成:

bash 复制代码
#define APP_UART_HANDLE huart2

如果用 USART3,就改成 huart3

4. 编译报 undefined symbol App_UART_StartReceiveIT

通常是 app_uart.c 没加入 Keil 工程。

解决方法:

  1. 右键 Application/User/Core

  2. 选择 Add Existing Files to Group

  3. 添加 Core/Src/app_uart.c

  4. 重新编译。

5. 进不了 HAL_UART_RxCpltCallback()

按顺序查这几个地方:

  1. CubeMX 是否打开 USART global interrupt;

  2. stm32xx_it.c 里是否有对应的 USARTx_IRQHandler()

  3. USARTx_IRQHandler() 里是否调用了 HAL_UART_IRQHandler(&huartx)

  4. App_UART_StartReceiveIT() 是否真的被执行;

  5. 串口助手发送方向是否正确,USB-TTL TX 是否接到了 STM32 RX。

如果你会打断点,可以在这些位置打断点:

bash 复制代码
HAL_UART_RxCpltCallback()

App_UART_OnRxCplt()

App_UART_ReadByte()

一个一个看数据有没有走到。

6. 收到的字符和发送的不一样

优先检查:

  • 波特率是否一致;

  • 数据位、停止位、校验位是否一致;

  • 系统时钟是否配置错误;

  • USB 转 TTL 电平是否匹配;

  • GND 是否接触不良;

  • 串口助手是否发送了换行或其他附加字符。

建议先用单个字符测试:

bash 复制代码
A

B

1

2

不要一开始就发中文或一大串命令。

7. 快速连续发送会丢字符

本篇代码只做最小单字节接收演示。

它只有一个简单的接收标志:

bash 复制代码
s_rx_ready

如果电脑连续高速发送很多字节,而主循环处理不及时,后来的字节可能覆盖前面的字节。

这不是 HAL 的错,也不是串口线坏了。

解决这个问题需要:

  • 接收缓冲区;

  • 环形队列;

  • 或者 USART DMA + IDLE。

这些我们后面单独讲。

这篇先把 RX 中断链路跑通。

本篇小结

这一篇我们完成了 USART 单字节中断接收。

你现在至少应该知道:

  • 串口接收必须接好 STM32 RX;

  • USART 中断接收要在 CubeMX 里打开 global interrupt;

  • 打开 NVIC 不代表自动开始接收;

  • 必须先调用 HAL_UART_Receive_IT()

  • 收到 1 个字节后会进入 HAL_UART_RxCpltCallback()

  • 回调里要重新开启下一次接收;

  • 中断里尽量只记录事件,主循环里处理打印和业务;

  • 换 USART1/2/3 时,要同步修改 APP_UART_HANDLE 和检查 IRQHandler。

下一篇我们继续扩展串口接收:

STM32 串口收一行命令:从单字节中断到简单命令解析。

到那一篇,我们会把现在的"收一个字节"扩展成"收一行字符串",让电脑输入:

bash 复制代码
led on

led off

beep

然后 STM32 根据命令去控制 LED 和蜂鸣器。

相关推荐
FreakStudio8 天前
W55MH32L-EVB 上手测评:硬件 TCP/IP 加持的以太网单片机,MicroPython 零门槛开发
python·单片机·嵌入式·大学生·面向对象·并行计算·电子diy·电子计算机
✎ ﹏梦醒͜ღ҉繁华落℘14 天前
单片机基础知识---stm32单片机的优先级
stm32·单片机·mongodb
u1521096484914 天前
S.S.Audio PRO A2音频隔离器
嵌入式硬件·音视频·实时音视频·视频编解码·视频
zd84510150014 天前
RS485 总线详解
单片机·嵌入式硬件
半条-咸鱼14 天前
【STM32】I2C协议原理、HAL读写与OLED显示操作
嵌入式硬件·c·信息与通信
牛根生同志14 天前
SPI数据收发的时候 TXE与RXNE标志位置位的时机
stm32·spi·transfer
wohoo_wangzi14 天前
苏州晟雅泰电子:关于W25Q128JVSIQ这个芯片物料的参数,规格及应用领域
嵌入式硬件
goldenrolan14 天前
学习型红外控制系统稳定性挂测工装专项总结
软件测试·python·stm32·嵌入式·红外
✎ ﹏梦醒͜ღ҉繁华落℘14 天前
编程基础 --高内聚,低耦合
c语言·单片机
科芯创展14 天前
1A,1MHz,30VIN,XZ4115,降压恒流LED驱动芯片
单片机·嵌入式硬件