07:(寄存器开发)串口通信

news2024/11/17 11:01:40

串口通信

  • 1、串口简介
  • 2、串口通讯协议
  • 3、硬件外设
  • 4、发送数据
  • 5、使用轮询的方式接收数据(USART1)
  • 6、使用中断的方式接收数据
  • 7、串口进行printf重定向

1、串口简介

  串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式,因为它简单便捷,因此大部分电子设备都支持该通讯方式,电子工程师在调试设备时也经常使用该通讯方式输出调试信息。

        在这里插入图片描述

2、串口通讯协议

    在这里插入图片描述
1)波特率
  “波特率”(Baudrate),它表示每秒钟传输了多少个码元。在二进制的世界码元和位是等价的。用每秒传输的比特数表示波特率。STM32提供的是串口异步通讯,异步通讯中由于没有时钟信号,所以两个通讯设备之间需要约定好波特率,即每个码元的长度,以便对信号进行解码。常见的波特率为4800、9600、115200等。
2)空闲位
  串口协议规定,当总线处于空闲状态时信号线的状态为‘1’即高电平,表示当前线路上没有数据。
3)通讯的起始位
  每开始一次通信时发送方先发出一个逻辑”0”的信号(低电平),表示传输字符的开始。因为总线空闲时为高电平所以开始一次通信时先发送一个明显区别于空闲状态的信号即低电平。
4)通讯的停止位
  停止信号可由 0.5、1、1.5 或 2个逻辑1的数据位表示,只要双方约定一致即可。
5)有效数据位
  在数据包的起始位之后紧接着的就是要传输的主体数据内容,也称为有效数据,有效数据的长度常被约定为 5、6、7 或8位长。构成一个字符(一般都是8位)。先发送最低位,最后发送最高位,使用低电平表示‘0’高电平表示‘1’完成数据位的传输。
6)校验位
  数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验数据传送的正确性。串口校验分几种方式:
(1)无校验(no parity)。
(2)奇校验(odd parity):如果数据位中“1”的数目是偶数,则校验位为“1”,如果“1”的数目是奇数,校验位为“0”。偶校验(even parity):如果数据为中“1”的数目是偶数,则校验位为“0”,如果为奇数,校验位为“1”。
7) 空闲帧
  通过检测空闲帧来判断数据是否接收完(相当于结束符)。检测到空闲帧也可以触发空闲帧中断

3、硬件外设

stm32的USART中结构框图如下:
在这里插入图片描述
2)波特率的产生
  发送器和接收器的波特率是一致的,都是通过设置BRR寄存器来得到。
          在这里插入图片描述
  这里的是给外设的时钟(usart1在APB2上一般是72MHz,usart2,3,4,5在APB1上一般为36MHz)。

在这里插入图片描述

  假设我们需要的波特率是115200,则对应的分频值应该是:39.0625,把这个值写入到BRR寄存器中。39.0625的小数部分:0.0625 * 16 = 1, 整数部分是:39(0x27)。
在这里插入图片描述

所以写入到BRR寄存器的值是:0x0271。

4、发送数据

在这里插入图片描述

①USATR1.c文件的代码如下:

#include "USART.h"

/*
 *  串口USART1的初始化:接收/发送
 */
void USART1_Init(void)
{
/*1.开启GPIOA的时钟和USART1的时钟*/
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;//开启GPIOA的时钟
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN;//开启USART1的时钟

/*2.配置PA9和PA10引脚的工作模式:PA9(TX)为复用推挽输出,PA10(RX)为浮空输入*/
    GPIOA->CRH |= GPIO_CRH_MODE9;//MODE9 = 11:输出模式Speed = 50MHz
    GPIOA->CRH &= ~GPIO_CRH_CNF9_0;
    GPIOA->CRH |= GPIO_CRH_CNF9_1;//CF9 = 10:复用推挽输出

    GPIOA->CRH &= ~GPIO_CRH_MODE10;//MODE10 = 00:输入模式
    GPIOA->CRH |= GPIO_CRH_CNF10_0;
    GPIOA->CRH &= ~GPIO_CRH_CNF10_1;//CF10 = 01:浮空输入

/*3.串口的参数配置*/
    /*3.1 配置波特率位115200:USART_BRR = 0x271*/
    USART1->BRR = 0x271;

    /*3.2 数据位长度位8位:USART_CR1_M = 0*/
    USART1->CR1 &= ~USART_CR1_M; //CR1控制寄存器中M = 0

    /*3.3 配置不需要校验位*/
    USART1->CR1 &= ~USART_CR1_PCE;//CR1控制寄存器中PCE = 0

    /*3.4 1位停止位*/
    USART1->CR2 &= ~USART_CR2_STOP;//CR2控制寄存器中STOP = 00

    /*3.5 使能接收与发送*/
    USART1->CR1 |= USART_CR1_TE;
    USART1->CR1 |= USART_CR1_RE;

/*4.使能串口*/
    USART1->CR1 |= USART_CR1_UE;
}

/*
 *  发送一个字节
 */
void USART1_SendByte(uint8_t Byte)
{
    /*1.等待数据寄存器是否空,即发送数据寄存器空*/
    while((USART1->SR & USART_SR_TXE) == 0);//表示数据寄存器非空
    USART1->DR = Byte;//写入DR硬件自动置位TXE位
}

/*
 *  发送一个字符串
 */
void USART1_SendString(uint8_t *str, uint16_t Length)
{
    for(uint8_t i = 0; i < Length ;i++)
    {
        USART1_SendByte(str[i]);
    }
}

②主函数文件的代码如下:

#include "stm32f10x.h"                  
#include "USART.h"
#include "Delay.h"
#include "String.h"

uint8_t Array[5] = {'A','B','C','D','E'};
uint8_t *String = "Hello World\r\n";

int main(void)
{
	USART1_Init();
	USART1_SendString(Array, 5);//向上位机发送字符数组Array
	USART1_SendString(String, 14);//向上位机发送字符串String

	while(1)
	{
		
	}
}

在这里插入图片描述

5、使用轮询的方式接收数据(USART1)

①USAR1.c文件的代码如下:

#include "USART.h"

/*
 *  串口USART1的初始化:接收/发送
 */
void USART1_Init(void)
{
/*1.开启GPIOA的时钟和USART1的时钟*/
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;//开启GPIOA的时钟
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN;//开启USART1的时钟

/*2.配置PA9和PA10引脚的工作模式:PA9(TX)为复用推挽输出,PA10(RX)为浮空输入*/
    GPIOA->CRH |= GPIO_CRH_MODE9;//MODE9 = 11:输出模式Speed = 50MHz
    GPIOA->CRH &= ~GPIO_CRH_CNF9_0;
    GPIOA->CRH |= GPIO_CRH_CNF9_1;//CF9 = 10:复用推挽输出

    GPIOA->CRH &= ~GPIO_CRH_MODE10;//MODE10 = 00:输入模式
    GPIOA->CRH |= GPIO_CRH_CNF10_0;
    GPIOA->CRH &= ~GPIO_CRH_CNF10_1;//CF10 = 01:浮空输入

/*3.串口的参数配置*/
    /*3.1 配置波特率位115200:USART_BRR = 0x271*/
    USART1->BRR = 0x271;

    /*3.2 数据位长度位8位:USART_CR1_M = 0*/
    USART1->CR1 &= ~USART_CR1_M; //CR1控制寄存器中M = 0

    /*3.3 配置不需要校验位*/
    USART1->CR1 &= ~USART_CR1_PCE;//CR1控制寄存器中PCE = 0

    /*3.4 1位停止位*/
    USART1->CR2 &= ~USART_CR2_STOP;//CR2控制寄存器中STOP = 00

    /*3.5 使能接收与发送*/
    USART1->CR1 |= USART_CR1_TE;
    USART1->CR1 |= USART_CR1_RE;

/*4.使能串口*/
    USART1->CR1 |= USART_CR1_UE;
}


/*
 *  接收一个字节
 */
uint8_t USART1_ReceiveByte(void)
{
    /*1 等待读取数据寄存器是否为非空 */
    while((USART1->SR & USART_SR_RXNE) == 0);//读数据寄存器非空(1:收到数据,可以读出)
    return USART1->DR;//读取DR,硬件中断清零RXNE位
}


/*
 *  接收一个变长的字符串,Size为接收到字符个数
 */
void USART1_ReceiveString(uint8_t str[],uint8_t *Size)
{
    uint8_t i = 0;
    while(1)
    {
        /* 判断当前数据帧是否接收完毕 */
        while (!(USART1->SR & USART_SR_RXNE))//读数据寄存器空(0:没有收到数据)
        {
          if((USART1->SR & USART_SR_IDLE))//IDLE位为1,标志空闲
           {
           	   USART1->SR &= ~USART_SR_IDLE;//IDLE位要软件置0,将IDLE位置0,为下一次空闲做准备
               *Size = i;
                return;//跳出函数
            }  
        }
      str[i++] =  USART1->DR;
    }
}

②主函数文件的代码如下:

#include "stm32f10x.h"                 
#include "USART.h"
#include "OLED.h"
#include "String.h"

uint8_t Str[100] = {0};
uint8_t Size = 0;
int main(void)
{
   
    OLED_Init();
	USART1_Init();
    
    OLED_ShowString(1,1,"Str:");

	while(1)
	{
		USART1_ReceiveString(Str,&Size);
        for(uint8_t i = 0;i < Size;i++)
        {
            OLED_ShowChar(1,i+5,Str[i]);
        }
	}
}

在这里插入图片描述

6、使用中断的方式接收数据

在这里插入图片描述
①USART.c文件的代码如下:

#include "USART.h"

/*
 *  串口1的初始化
 */
void USART1_Init(void)
{
/*1.开启GPIOA的时钟和USART1的时钟*/
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;//开启GPIOA的时钟
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN;//开启USART1的时钟

/*2.配置PA9和PA10引脚的工作模式:PA9(TX)为复用推挽输出,PA10(RX)为浮空输入*/
    GPIOA->CRH |= GPIO_CRH_MODE9;//MODE9 = 11:输出模式Speed = 50MHz
    GPIOA->CRH &= ~GPIO_CRH_CNF9_0;
    GPIOA->CRH |= GPIO_CRH_CNF9_1;//CF9 = 10:复用推挽输出

    GPIOA->CRH &= ~GPIO_CRH_MODE10;//MODE10 = 00:输入模式
    GPIOA->CRH |= GPIO_CRH_CNF10_0;
    GPIOA->CRH &= ~GPIO_CRH_CNF10_1;//CF10 = 01:浮空输入

/*3.串口的参数配置*/
    /*3.1 配置波特率位115200*/
    USART1->BRR = 0x271;

    /*3.2 数据位长度位8位*/
    USART1->CR1 &= ~USART_CR1_M; //CR1控制寄存器中M = 0

    /*3.3 配置不需要校验位*/
    USART1->CR1 &= ~USART_CR1_PCE;//CR1控制寄存器中PCE = 0

    /*3.4 1位停止位*/
    USART1->CR2 &= ~USART_CR2_STOP;//CR2控制寄存器中STOP = 00

    /*3.5 使能接收与发送*/
    USART1->CR1 |= USART_CR1_TE;
    USART1->CR1 |= USART_CR1_RE;

    /*3.6 使能中断*/
    USART1->CR1 |= USART_CR1_RXNEIE;//使能接收中断
    USART1->CR1 |= USART_CR1_IDLEIE;//使能空闲中断
    
/*4.配置NVIC*/
    NVIC_SetPriorityGrouping(4);//优先级分组
    NVIC_SetPriority(USART1_IRQn,2);//抢占值为2
    NVIC_EnableIRQ(USART1_IRQn);//使能中断请求

/*5.使能串口*/
    USART1->CR1 |= USART_CR1_UE;
}

/*
 *  中断服务函数:接收变长数据
 */
uint8_t Array[100];
uint8_t Flag = 0;
uint8_t Len = 0;
void USART1_IRQHandler(void)
{
    /* 产生中断的发送很多,但是只有一个中断服务函数,所以需要判断标志位 */
    if(USART1->SR & USART_SR_RXNE)//如果是接收数据产生的中断
    {
        Array[Len] = USART1->DR;//读取数据并自动清除中断标志位
        Len++;
    }
    if(USART1->SR & USART_SR_IDLE)//如果是空闲产生的中断
    {
        USART1->SR;
        USART1->DR;//清除IDLE中断标志位
        Flag = 1;
    }
}

②USART.h文件的代码如下:

#ifndef __USART_H
#define __USART_H

#include "stm32f10x.h"

void USART1_Init(void);
void USART1_SendByte(uint8_t Byte);
void USART1_SendString(uint8_t *str, uint16_t Length);

extern uint8_t Array[100];
extern uint8_t Flag;
extern uint8_t Len;
#endif

③主函数文件的代码如下:

#include "stm32f10x.h"                  
#include "USART.h"
#include "OLED.h"
#include "String.h"


int main(void)
{
	USART1_Init();
    OLED_Init();
    OLED_ShowString(1,1,"Str:");
	while(1)
	{
        if(Flag)
        {
            OLED_Clear();
            OLED_ShowString(1,1,"Str:");
            for(uint8_t i = 0;i < Len;i++)
            {
                OLED_ShowChar(1,i+5,Array[i]);
            }
            Flag = 0;
            Len = 0;
        }
	}
}

在这里插入图片描述

7、串口进行printf重定向

Keil软件的一些配置:
在这里插入图片描述①USART.h文件的代码如下:

#include "USART.h"
#include "String.h"
#include <stdio.h>

/*
 *  串口1的初始化
 */
void USART1_Init(void)
{
/*1.开启GPIOA的时钟和USART1的时钟*/
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;//开启GPIOA的时钟
    RCC->APB2ENR |= RCC_APB2ENR_USART1EN;//开启USART1的时钟

/*2.配置PA9和PA10引脚的工作模式:PA9(TX)为复用推挽输出,PA10(RX)为浮空输入*/
    GPIOA->CRH |= GPIO_CRH_MODE9;//MODE9 = 11:输出模式Speed = 50MHz
    GPIOA->CRH &= ~GPIO_CRH_CNF9_0;
    GPIOA->CRH |= GPIO_CRH_CNF9_1;//CF9 = 10:复用推挽输出

    GPIOA->CRH &= ~GPIO_CRH_MODE10;//MODE10 = 00:输入模式
    GPIOA->CRH |= GPIO_CRH_CNF10_0;
    GPIOA->CRH &= ~GPIO_CRH_CNF10_1;//CF10 = 01:浮空输入

/*3.串口的参数配置*/
    /*3.1 配置波特率位115200*/
    USART1->BRR = 0x271;

    /*3.2 数据位长度位8位*/
    USART1->CR1 &= ~USART_CR1_M; //CR1控制寄存器中M = 0

    /*3.3 配置不需要校验位*/
    USART1->CR1 &= ~USART_CR1_PCE;//CR1控制寄存器中PCE = 0

    /*3.4 1位停止位*/
    USART1->CR2 &= ~USART_CR2_STOP;//CR2控制寄存器中STOP = 00

    /*3.5 使能接收与发送*/
    USART1->CR1 |= USART_CR1_TE;
    USART1->CR1 |= USART_CR1_RE;


/*4.使能串口*/
    USART1->CR1 |= USART_CR1_UE;
}

/*
 *  发送一个字节
 */
void USART1_SendByte(uint8_t Byte)
{
    /*1.等待数据寄存器是否空,即发送数据寄存器空*/
    while((USART1->SR & USART_SR_TXE) == 0);//表示数据寄存器非空
    USART1->DR = Byte;//写入DR硬件自动置位TXE位
}

/*
 *  发送一个字符串
 */
void USART1_SendString(uint8_t *str, uint16_t Length)
{
    for(uint8_t i = 0; i < Length ;i++)
    {
        USART1_SendByte(str[i]);
    }
}

/*
 *  printf()重定向:重写fputc
 */
int fputc(int ch,FILE * file)
{
    //直接将字符发送到串口
    USART1_SendByte(ch);
    return ch;
}

②主函数文件的代码如下:

#include "stm32f10x.h"                  
#include "USART.h"

int main(void)
{
	USART1_Init();
    printf("woshinibaba\r\n");//向串口输出woshinibaba
   
	while(1)
	{
        
	}
}

在这里插入图片描述

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

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

相关文章

后端增删改查的基本应用——一个简单的货物管理系统

最终效果&#xff0c;如图所示&#xff1a; 如果想要进行修改操作&#xff0c;可点击某栏修改选项&#xff0c;会在本表格下方弹出修改的具体操作界面&#xff08;点击前隐藏&#xff09;&#xff0c;并且目前的信息可复现在修改框内。 本篇文章通过该项目将后端和前端结合起来…

java内存控制

Java 内存控制是一个相对复杂但至关重要的主题&#xff0c;它涉及到如何高效地管理Java应用程序中的内存资源。在Java中&#xff0c;内存管理主要由Java虚拟机&#xff08;JVM&#xff09;负责&#xff0c;包括内存的分配和回收。尽管如此&#xff0c;作为开发者&#xff0c;我…

2025年5月高项,从0备考信息系统项目管理师 | 备考经验全攻略分享

在逐步摸索备考信息系统项目管理师的过程中&#xff0c;我总结了很多关于班课资料和学习经验&#xff0c;现在与大家分享。&#xff08;全文约3k字&#xff0c;阅读用时约5min&#xff09; 这篇分享帖不仅告诉你关于备考信息系统项目管理师实用的班课资料&#xff0c;还有学习…

Win11 23H2 10月正式版:22631.4317 镜像免费下载!

今日&#xff0c;系统之家小编给您带来2024年10月最新更新的Windows11 23H2正式版系统下载&#xff0c;该版本系统基于微软官方最新Windows11 23H2 22631.4317专业版展开离线制作&#xff0c;没有病毒残留&#xff0c;且能完美支持新老机型&#xff0c;安装后&#xff0c;系统版…

【概率论】泊松分布

泊松分布 若 &#xff0c;则 归一性 例子 泊松分布多出现在当X表示一定时间或一定空间内出现的事件的个数这种场合&#xff0c;如在一定时间内某交通路口所发生的事故的个数。 将泊松分布假设为二项分布 假设条件: &#xff08;1&#xff09;泊松分布一般为一段时间或一…

★ 算法OJ题 ★ 二分查找算法

Ciallo&#xff5e;(∠・ω< )⌒☆ ~ 今天&#xff0c;塞尔达将和大家一起做几道二分查找算法算法题 ~ ❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️ 澄岚主页&#xff1a;椎名澄嵐-CSDN博客 算法专栏&#xff1a;★ 优选算法100天 ★_椎名澄嵐的博客-CSDN博客…

STM32 SPI串行总线

目录 STM32的SPI通信原理 SPI串行总线概述 SPI串行总线互连方式 STM32F1 SPI串行总线的工作原理 SPI串行总线的特征 SPI串行总线的内部结构 SPI串行总线时钟信号的相位和极性 STM32的SPI接口配置 STM32的SPI接口数据发送与接收过程 SPI的HAL 驱动函数 STM32的SPI通信…

靶标弹孔检测系统源码分享

靶标弹孔检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision …

apt update报错:ModuleNotFoundError: No module named ‘apt_pkg‘(可能是默认python版本被改坏了)

文章目录 错误信息分析1. 确保 apt_pkg 模块已安装2. 检查 Python 版本3. 重新配置 Python4. 修复损坏的依赖5. 检查环境变量 尝试 错误信息 (base) rootkyai:/ky/tml/ky_ai_get_server_info# apt update 获取:1 file:/var/cuda-repo-cross-aarch64-ubuntu2004-11-4-local InR…

【Python】如何让SQL Server像MySQL一样拥有慢查询日志(Slow Query Log慢日志)

如何让SQL Server像MySQL一样拥有慢查询日志&#xff08;Slow Query Log慢日志&#xff09; SQL Server一直以来被人诟病的一个问题是缺少了像MySQL的慢日志功能&#xff0c;程序员和运维无法知道数据库过去历史的慢查询语句。 因为SQLServer默认是不捕获过去历史的长时间阻塞…

inBuilder低代码平台新特性推荐-第二十五期

今天来给大家带来的是inBuilder低代码平台社区版中的特性推荐系列第二十五期——选人组件扩展&#xff01; 一、概述 inBuilder低代码平台社区版的开发过程中&#xff0c;选人组件支持tab页中增加扩展页面&#xff0c;由二开人员根据业务场景实现自定义取数接口和页面展示形式…

【笔记】济南,天命人,春秋

孤独而高傲的济南人 浩克山东知天命热爱的sensei 浩克山东 哦哦&#xff0c;最高的大葱也是济南的了&#xff0c;这大葱&#xff0c;比一般人要高呢&#xff0c;尽管济南的朋友们也都个子不矮。。能想像的到两米高的米库。。。。 然而在这块地界&#xff0c;遇到个人&#xf…

基于STM32的简易交通灯proteus仿真设计(仿真+程序+设计报告+讲解视频)

基于STM32的简易交通灯proteus仿真设计(仿真程序设计报告讲解视频&#xff09; 仿真图proteus 8.9 程序编译器&#xff1a;keil 5 编程语言&#xff1a;C语言 设计编号&#xff1a;C0091 **1.**主要功能 功能说明&#xff1a; 以STM32单片机和数码管、LED灯设计简易交通…

版本控制系统Helix Core的常见使用误区及解决办法、实用工具及新功能介绍

日前&#xff0c;Perforce携手合作伙伴龙智一同亮相Unreal Fest 2024上海站&#xff0c;分享Helix Core版本控制系统及其协作套件的强大功能与最新动态&#xff0c;助力游戏创意产业加速前行。 Perforce解决方案工程师Kory Luo在活动主会场&#xff0c;带来《Perforce Helix C…

QT安装成功后-在创建项目时,发现仅有项目名文件

&#xff08;1&#xff09;QT安装成功后&#xff0c;发现仅有项目名文件其他可编辑文件缺失 &#xff08;2&#xff09;点击文件名左上角的感叹号显示【No kits are enabled for this project. Enable】 小编在尝试多次后发现&#xff0c;可以通过以下方式解决&#xff1a;QT软…

YOLO11改进|编码器篇|引入AIFI混合特征编码器

目录 一、【AIFI】混合编码器机制1.1【AIFI】混合编码器介绍1.2【AIFI】核心代码 二、添加【AIFI】机制2.1STEP12.2STEP22.3STEP32.4STEP4 三、yaml文件与运行3.1yaml文件3.2运行成功截图 一、【AIFI】混合编码器机制 1.1【AIFI】混合编码器介绍 【AIFI】在论文中并没有结构图…

CVPR 2024最佳论文候选-pixelSplat论文解读

目录 一、概述 二、相关工作 1、单场景下的视角合成 2、基于先验的三维重建和视图合成 3、多视图几何测量 三、3DGS的缺点 1、容易陷入最小值 2、需要大量输入图像 3、尺度模糊性 四、pixelSplat 1、解决尺度模糊性&#xff08;深度信息生成&#xff09; 2、编码器…

QT实现QMessageBox中文按钮

这是我记录Qt学习过程心得文章的第二篇&#xff0c;主要是为了方便QMessageBox弹出框的使用&#xff0c;通过自定义的方式&#xff0c;将其常用的功能&#xff0c;统一封装成一个函数&#xff0c;还是写在了Skysonya类里面。 实现代码&#xff1a; //中文提示对话框 bool Sky…

线程(四)线程的同步——条件变量

文章目录 线程线程的同步和互斥线程同步--条件变量什么是线程同步示例--条件变量的使用示例--使用两个线程对同一个文件进行读写示例--一个读者一个写者使用条件变量来实现同步 线程 线程的同步和互斥 线程同步–条件变量 是一个宏观概念&#xff0c;在微观上包含线程的相互…

新160个crackme - 078-CodeZero.1

运行分析 需要破解Serial PE分析 VB程序&#xff0c;32位&#xff0c;无壳 静态分析&动态调试 使用VB Decompiler进行分析找到check按钮事件&#xff1a; Form1 -> Command1_Click_4055F4发现直接爆出了Serial55555 验证成功