找回密码
 立即注册
查看: 25|回复: 8

USB型 1T 8051 单片机原理及应用-8H8K64U-学习打卡

[复制链接]
  • 打卡等级:偶尔看看I
  • 打卡总天数:14
  • 最近打卡:2026-03-27 00:08:07
已绑定手机

2

主题

21

回帖

86

积分

注册会员

积分
86
发表于 3 天前 | 显示全部楼层 |阅读模式

打卡第一集-《STC最新8051单片机原理及应用-STC8H8K64U》视频课程导论

单片机应用系统常用的元器件

一、电阻

1. 作用

  • 限流:保护LED、三极管、IC输入脚等
  • 分压:产生参考电压、电平转换
  • 上拉/下拉:为引脚确定默认电平(防止悬空)
  • 阻抗匹配:信号完整性,如USB、CAN总线终端电阻

2. 常用类型

类型 特点 应用
贴片电阻 体积小,适合PCB量产 绝大多数现代电路
色环电阻 直插式,方便手工焊接 面包板、万能板实验
排阻 多个电阻集成,节省空间 上拉电阻组(如8路LED限流)

3. 选型要点

  • 阻值:根据欧姆定律计算(如LED限流:R=(VCC−VF)/IFR=**(VCC****−VF)**/IF****)
  • 功率:1/4W(0.25W)最常用,大电流场合选1/2W或更大
  • 精度:普通电路5%即可,精密分压(如ADC参考)选1%或更高

二、电容

1. 作用

  • 滤波:平滑电源纹波,去除高频噪声
  • 耦合/隔直:交流信号传输,阻断直流
  • 去耦:靠近IC电源引脚,提供瞬时电流,防止电源波动导致误动作
  • 定时/振荡:与电阻组成RC定时或配合晶振起振

2. 常用类型

类型 特点 典型容量 应用场景
陶瓷电容 高频特性好,无极性 0.1μF、1μF、10μF 去耦、高频滤波
电解电容 容量大,有极性(注意正负极) 10μF~1000μF 电源滤波、储能
钽电容 体积小,稳定性好,有极性 10μF~100μF 对体积和稳定性要求高的场合

3. 典型配置

  • 电源输入端:大电解电容(100μF~470μF)+ 小陶瓷电容(0.1μF)
  • MCU每个电源引脚:0.1μF陶瓷电容就近放置(去耦)
  • 晶振电路:12pF~22pF负载电容,配合晶振使用

三、二极管

1. 作用

  • 整流:交流变直流
  • 续流:保护开关器件(如继电器、电机驱动)
  • 稳压:稳压二极管提供参考电压
  • 防反接:电源输入端防止正负极接反
  • 信号钳位:限制输入电压范围

2. 常用类型

类型 符号特征 典型应用
整流二极管(1N4007) 普通PN结,耐压高 电源整流、防反接
开关二极管(1N4148) 开关速度快 高频信号、续流
肖特基二极管(SS34) 正向压降低(~0.3V),速度快 低压电源、高频整流
稳压二极管(齐纳管) 反向击穿区工作 产生稳定电压(如3.3V、5V参考)
LED 发光二极管,有极性 电源指示、状态指示

💡 注意:二极管有正负极,实物中通常有标记(LED长脚为正,稳压管黑环为负)。


四、三极管

1. 类型

  • NPN型:电流从基极流向发射极时,集电极到发射极导通(高电平控制)
  • PNP型:电流从发射极流向基极时,发射极到集电极导通(低电平控制)

2. 三种工作状态(以NPN为例)

状态 条件(VBEVBE) 特征 应用
截止状态 VBE<0.6VVBE<0.6V 相当于开关断开,IC≈0IC≈0 开关断开、逻辑0
放大状态 VBE≈0.6VVBE≈0.6V,且基极电流适中 IC=β×IBIC=**β**×**I**B****,线性放大 模拟信号放大(音频、传感器)
饱和状态 VBEVBE足够大,基极电流充足 VCE≈0.2VVCE≈0.2V,相当于开关闭合 驱动LED、继电器、蜂鸣器

3. 典型应用

  • 开关驱动:用单片机IO口控制三极管基极,驱动大电流负载(继电器、电机)
  • 电平转换:3.3V系统控制5V器件
  • 信号放大:麦克风、光敏传感器前端放大

💡 常用型号:NPN(S8050、2N2222)、PNP(S8550、2N3906)


五、晶体振荡器(晶振)

1. 作用

为单片机提供稳定的时钟信号,是系统运行的“心跳”。

2. 类型

类型 说明 典型频率
无源晶振(晶体) 需要配合MCU内部振荡电路和负载电容 8MHz、12MHz、16MHz
有源晶振(振荡器) 内部集成振荡电路,直接输出方波,供电即可 8MHz、16MHz、25MHz

3. 选型要点

  • 单片机主频取决于外部晶振频率和内部PLL倍频(如STM32用8MHz晶振可倍频到72MHz)
  • 时钟精度影响定时、串口通信波特率
  • 晶振两端负载电容需匹配,常见12pF~22pF

六、数码管

1. 作用

用于数字显示(温度、计数值、时间等),是单片机常用输出设备。

2. 类型

类型 特点
共阴极数码管 公共端接GND,段码高电平点亮
共阳极数码管 公共端接VCC,段码低电平点亮
一位/多位 多位数码管通常通过动态扫描驱动

3. 驱动方式

  • 静态驱动:每个段单独用IO口控制(占用引脚多)
  • 动态扫描:分时轮流点亮每位,利用视觉暂留(节省IO口,常用74HC595、TM1650等驱动芯片)

💡 典型驱动芯片:TM1637、MAX7219,可简化电路,减少IO占用。


七、电路板/实验平台

1. 面包板

  • 特点:免焊接,可反复插拔
  • 用途:电路原型验证、实验教学、临时搭建
  • 注意:接触电阻不可忽略,不适合高频或大电流电路

2. 万能板 + 套件

  • 特点:又称洞洞板、万用板,需要手工焊接
  • 用途:制作永久性实验电路、DIY项目
  • 套件内容:常包含排针、排母、杜邦线、电源模块、常用阻容件
  • 优点:成本低,适合学生练习焊接和调试

3. 试验箱

  • 特点:集成化的教学实验平台
  • 包含:单片机核心板、按键、LED、数码管、LCD、蜂鸣器、传感器模块等
  • 用途:高校实验室、系统学习单片机开发
  • 优点:即插即用,减少接线错误,快速验证代码

八、总结对照表

元器件 核心作用 选型关键
电阻 限流、分压、上下拉 阻值、功率、精度
电容 滤波、去耦、储能 容值、耐压、类型
二极管 整流、续流、稳压、指示 正向压降、反向耐压、速度
三极管 开关、放大 类型(NPN/PNP)、电流、hFEhFE
晶振 提供时钟 频率、负载电容、精度
数码管 数字显示 位数、共阴/共阳、驱动方式
面包板 免焊实验 触点质量、插孔间距
万能板 手工焊接成品 孔径、焊盘间距
试验箱 教学集成平台 集成度、配套资源

Flash程序存储器,通常简称为 Flash程序存储器,是嵌入式系统(如单片机、微控制器)中的一种非易失性存储器

它的核心作用是存储用户编写的程序代码(固件)以及一些需要在断电后保留的数据。

以下是它的几个关键特性:

1. 非易失性

与计算机的内存(RAM)不同,Flash存储器在芯片断电后数据不会丢失。当你在单片机中烧录程序后,即使断开电源,下次上电时程序依然会运行。

2. 电可擦除与可编程

传统的单片机通常使用 ROM(只读存储器,无法修改)或 EPROM(需要紫外线擦除,修改不便)。Flash存储器可以通过电信号进行在线擦除和重写,这极大地方便了程序的调试和升级(ISP/IAP技术)。

3. 在单片机中的角色

在STM32、AVR、ESP32等常见的微控制器(MCU)内部,通常包含三种主要的存储区域:

  • Flash(闪存): 相当于电脑的“硬盘”。存放你的代码(.text段)、常量(.rodata段)以及只读数据。通常容量较大,但写入速度相对较慢(按页/扇区操作)。
  • SRAM(静态随机存取存储器): 相当于电脑的“内存”。存放全局变量、栈(Stack)和堆(Heap)。断电数据丢失,但读写速度快(按字节操作)。
  • EEPROM(电可擦除可编程只读存储器): 部分单片机内置。用于存储需要频繁修改且断电保留的数据(如用户设置)。虽然Flash也可以模拟EEPROM,但EEPROM在按字节擦写方面更为灵活。

4. 主要特点

  • 读速度快: CPU可以直接从Flash中“取指”执行(即冯·诺依曼或哈佛架构中的取指阶段)。
  • 写/擦除慢: Flash的写入通常需要先将一整块区域(称为“扇区”或“页”)擦除(变为0xFF),然后再写入数据。不能像RAM那样直接覆盖单个字节。
  • 擦写寿命: Flash存储器有有限的擦写次数,通常在 1万次到10万次 之间。如果程序需要频繁保存数据(例如每秒记录一次),需要注意磨损均衡算法,否则Flash可能会损坏。

5. 扩展与分类

  • 内部Flash: 集成在MCU芯片内部。如STM32F103C8T6通常有64KB的Flash。
  • 外部Flash: 对于某些应用(如存储字库、图片、音频),MCU内部的Flash容量不足时,可以通过SPI、QSPI等接口外接Flash芯片(如W25Q64)。

总结:
在嵌入式开发中,Flash程序存储器就是用来“固住”你的程序的存储器。当你通过下载器(如ST-Link、J-Link)将编译好的 .hex.bin 文件烧录进芯片时,这些数据最终就是被写入到了Flash程序存储器中。


在嵌入式开发(单片机、ARM、DSP等)的语境下,仿真器(通常指的是硬件调试器/编程器)是一种必不可少的硬件工具。

简单来说,它的核心作用是充当 “电脑(PC)”与“芯片(MCU)”之间的桥梁。它主要负责两件事:把程序烧录进去,以及让你实时查看芯片内部正在发生什么

结合你刚才问的Flash程序存储器,它们的关系是:仿真器负责把代码“搬运”并写入到Flash程序存储器中。

具体来说,仿真器主要有以下两大核心功能:

1. 程序下载(编程器功能)

当你写完代码,编译生成 .hex.bin 文件后,程序需要被放进单片机的Flash里。

  • 过程:电脑通过USB线连接仿真器 -> 仿真器通过专用的调试接口(如SWD、JTAG)连接单片机。
  • 作用:仿真器接收电脑发来的程序数据,将其转换成单片机能够识别的电气信号,写入内部的Flash程序存储器(也就是你之前了解的那个存储空间)。如果没有仿真器,单片机就是一块“空白的石头”,无法运行任何逻辑。

2. 在线调试(调试器功能)

这是仿真器最强大的地方,也是它区别于普通“下载器”的地方。它允许你“冻结”正在运行的芯片,窥探其内部状态。

  • 断点:你可以在代码的某一行设置一个断点。程序运行到这里会瞬间暂停。你可以查看此时CPU寄存器里是什么值,某个变量的数值是多少。
  • 单步执行:你可以让程序一行一行地执行。这在排查逻辑错误、死机、程序跑飞时极其有用。
  • 实时观察:在调试界面上,你可以看到RAM(内存)中的数据变化,甚至可以在不停止程序的情况下查看变量。

常见的仿真器类型

不同的芯片厂商有不同的仿真器,但它们本质上干的是同一件事:

  • ST-Link:用于意法半导体(ST)的STM32系列单片机。这是最普及的仿真器之一。
  • J-Link:德国Segger公司出品,通用性最强,支持几乎所有的ARM Cortex-M内核芯片。性能稳定,速度很快,但在业界使用较多(价格也较高),个人开发者也有机会用到其衍生版本。
  • DAP-Link:ARM官方推出的开源仿真器,很多国产开发板(如STM32、MM32等)都板载这种调试器。
  • USB转TTL(串口下载):需要区分一下。像Arduino、51单片机常用这种。它通常只能“下载程序”,不能“在线调试”(无法设置断点看内部变量),属于简化版的仿真/下载工具。

总结

  • 没有仿真器:你只能把代码写出来,烧进去,然后靠看LED灯闪不闪、或者通过串口打印数据来猜测程序哪里出错了(这被称为“盲调”)。
  • 有仿真器:你可以随时让程序暂停,看看到底是哪个变量变成了奇怪的值,或是程序有没有卡死在某个死循环里。

一句话总结: 仿真器是嵌入式开发的“透视眼”和“手术刀”,让你不仅能把程序装进Flash,还能在芯片运行时实时诊断和修复Bug

回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:361
  • 最近打卡:2026-03-26 08:46:35

844

主题

1万

回帖

2万

积分

管理员

积分
22719
发表于 3 天前 | 显示全部楼层
要 做到 USB不停电下载
要 尝试 AiCube 图形化自动配置生成程序工具
推荐优先看的:  
printf_usb("Hello World !\r\n")
USB不停电下载, 演示视频链接:
https://www.stcaimcu.com/thread-19077-1-1.html

下载 最新的 AiCube-ISP-V6.96T 或以上版本软件 !

深圳国芯人工智能有限公司-工具软件

下载 最新的 USB库函数,永远用最新的 USB库函数 !
深圳国芯人工智能有限公司-库函数
下载 最新的 用户手册 !
下载 最新的 上机实践指导书 !

下载 最新的 STC8H8K64U 用户手册
https://www.stcaimcu.com/data/download/Datasheet/STC8H.pdf

下载 最新的 STC8H8K64U 实验指导书
AiCube 图形化自动配置生成程序工具使用说明
https://www.stcaimcu.com/data/do ... %AF%BC%E4%B9%A6.pdf


上面是 小李 演示:STC8H8K64U, printf_usb("Hello World !\r\n")及usb不停电下载@AiCube之图形化程序自动生成
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:14
  • 最近打卡:2026-03-27 00:08:07
已绑定手机

2

主题

21

回帖

86

积分

注册会员

积分
86
发表于 3 天前 | 显示全部楼层

打卡第二集-点灯大师启航,看到效果再理论

单片机中的 main函数与计算机程序有所不同,因为单片机通常没有操作系统,程序是裸机运行的。

基本结构

c

#include <reg52.h>  // 或相应的头文件

void main() {
    // 初始化代码
  
    while(1) {
        // 主循环,程序永远在这里运行
    }
}

关键特点

1. 不会返回

c

void main(void) {  // 通常返回类型为void
    // 初始化
  
    while(1) {
        // 无限循环,程序不会退出
    }
}

2. 需要初始化

c

void main(void) {
    // 1. 关闭中断(如果需要)
    // 2. 初始化时钟
    // 3. 初始化外设(GPIO、UART、定时器等)
    // 4. 初始化变量
  
    while(1) {
        // 主循环任务
    }
}

3. 常见模式

轮询模式:

c

void main(void) {
    System_Init();
  
    while(1) {
        // 不断检查各个标志位
        if (flag_uart) {
            Process_UART();
        }
        if (flag_timer) {
            Process_Timer();
        }
    }
}

中断+主循环:

c

void main(void) {
    System_Init();
    __enable_irq();  // 开启中断
  
    while(1) {
        // 主循环处理后台任务
        // 中断服务程序处理实时任务
        __WFI();  // 进入低功耗模式(可选)
    }
}

不同单片机的差异

单片机 main函数特点
51单片机 void main(void),需要手动配置寄存器
STM32 int main(void),通常在 while(1)前有外设初始化
Arduino setup() + loop()main()被框架隐藏
ESP32 void app_main(void),基于FreeRTOS

启动流程(重要)

单片机上电后,实际上不是直接执行main函数

text

上电复位 → 启动文件(startup) → 设置堆栈指针 → 
清除BSS段 → 初始化C库 → 调用main函数 → 执行main函数

示例:STM32的main函数

c

int main(void) {
    // 1. 复位所有外设
    HAL_Init();
  
    // 2. 配置系统时钟
    SystemClock_Config();
  
    // 3. 初始化外设
    MX_GPIO_Init();
    MX_USART1_Init();
    MX_TIM1_Init();
  
    // 4. 用户初始化
    LED_Off();
  
    // 5. 主循环
    while(1) {
        HAL_Delay(1000);
        LED_Toggle();
    }
}

注意事项

  1. 不能返回:main函数中不能用 return(除非有操作系统)
  2. 堆栈大小:需要合理设置启动文件中的堆栈大小
  3. 看门狗:主循环中要定期喂狗,防止复位
  4. 低功耗:主循环空闲时可以进入休眠模式

Keil C251Keil C51的主要区别

对比维度 Keil C51 Keil C251
目标芯片 支持8051及衍生系列单片机。 支持MCS 251架构微控制器,可向下兼容部分8051功能。
代码与数据空间 最大支持64KB 程序/数据空间。 程序空间可高达 16MB,远超C51的限制。
库函数特性 约一半的库函数不可重入,在多任务或中断中需特别小心。 绝大部分库函数是可重入的,更适合运行RTOS实时操作系统。
参数传递方式 主要通过固定的寄存器或内存位置传递,效率相对较低。 优化了参数传递,更多地利用堆栈,效率更高且支持更复杂的函数调用。
编译器指令 需要 AREGS, NOAREGS等指令来优化寄存器访问。 不再需要上述指令,新增 MODSRCPARM251等以适配251架构。
兼容与模式 仅支持标准8051模式。 提供二进制模式,可直接调用和链接为C51编译的旧代码。

为什么会有这些区别?

理解这些区别的关键在于它们服务的硬件内核完全不同:

  1. 硬件架构的演进
    • 8051 是经典的8位单片机架构,其指令集和寻址能力(最大64KB)限制了编译器的设计,迫使C51采用了许多“取巧”的方式(如固定寄存器传递参数)来在有限资源下提高效率。
    • MCS 251 是8051的升级版,引入了16位/32位指令和更强大的寻址能力(最大16MB)。C251编译器因此可以设计得更现代化,比如更好地利用堆栈来传递参数和分配局部变量,这使得函数天然具备可重入性,极大地简化了多任务编程的复杂性。
  2. 开发体验的侧重
    • C51 侧重于在资源极其受限的8051芯片上,榨取最高的性能和最小的代码尺寸。因此它的很多特性(如不可重入函数)是特定历史条件下的优化选择,但也要求开发者具备更深厚的专业知识来避免踩坑。
    • C251 则是在保持与8051一定兼容性的基础上,提供了更接近现代C语言开发体验的环境。它的库函数更安全(可重入),代码管理更灵活(支持更大内存模型),让开发者能更专注于业务逻辑而非底层细节。

总结与选择建议

  • 选择 Keil C51:当你使用的单片机是标准的8051内核,如经典的AT89C51、STC89C52,或是较新的STC8系列时。此时C51是最佳也是唯一的选择。
  • 选择 Keil C251:当你使用的单片机是基于251内核的,例如 STC32系列 等。使用C251才能充分发挥这些芯片的性能优势,特别是在需要运行实时操作系统(RTOS) 或处理更复杂逻辑的大型项目中。

两者都使用相同的μVision集成开发环境(IDE),所以在操作界面上差别不大,主要区别在于底层的编译器工具链。在Keil安装目录下,C51和C251也是两个独立的文件夹,不能混用。


总线是计算机或嵌入式系统中,用于在多个组件之间传输数据的公共通信路径。简单理解,它就像城市的“交通系统”,连接CPU、内存、外设等各个部件,让它们能够相互通信。

根据传输内容的不同,总线通常被分为三大类:地址总线数据总线控制总线。这三者协同工作,完成一次完整的读写操作。


一、地址总线

作用:用于传输地址信息,指定数据从哪里来或到哪里去。
方向单向,通常由CPU发出,指向内存或外设。

  • CPU通过地址总线告诉内存:“我要操作地址0x1000这个位置的数据。”
  • 宽度决定寻址范围。例如:
    • 16位地址总线 → 可寻址 216=64KB216**=**64**K**B
    • 32位地址总线 → 可寻址 4GB

结合你之前问的Keil C51,8051单片机就是典型的16位地址总线,因此程序空间和数据空间最大均为64KB。


二、数据总线

作用:用于传输实际的数据,可以是CPU读入的数据,也可以是CPU写出的数据。
方向双向,数据可以在CPU与内存/外设之间双向流动。

  • 宽度决定单次传输的数据量。常见宽度有8位、16位、32位、64位等。
  • 例如:32位数据总线,一次可以传输4字节数据。

数据总线宽度与地址总线宽度是独立的。比如8086是16位数据总线 + 20位地址总线。


三、控制总线

作用:用于传输控制信号,协调总线上各个部件的工作,决定总线操作的类型和时序。
方向单向或双向均可,具体取决于信号类型。

常见的控制信号包括:

信号 含义
RD(读) CPU发出,表示要从内存/外设读取数据
WR(写) CPU发出,表示要向内存/外设写入数据
ALE(地址锁存允许) 用于分离地址和数据复用的总线
INT(中断请求) 外设向CPU请求中断服务
RESET 复位信号
HOLD/HLDA(总线保持/响应) DMA等设备请求并占用总线控制权

四、三者如何配合工作?

以CPU从内存读取一个字节为例:

  1. CPU将目标地址放到地址总线上(如0x2000)
  2. CPU通过控制总线发出 RD(读)信号
  3. 内存控制器根据地址取出对应的数据
  4. 数据通过数据总线传回CPU

地址总线负责“定位”,控制总线负责“指挥”,数据总线负责“传输”。


五、补充概念:总线复用

在一些资源受限的系统中(如经典的8051单片机),为了减少引脚数量,地址总线和数据总线会复用

  • 例如8051的P0口既作为低8位地址总线,也作为8位数据总线
  • 通过 ALE 信号锁存地址,实现分时复用
  • 代价是传输效率略低于独立总线架构

六、从“总线”延伸:总线分类

除了按功能分为地址/数据/控制总线外,按层次结构还可以分为:

类型 说明
片内总线 CPU芯片内部的总线,连接ALU、寄存器、Cache等
系统总线 连接CPU、内存、DMA、主控外设等主要部件
外部总线 连接外部设备,如PCI、USB、I²C、SPI、CAN等

总结

总线类型 核心作用 方向 类比
地址总线 指定操作目标地址 单向 快递单上的“收件地址”
数据总线 传输实际数据 双向 快递包裹中的“货物”
控制总线 发出控制指令与状态 单向/双向 快递员的“派送指令”

这三者共同构成了计算机系统的通信骨架。如果你正在学习单片机(如8051或STM32),理解总线的概念对于掌握存储器扩展、I/O接口设计、时序分析都会很有帮助。

回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:14
  • 最近打卡:2026-03-27 00:08:07
已绑定手机

2

主题

21

回帖

86

积分

注册会员

积分
86
发表于 3 天前 | 显示全部楼层

打卡第三集-数字逻辑与基本数字电路

逻辑电平是数字电路中用来表示逻辑状态(0或1)的电压范围。简单来说,它定义了“多高的电压算高电平(逻辑1),多低的电压算低电平(逻辑0)”。

由于不同系列的芯片(如TTL、CMOS)对电压的“阈值”定义不同,理解逻辑电平对电路设计、芯片互联至关重要。如果电平不匹配,可能导致逻辑误判、功耗增大,甚至烧毁芯片。


三种逻辑门电路

一、基本逻辑门

1. 与门

  • 逻辑关系全1出1,有0出0
  • 通俗理解:相当于电路中的“串联开关”。只有两个开关同时闭合,灯泡才会亮。
  • 表达式:Y=A⋅BY=**A**⋅**B** 或 Y=A&B**Y**=**A**&**B**
输入 A 输入 B 输出 Y
0 0 0
0 1 0
1 0 0
1 1 1

2. 或门

  • 逻辑关系有1出1,全0出0
  • 通俗理解:相当于电路中的“并联开关”。只要至少有一个开关闭合,灯泡就会亮。
  • 表达式:Y=A+BY=**A**+**B**
输入 A 输入 B 输出 Y
0 0 0
0 1 1
1 0 1
1 1 1

3. 非门

  • 逻辑关系输入与输出相反
  • 通俗理解:相当于电路中的“反相器”。开关闭合(1),灯泡反而不亮(0);开关断开(0),灯泡反而亮(1)。
  • 表达式:Y=A‾Y=**A** 或 Y=!A**Y**=**!**A
输入 A 输出 Y
0 1
1 0

二、逻辑门的物理实现(TTL与CMOS)

结合你之前问的逻辑电平,这些逻辑门在实际电路中是通过晶体管实现的:

  • TTL(晶体管-晶体管逻辑):早期标准,使用双极性晶体管,速度快但功耗高。
  • CMOS(互补金属氧化物半导体):现代主流,使用MOSFET(金属氧化物半导体场效应管)组成互补的“上拉网络”(PMOS)和“下拉网络”(NMOS)。

物理实现简析(以CMOS非门为例)

  • 输入为高电平(3.3V):NMOS导通,输出端被拉到GND(0V)→ 输出低电平
  • 输入为低电平(0V):PMOS导通,输出端被拉到VDD(3.3V)→ 输出高电平

三、由基本门派生的常用门

在实际应用中,为了简化电路设计,通常使用以下组合门:

门类型 逻辑关系 表达式 说明
与非门 先与后非 Y=A⋅B‾Y=**A**⋅**B** 通用性最强,可单独构成任何逻辑电路
或非门 先或后非 Y=A+B‾Y=**A**+**B** 同样具有完备性
异或门 相同为0,相异为1 Y=A⊕BY=**A**⊕**B** 常用于比较器、加法器、奇偶校验

四、逻辑门与单片机的关联

结合你之前关注的Keil C51/C251总线,逻辑门在单片机系统中的作用主要体现在:

  1. 地址译码(总线扩展)
    当单片机通过总线连接多个外部设备(如RAM、ROM、外设)时,需要用逻辑门对地址总线的高位进行“译码”,产生片选信号(CS)
    • 场景:C51扩展32KB外部RAM。
    • 实现:使用与门或门组合,判断地址线(如A15)是否为高电平,决定选中哪一块芯片。
  2. 接口电平转换
    当5V单片机与3.3V模块通信时,除了用专用芯片,有时也会用非门与门搭配上拉电阻进行简易的双向电平转换。
  3. 中断与唤醒
    多个外部中断源(INT0, INT1)可以通过或门合并为一个CPU中断引脚。此时任何一个外设触发中断,CPU都能响应。

五、总结

门电路 记忆口诀 电路类比 核心应用
与门 有0得0,全1得1 串联开关 使能控制、地址译码
或门 有1得1,全0得0 并联开关 中断合并、通道选择
非门 相反输出 反相器 电平翻转、振荡电路

这三者构成了数字世界的“加减乘除”。无论是CPU内部的算术逻辑单元进行运算,还是通过总线访问内存的地址译码,本质上都是成千上万个这类基本逻辑门在同时工作。

回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:14
  • 最近打卡:2026-03-27 00:08:07
已绑定手机

2

主题

21

回帖

86

积分

注册会员

积分
86
发表于 前天 08:22 | 显示全部楼层

打卡第四集-单片机的内部结构,STC补充外围电路设计讲解

单片机内部关键组成部分

1. 存储器(Memory)

单片机中的存储器解决了“存程序”和“存数据”的问题。与台式机CPU不同,单片机的存储器是集成在芯片内部的。

  • 程序存储器(ROM/Flash)
    • 作用非易失性存储,用来存放用户程序(代码)常量。断电后内容不会丢失。
    • 常见类型:现代单片机多为 Flash 存储器,支持在线编程;早期有OTP(一次可编程)或Mask ROM(掩膜ROM,出厂固化)。
  • 数据存储器(RAM)
    • 作用易失性存储,用来存放程序运行过程中的临时变量堆栈
    • 常见类型:通常为 SRAM(静态随机存取存储器),速度较快。
  • 特殊功能寄存器
    • 这是一种特殊的存储区。它既是存储器,也是控制单片机的“开关”。比如,你往某个特定地址的寄存器写入 0x01,对应的LED引脚就会亮;读取另一个寄存器,就能知道按键是否被按下。

2. 输入输出端口(I/O Ports)

这是单片机与外部世界交互的“手脚”。

  • GPIO:通用输入输出引脚。这是单片机最基本的外设。
    • 结构:通常可以配置为输入(读取高低电平)、输出(推挽或开漏输出)、复用功能(作为下面提到的UART、SPI等通信引脚)。
    • 特点:通常带有上拉/下拉电阻配置,以及施密特触发功能以提高抗干扰能力。

3. 定时器与计数器(Timers/Counters)

这是单片机中功能最丰富、最核心的外设之一。它不仅仅是用来计时的。

  • 基本定时器:产生周期性的中断,用于系统节拍(如RTOS的心跳)、延时。
  • 高级/通用定时器
    • PWM输出:通过调节占空比,用于控制电机转速、舵机角度、LED调光(呼吸灯)。
    • 输入捕获:测量外部输入信号的脉冲宽度或频率(如超声波测距、红外解码)。
  • 看门狗:这是一个特殊的定时器。启动后,程序必须定期“喂狗”(清零计数器)。如果程序跑飞或死机,没能及时喂狗,看门狗就会强制复位单片机,提高系统可靠性。

4. 中断系统(Interrupt System)

中断系统让单片机具备了“紧急响应”的能力。如果没有中断,CPU只能靠轮询(不断查看状态),效率很低。

  • 机制:当某个事件发生(如按键按下、串口收到数据、定时器溢出),CPU会暂停当前正在执行的主程序,保存现场,跳转去执行对应的“中断服务函数”,执行完后再回来继续执行主程序。
  • 优先级:现代单片机支持中断嵌套,高优先级的中断可以打断低优先级的中断。

5. 时钟系统(Clock System)

单片机是“同步时序电路”,没有时钟,它就“静止”了。

  • 内部振荡器:大部分单片机内部集成了RC振荡器(如8MHz、32kHz)。优点是上电即运行,不需要外接元件;缺点是精度相对较低(受温度影响)。
  • 外部振荡器:可以外接晶体(如常用的8MHz、12MHz晶振),用于对时钟精度要求较高的场景(如精准计时、USB通信)。
  • 锁相环:用于将低频时钟倍频到高频。例如,外部接8MHz晶振,通过PLL倍频到72MHz或更高,供CPU内核运行,以提升处理速度。

6. 通信接口(Communication Interfaces)

单片机通过这些接口与其他芯片(传感器、显示器、存储卡)或设备(电脑、手机)交换数据。

  • 同步串行接口
    • SPI:高速全双工,常用于显示屏、SD卡、Flash芯片通信。
    • I2C:半双工,仅需两根线(数据SDA、时钟SCL),常用于温湿度传感器、EEPROM。
  • 异步串行接口
    • UART/USART:也就是通常说的串口。常用于与电脑调试、连接GPS模块、蓝牙模块。
  • 其他高级接口
    • CAN:汽车电子和工业控制常用,抗干扰能力强。
    • USB:用于与PC高速通信或模拟键盘、U盘。
    • 以太网 MAC:用于网络通信。

7. 模拟外设(Analog Peripherals)

让单片机能够处理现实世界中连续变化的模拟信号。

  • 模数转换器核心部件。将外部输入的模拟电压(如电位器电压、传感器输出的连续电压)转换为数字量(如0-4095),供CPU计算。
    • 参数:分辨率(8位、10位、12位)、采样率。
  • 数模转换器:将数字量转换为模拟电压输出。部分高端单片机集成,用于音频播放或模拟量控制。
  • 比较器:比较两个输入电压的大小,直接输出0或1,常用于过压保护、波形整形等。

8. 总线系统(Bus System)

上述所有模块并不是孤立的,它们通过总线连接起来。

  • 结构:在单片机内部,通常有数据总线地址总线控制总线
  • 矩阵:在ARM Cortex-M系列(如STM32)等较复杂的单片机中,存在多层总线矩阵或多总线系统。它允许CPU访问Flash的同时,DMA(直接内存访问)在后台搬运数据,互不冲突,从而提高并发处理能力。

总结对比:单片机 vs. 通用CPU

为了让你更清晰地理解,可以对比一下:

特性 通用CPU (如电脑的Intel/AMD) 单片机 (如STM32, 8051, ESP32)
集成度 仅包含内核(控制器+运算器)和缓存 集成CPU、RAM、Flash、各种外设(ADC、定时器等)于单芯片
存储器 外接内存条(DDR)、硬盘 内部集成Flash和RAM
I/O能力 较弱,主要通过PCIe等总线扩展 强,上百个可编程I/O引脚直接引出
实时性 依赖操作系统调度,响应不确定 中断响应快,通常用于硬实时控制(如电机、汽车)
功耗 高,通常需要风扇散热 极低,可进入微安级睡眠模式
应用 运行Windows/Linux,处理复杂计算 控制家电、智能硬件、工业设备

总的来说,单片机是一个麻雀虽小,五脏俱全的微型计算机。它的核心优势在于高集成度低成本低功耗,特别适合用于嵌入式控制场景。

image.png

回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:14
  • 最近打卡:2026-03-27 00:08:07
已绑定手机

2

主题

21

回帖

86

积分

注册会员

积分
86
发表于 前天 13:39 | 显示全部楼层

打卡第五集-存储器空间及存储器,单片机的引脚

unsigned关键字

1. 基本区别:有符号 vs 无符号

类型 关键字 取值范围(以8位为例) 最高位含义
有符号 signed charchar(默认可能为有符号) -128~ 127 符号位(0正1负)
无符号 unsigned char 0~ 255 数值位的一部分

在16位或32位系统上类似,只是范围扩大。

例如

  • unsigned int:在32位单片机中通常为 0 ~ 4,294,967,295
  • unsigned short:0 ~ 65,535
  • unsigned long:0 ~ 4,294,967,295(与int可能相同,取决于编译器)

2. 在单片机编程中的典型用途

2.1 寄存器与位操作

单片机中的特殊功能寄存器、内存地址、标志位等都是非负的。使用 unsigned 可以避免符号扩展带来的意外。

c

// 错误示例:如果使用 signed char,右移可能带符号扩展
unsigned char reg = 0x80;
reg = reg >> 1;  // 结果为 0x40,符合预期

如果用 signed char 且值为 0x80(即 -128),右移时某些编译器会进行算术右移(保留符号位),结果变成 0xC0,导致错误。

2.2 循环变量与数组索引

数组下标、循环计数器通常是非负的,使用 unsigned 可以表达意图,并在某些情况下让编译器生成更高效的代码。

c

for (unsigned int i = 0; i < 10; i++) {
    // ...
}

2.3 内存地址与指针

指针的数值(地址)本质上也是无符号整数,虽然C语言中指针类型本身不区分符号,但若要对地址进行算术运算,将其转为 unsigned 类型可以避免符号扩展问题。

c

uint32_t addr = (uint32_t)&some_variable;

2.4 通信协议与数据缓冲

串口、SPI、I2C 等通信中传输的原始字节(0~255)应使用 unsigned charuint8_t 存储,避免因符号位导致数据解释错误。


3. 使用 unsigned 时的常见陷阱

3.1 与有符号数混合运算

当有符号数与无符号数混合运算时,C语言会进行隐式类型转换,将有符号数转为无符号数,可能导致意想不到的结果。

c

int a = -1;
unsigned int b = 1;
if (a < b) {
    // 这个条件可能为假!
    // 因为 -1 被转换为 0xFFFFFFFF(很大的无符号数),大于 1
}

解决方法:尽量避免混用,或显式强制类型转换。

3.2 循环的下溢问题

如果循环变量是 unsigned,注意循环结束条件不要依赖等于0后继续递减。

c

for (unsigned int i = 10; i >= 0; i--) {  // 死循环!
    // i >= 0 永远为真,因为 i 是无符号,减到 0 后再减变成最大值
}

应改为:

c

for (unsigned int i = 10; i > 0; i--) {
    // 或者使用 do-while
}

3.3 右移操作

对于 unsigned 类型,右移是逻辑右移(高位补0),这是符合预期的。对于有符号负数,右移是实现定义的(通常为算术右移,高位补1),容易出错。


4. 单片机编程中的类型别名

在嵌入式开发中,通常不直接使用 unsigned int,而是使用标准固定宽度类型(在 <stdint.h> 中定义),以提高可移植性:

类型别名 实际类型 说明
uint8_t unsigned char 8位无符号整数
uint16_t unsigned short 16位无符号整数
uint32_t unsigned int / unsigned long 32位无符号整数
uint64_t unsigned long long 64位无符号整数

这些类型在操作寄存器、内存映射时能明确宽度,避免因不同编译器下 int 大小不同带来的问题。


5. 总结

  • unsigned 表示变量只能存储非负整数,在单片机编程中广泛用于表示寄存器值、地址、长度、标志位、原始数据等。
  • 使用 unsigned 可以避免符号扩展错误,并且让代码意图更清晰。
  • 需要注意与有符号数混用时的隐式转换,以及循环边界的处理。
  • 推荐使用 stdint.h 中的 uint8_tuint32_t 等类型替代裸 unsigned 关键字,以获得更好的可移植性和明确性。

xdata 是一个存储类型关键字

1. 8051 单片机的存储器结构

8051 核心采用 哈佛架构,程序和数据存储器独立编址,并且内部数据存储器空间非常有限。它分为几个不同的区域:

存储区域 关键字 地址范围 访问方式 特点
内部数据存储器 data 0x00~0x7F (128B) 直接寻址 访问速度最快,但空间极小
内部数据存储器(间接访问) idata 0x00~0xFF (256B) 间接寻址 包含 data 区域和高 128 字节(仅 8052 系列有)
位寻址区 bdata 0x20~0x2F (16B) 位寻址 可进行位操作,用于布尔变量
外部数据存储器 xdata 0x0000~0xFFFF (64KB) 通过 DPTR 间接访问 空间大,但访问速度慢
分页外部数据存储器 pdata 一页 256B 通过 R0/R1 间接访问 介于 dataxdata 之间
程序存储器 code 0x0000~0xFFFF (64KB) 只读 存放代码和常量

关键点:8051 的内部 RAM 只有 128 或 256 字节,但通过外部扩展(如外挂 RAM 芯片)或内部集成的大容量 RAM,可以使用 xdata 区域来存放大量数据。


2. xdata 的作用

  • 扩展内存:当内部 RAM 不够用时,将变量放到 xdata 区。例如,一个 1KB 的缓冲区、大量数组、通信数据包等。
  • 访问外部器件:某些外设(如 LCD、外部存储器)被映射到 xdata 地址空间,可以通过 xdata 指针直接访问。
  • 编译器优化:使用 xdata 关键字后,编译器会生成相应的 MOVX 指令(访问外部数据存储器的指令),而不是 MOV 指令(访问内部 RAM)。

3. 使用示例

c

unsigned char xdata buffer[1024];   // 1KB 的缓冲区,放在外部 RAM
unsigned int xdata counter;         // 计数器变量

也可以配合指针使用:

c

unsigned char xdata *ptr;           // 指向外部 RAM 的指针
ptr = 0x2000;                       // 指向外部 RAM 地址 0x2000
*ptr = 0x55;                        // 写入数据

4. 不同存储类型的性能比较

类型 速度 空间 适用场景
data 最快 最少(128B) 频繁访问的全局变量、中断中用到的变量
idata 较快 256B data 略慢,但空间稍大,用于大型局部变量
bdata 最快 16B 需要位操作的标志位
pdata 中等 256B(分页) 批量数据,但访问比 xdata 快一点
xdata 最慢 64KB 大数据缓存、数组、结构体
code 只读 64KB 常量字符串、查找表

速度差异原因

  • data / idata 使用 MOV 指令,单周期或双周期。
  • xdata 使用 MOVX 指令,需要 2~3 个指令周期,且需要通过 DPTR 间接寻址,速度较慢。

5. 在现代单片机中的类比

如果你使用的是 ARM Cortex-M 系列(如 STM32),所有内存(内部 SRAM、外部 SDRAM)是统一编址的,不需要 xdata 这样的关键字。你只需要通过链接脚本将变量分配到不同的内存段即可,例如:

c

uint8_t buffer[1024] __attribute__((section(".external_ram")));

或者使用 __attribute__((at(0x68000000))) 指定绝对地址。但在 8051 这类古老架构中,xdata 依然是常见的关键字。


6. 注意事项

  • 初始化问题xdata 区域的变量在启动时不会自动清零(除非编译器提供了额外的初始化代码)。如果需要清零,需手动处理。
  • 并发访问:如果中断和主程序都访问同一个 xdata 变量,要注意原子性,因为访问 xdata 可能需要多条指令(例如通过 DPTR),可能导致数据不一致。
  • 指针类型匹配xdata 指针与 data 指针不能随意混用。例如,将 data 变量的地址赋给 xdata 指针可能会导致访问错误。
  • 编译器支持xdata 是 Keil C51 等特定编译器扩展的关键字,不是标准 C。在其他平台编译时可能会报错。

7. 总结

  • xdata 是 8051 单片机 C 语言中用于将变量分配到外部数据存储器的关键字。
  • 它解决了 8051 内部 RAM 过小的问题,允许使用高达 64KB 的 RAM 空间。
  • 访问速度较慢,适合存放不频繁访问或占用空间大的数据。
  • 在现代单片机(如 ARM)中,内存统一编址,通常通过链接脚本或属性指定位置,不再需要 xdata

dataxdata 是 8051 单片机 C 语言中两个重要的存储类型关键字,它们的主要区别在于存储位置访问速度使用场景。下面从几个方面对比:

对比项 data xdata
存储区域 内部数据存储器(内部 RAM) 外部数据存储器(外部 RAM)
地址范围 0x00~0x7F(标准 8051),共 128 字节 0x0000~0xFFFF(64KB)
访问方式 直接寻址(MOV 指令) 间接寻址,通过 DPTR 或 R0/R1(MOVX 指令)
访问速度 最快(1~2 个指令周期) 较慢(2~3 个指令周期,且需要加载 DPTR)
空间大小 很小(128B),部分高端芯片有 256B 很大(可达 64KB)
适用场景 频繁使用的全局变量、中断变量、实时性要求高的数据 大数组、缓冲区、不频繁访问的变量、外设映射区域
初始化 启动时通常自动清零(取决于编译器) 启动时一般不会自动清零,需手动初始化
编译器关键字 data(默认省略时通常也是 data) xdata

详细说明

  1. 访问速度
    data 变量直接位于 CPU 的内部 RAM,访问时使用 MOV 指令,单周期或双周期完成。
    xdata 变量位于外部 RAM,需要通过 DPTR 先加载地址,再使用 MOVX 指令读写,速度慢得多。在性能敏感场合(如中断服务程序、循环内频繁访问的变量)应优先使用 data

  2. 空间限制
    标准 8051 内部 RAM 只有 128 字节(data 区),即使 8052 扩展到 256 字节(idata),对于复杂应用仍然捉襟见肘。
    xdata 提供最多 64KB 的空间,适合存放大量数据(如 LCD 显存、通信缓冲、大型数组)。

  3. 地址映射
    某些外设(如 LCD 控制器、外部 EEPROM)通过硬件映射到 xdata 地址空间,此时必须用 xdata 指针访问。
    data 区域专用于内部 RAM,不能直接访问外设。

  4. 编译器处理
    在 Keil C51 中,不指定存储类型的变量默认放在 data 区(如果空间不足会报错)。使用 xdata 关键字后,编译器生成 MOVX 指令访问外部 RAM。

  5. 典型代码示例
    c

    unsigned char data flag;           // 放在内部 RAM,快速访问
    unsigned int xdata buffer[512];    // 放在外部 RAM,节省内部空间
    

实际编程建议

  • 关键变量用 data:中断标志、循环计数器、频繁访问的状态变量应放在 data 区。
  • 大数据用 xdata:数组、结构体、串口接收缓冲区等占用空间大的变量放 xdata
  • 注意指针类型data 指针和 xdata 指针不能混用,指向 xdata 的指针必须声明为 unsigned char xdata *
  • 启动初始化xdata 变量不会自动清零,如需初始值,应在 main 开始处显式赋值或使用编译器扩展(如 Keil 的 init_xdata)。

总结

dataxdata 的核心差异是 速度换空间data 快但稀缺,适合核心数据;xdata 慢但充足,适合大容量存储。合理划分变量的存储区域,是 8051 单片机编程中优化性能和资源的关键技巧。


单片机引脚

1. 电源引脚

为单片机提供工作电压和参考地,是芯片正常工作的基础。

  • VCC / VDD:电源正极。不同型号电压不同,常见的有 5V、3.3V、1.8V 等。
  • GND / VSS:电源地(参考地)。
  • AVCC / AVDD(部分型号):模拟电源正极,单独为 ADC、比较器等模拟电路供电,以减少数字电路噪声干扰。
  • AGND:模拟地,通常与数字地通过磁珠或单点连接。

注意事项:电源引脚必须可靠连接,并就近放置去耦电容(如 0.1μF + 10μF),以滤除高频噪声,保证单片机稳定运行。


2. 外接晶体引脚

用于连接外部时钟源,为单片机提供系统时钟。

  • XTAL1(或 OSC_IN):晶体振荡器输入端。
  • XTAL2(或 OSC_OUT):晶体振荡器输出端。

常见用法

  • 外接石英晶体(如 8MHz、12MHz)和两个匹配电容,构成皮尔斯振荡器。
  • 也可直接输入外部时钟信号(通常接 XTAL1,XTAL2 悬空)。

内部时钟:许多现代单片机内部集成了 RC 振荡器(如 8MHz、32kHz),可以不外接晶体,但精度较低。


3. 控制和复位引脚

用于控制单片机的启动、复位、编程模式等特殊功能。

引脚名称 常见功能 说明
RST / RESET 复位 通常低电平或高电平有效(视型号),复位后程序从头执行。
ALE 地址锁存允许 在 8051 等总线扩展型单片机中,用于锁存低 8 位地址。
PSEN 程序存储使能 读取外部程序存储器时输出选通信号(8051 系列)。
EA / VPP 外部访问允许/编程电压 高电平时访问内部程序存储器,低电平时访问外部程序存储器;部分型号兼作编程电压输入。
BOOT0 / BOOT1 启动模式选择 如 STM32 中,通过高低电平选择从 Flash、系统存储器或 SRAM 启动。
SWD / JTAG 调试接口 用于在线仿真、程序下载(如 SWDIO、SWCLK 等)。

注意:这些引脚在普通应用时通常需要接固定电平(如复位脚接上拉电阻或按键),不能悬空。


4. 输入输出引脚(GPIO 及复用功能)

这是单片机与外部世界交互的主要通道。每个 I/O 引脚通常可以配置为多种功能。

(1)通用输入输出(GPIO)

  • 输入模式:读取外部电平(高/低),可配置上拉、下拉、浮空、施密特触发等。
  • 输出模式:输出高电平或低电平,通常有推挽输出(强驱动)和开漏输出(需外部上拉)。
  • 模拟功能:当用作 ADC 输入、比较器输入时,引脚处于模拟模式,数字通路关闭。

(2)复用功能

大多数引脚除了作为 GPIO 外,还可复用作外设接口,例如:

  • 通信接口:UART(TX、RX)、SPI(SCK、MOSI、MISO)、I2C(SCL、SDA)、USB、CAN 等。
  • 定时器功能:PWM 输出、输入捕获(如 TIMx_CHx)。
  • 外部中断:用于响应外部事件的边沿触发(上升沿、下降沿、双边沿)。
  • 特殊功能:如晶振输入、调试接口、复位输入等。

设计要点

  • I/O 引脚的驱动能力有限(通常几毫安到几十毫安),驱动大负载(如继电器、电机)需加缓冲电路。
  • 5V 兼容问题:3.3V 单片机若引脚耐受 5V,可直接连接 5V 逻辑;否则需要电平转换。
  • 未使用的引脚建议设置为输出低电平或输入上拉,避免悬空引入噪声。

总结

单片机的引脚按照功能划分,各有其作用:

  • 电源引脚:保证供电稳定。
  • 晶体引脚:提供系统时钟。
  • 控制/复位引脚:控制运行状态、下载调试。
  • I/O 引脚:实现与外设的数据交换。
回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:14
  • 最近打卡:2026-03-27 00:08:07
已绑定手机

2

主题

21

回帖

86

积分

注册会员

积分
86
发表于 昨天 13:24 | 显示全部楼层

打卡第六集-I/O口的工作模式,STC8H8K64U的汇编语言程序设计,初步入门

汇编语言-伪指令

在汇编语言中,伪指令(Pseudo-instruction,也称伪操作)是一种特殊的指令。它不像机器指令那样由CPU直接执行,而是告诉汇编器(Assembler)如何对程序进行汇编的指令。

简单来说,伪指令是写给汇编器看的,而不是写给CPU看的。它用于定义数据、分配内存、控制程序结构、定义宏等,最终会被汇编器转换成相应的机器码数据或影响地址的分配,但不会在程序运行时直接对应一条CPU指令。


一、 伪指令与机器指令的区别

特性 机器指令 伪指令
对象 CPU 汇编器
作用 控制CPU进行运算、数据传输、跳转等 告诉汇编器如何组织程序、定义数据、分配内存
执行 程序运行时由CPU执行 汇编阶段由汇编器处理,不产生直接的机器码(除非定义了数据)
例子 MOV AX, BX DB, DW, SEGMENT, END, EQU

二、 常见的伪指令分类

不同的汇编器(如 MASM、TASM、NASM)语法略有不同,但核心功能类似。以下以经典的 MASM(Microsoft Macro Assembler)为例:

1. 数据定义伪指令

用于定义变量和申请内存空间,并可以给内存赋初值。

  • DB —— Define Byte,定义字节(8位)。
  • DW —— Define Word,定义字(16位)。
  • DD —— Define Doubleword,定义双字(32位)。
  • DQ —— Define Quadword,定义四字(64位)。
  • DT —— Define Ten Bytes,定义10字节(常用于BCD码)。

示例:

assembly

DATA SEGMENT
    var1 DB 12h          ; 定义一个字节,值为0x12
    var2 DW 1234h        ; 定义一个16位字,值为0x1234
    str  DB 'Hello', 0   ; 定义字符串并以0结尾
    arr  DB 10 DUP(0)    ; 重复10次0,相当于申请10个字节的数组
DATA ENDS

2. 符号定义伪指令

用于给常量或表达式起一个名字,提高代码可读性。

  • EQU —— Equate,等值。定义符号常量,不允许重复定义。
  • = —— 类似EQU,但允许重复定义。
  • $ —— 当前位置计数器,表示当前汇编地址的偏移量。

示例:

assembly

COUNT EQU 100        ; 定义COUNT为100
MAX  =  200          ; 定义MAX为200
LEN  =  MAX - 10     ; 支持表达式

3. 段定义伪指令

用于划分代码段、数据段、堆栈段等。在分段结构的汇编程序中必不可少。

  • SEGMENT / ENDS —— 定义段的开始和结束。
  • ASSUME —— 告诉汇编器某个段寄存器指向哪个段。
  • ORG —— 指定当前段内起始偏移地址。

示例:

assembly

STACK SEGMENT STACK          ; 定义堆栈段
    DB 100 DUP(?)
STACK ENDS

DATA SEGMENT                 ; 定义数据段
    msg DB 'Hello$'
DATA ENDS

CODE SEGMENT                 ; 定义代码段
    ASSUME CS:CODE, DS:DATA
START:
    MOV AX, DATA
    MOV DS, AX
    ; ... 程序代码 ...
    MOV AH, 4CH
    INT 21H
CODE ENDS
END START                    ; 程序结束,并指定入口点为START

4. 过程定义伪指令

用于定义子程序(函数)。

  • PROC / ENDP —— 定义过程的开始和结束。

示例:

assembly

MyProc PROC
    ; 子程序代码
    RET
MyProc ENDP

5. 汇编控制伪指令

用于控制汇编器的工作流程。

  • END —— 结束汇编,通常放在程序最后。
  • INCLUDE —— 包含外部文件。
  • ORG —— 设置地址计数器(常用于引导扇区等底层开发)。

三、 特别概念:伪指令与宏指令

有时伪指令容易和宏指令混淆:

  • 伪指令:由汇编器内置支持,用于环境设置和内存管理。
  • 宏指令:由程序员定义,将一组常用指令封装成一个新的“指令”,在汇编时展开。

四、 不同汇编器的差异

虽然伪指令的概念通用,但不同汇编器的语法差异较大:

  1. MASM / TASM (Intel语法):用于DOS/Windows开发,语法严谨,分段明显,常见于《汇编语言》教材(如王爽老师的书)。
  2. NASM:开源跨平台,语法简洁,在Linux和Windows内核开发中常见,使用 SECTION 替代 SEGMENT,默认没有 ASSUME
  3. GAS (GNU Assembler):AT&T语法,常用于Linux下的GCC后端,伪指令通常以点 . 开头,如 .section .text, .byte, .long

总结:
伪指令是汇编语言中用于指导汇编过程的特殊指令。它们不参与CPU运行时逻辑,但却是构建完整、可维护的汇编程序必不可少的基础。无论使用哪种汇编器,理解数据定义、段划分和符号定义这些核心伪指令,都是写好汇编代码的第一步。

回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:14
  • 最近打卡:2026-03-27 00:08:07
已绑定手机

2

主题

21

回帖

86

积分

注册会员

积分
86
发表于 昨天 17:45 | 显示全部楼层

打卡第七集-STC8H8K64U的汇编语言程序设计进阶,宏汇编

汇编语言-操作码操作数

一、 操作码(Opcode)

操作码 告诉 CPU 要做什么(执行什么操作)。

  • 它是指令的核心,对应于 CPU 内部的某条机器指令。
  • 例如:MOV(传送)、ADD(加法)、JMP(跳转)、CALL(调用)等。

在汇编代码中,操作码通常是一个助记符(mnemonic),方便程序员记忆。汇编器会把它翻译成对应的机器码(一个或几个字节)。


二、 操作数(Operand)

操作数 告诉 CPU 对什么数据执行操作,或者数据在哪里

  • 操作数可以是立即数(具体的数值)、寄存器(CPU内部寄存器)、内存地址 等。
  • 大多数指令有 1~2 个操作数,也有些指令没有操作数(如 NOPRET)。

常见操作数类型(以 80x86 为例):

  • 立即数:直接给出的数值,如 MOV AX, 1234h 中的 1234h
  • 寄存器:如 MOV AX, BX 中的 AXBX
  • 内存地址:如 MOV AX, [1000h] 中的 [1000h],表示取内存单元的内容。

三、 指令格式示例

text

操作码    操作数1, 操作数2
  • 双操作数指令MOV AX, BX
    • 操作码:MOV
    • 操作数1:AX(目的操作数)
    • 操作数2:BX(源操作数)
      含义:将 BX 的值传送到 AX
  • 单操作数指令INC CX
    • 操作码:INC
    • 操作数:CX
      含义:将 CX 的值加 1。
  • 无操作数指令NOP
    • 操作码:NOP
    • 含义:空操作,什么也不做。

四、 操作数的方向与约定

在 Intel 格式的汇编(如 MASM、TASM、NASM)中,通常约定:

  • 第一个操作数是目的操作数(dest),第二个操作数是源操作数(src)。
  • 例如 MOV DEST, SRC 表示将源操作数的值传送给目的操作数。

在 AT&T 格式(GAS)中,顺序相反:MOV SRC, DEST


五、 与伪指令的区别

  • 操作码 + 操作数 构成的是 机器指令,会被 CPU 执行。
  • 之前提到的 伪指令(如 DB, EQU, SEGMENT)不属于操作码,它们不生成 CPU 执行的机器码,只用来指导汇编器如何组织程序。

六、 举例:一段汇编代码中的操作码与操作数

assembly

MOV  AX, 1234h    ; 操作码: MOV, 操作数: AX, 1234h
ADD  AX, BX       ; 操作码: ADD, 操作数: AX, BX
CMP  AX, 10       ; 操作码: CMP, 操作数: AX, 10
JZ   label        ; 操作码: JZ,  操作数: label(地址标号)

总结
在汇编语言中,操作码 指明操作类型,操作数 指明操作所涉及的数据或位置。两者结合,形成一条完整的 CPU 可执行的指令。理解操作码和操作数,是阅读和编写汇编代码的基础。


寻址方式

1. 立即寻址

操作数直接写在指令中,与操作码一起存放在程序存储器中。

  • 特点:数据是常数,执行速度快,但只能用于源操作数。

  • 符号# 号后跟数据。

  • 示例
    assembly

    MOV A, #30H   ; 将立即数 0x30 送入累加器 A
    MOV DPTR, #2000H ; 将立即数 0x2000 送入数据指针
    

2. 直接寻址

指令中给出操作数的直接地址,CPU 根据这个地址到存储器中取数。

  • 特点:主要用于访问内部 RAM(00H-7FH)和特殊功能寄存器(SFR)(80H-FFH)。

  • 示例
    assembly

    MOV A, 50H    ; 将内部 RAM 中地址 50H 单元的内容送入 A
    MOV P1, #00H  ; 实际上 P1 是 SFR,地址为 90H,这也属于直接寻址
    

3. 寄存器寻址

操作数存放在工作寄存器(R0-R7)中。

  • 特点:指令代码短,执行速度快。当前选中的工作寄存器组(通过 PSW 的 RS0、RS1 选择)决定了具体的物理地址。

  • 示例
    assembly

    MOV A, R0     ; 将 R0 寄存器中的内容送入 A
    ADD A, R3     ; 将 A 与 R3 相加,结果存回 A
    

4. 寄存器间接寻址

指令中存放的是寄存器的编号,该寄存器中存放的是操作数的地址

  • 特点:非常适合处理数组或循环操作。通过地址指针(R0、R1 或 DPTR)来访问数据。

  • 符号@ 表示间接。

  • 示例
    assembly

    MOV A, @R0    ; R0 中存放了地址(如 40H),该指令将地址 40H 中的内容送入 A
    MOVX A, @DPTR ; 访问外部 RAM,地址由 DPTR 指定
    

5. 变址寻址

以程序计数器(PC)或数据指针(DPTR)作为基址寄存器,累加器 A 作为变址寄存器,两者相加形成操作数的地址。

  • 特点:主要用于查表操作(读取程序存储器 ROM 中的数据,即常数表)。

  • 指令MOVC A, @A+DPTRMOVC A, @A+PC

  • 示例
    assembly

    MOV DPTR, #TABLE ; 设置表首地址
    MOV A, #02H      ; 查第 2 项
    MOVC A, @A+DPTR  ; 取出 TABLE+2 地址处的数据送入 A
    

6. 相对寻址

主要用于程序分支(跳转指令)。它以 PC 的当前值为基址,加上指令中给出的相对偏移量(rel)得到新的跳转地址。

  • 特点:用于实现条件转移(如 JZCJNE 等)。

  • 示例
    assembly

    SJMP LOOP    ; 这是一个相对跳转,偏移量由编译器计算
    

7. 位寻址

MCS-51 是“位处理机”的典型代表,它可以对某些 RAM 单元和 SFR 中的**单个位(bit)**进行独立的读写操作。

  • 特点:操作对象不是字节,而是位。位地址范围 00H-7FH(对应字节地址 20H-2FH)以及 SFR 中能被 8 整除的地址。

  • 示例
    assembly

    SETB P1.0    ; 将 P1 口的第 0 位设置为高电平
    CLR C        ; 清除进位标志位(PSW.7)
    MOV C, 20H   ; 将位地址 20H 的值送入进位标志位
    

补充说明:不同单片机的差异

如果你使用的是 STM32 等 32 位 ARM 单片机,寻址方式在概念上类似,但通常不再像 51 那样细分,而是统称为:

  • 立即寻址MOV R0, #0x1234
  • 寄存器寻址ADD R0, R1
  • 寄存器间接/基址加偏移LDR R0, [R1, #0x04]):这是 ARM 最常用的方式,支持前变址、后变址等复杂模式,用于访问堆栈或结构体。

总结:对于初学者来说,立即寻址(给常数)和寄存器寻址(最快)是最常用的;如果需要操作数组或缓冲区,就要用到寄存器间接寻址;而如果要控制引脚的高低电平,就需要用位寻址

回复

使用道具 举报 送花

  • 打卡等级:偶尔看看I
  • 打卡总天数:14
  • 最近打卡:2026-03-27 00:08:07
已绑定手机

2

主题

21

回帖

86

积分

注册会员

积分
86
发表于 昨天 21:07 | 显示全部楼层

打卡第八集-汇编指令一(数据传送/逻辑运算/算术运算)

一、 数据传送类指令

作用:在寄存器、内存、I/O 端口之间复制数据。
特点:不改变数据本身,只改变位置。

指令 功能 示例
MOV 传送数据 MOV AX, BX ;BX → AX
MOV [1000H], AL ;AL → 内存地址 1000H
XCHG 交换数据 XCHG AX, BX ;AX 与 BX 互换
PUSH 压栈 PUSH AX ;AX 内容压入堆栈
POP 出栈 POP BX ;从堆栈弹出数据到 BX
LEA 取有效地址 LEA BX, [SI+10] ;将 SI+10 的偏移地址送入 BX
IN/OUT I/O 端口传送 IN AL, 80H ;从端口 80H 读入一个字节到 AL

二、 算术运算类指令

作用:执行加、减、乘、除等算术运算,结果通常影响标志位(ZF、CF、OF 等)。

指令 功能 示例
ADD 加法 ADD AX, BX ;AX = AX + BX
ADC 带进位加法 ADC AX, BX ;AX = AX + BX + CF
SUB 减法 SUB AX, BX ;AX = AX - BX
SBB 带借位减法 SBB AX, BX ;AX = AX - BX - CF
INC 加 1 INC CX ;CX = CX + 1
DEC 减 1 DEC CX ;CX = CX - 1
MUL 无符号乘 MUL BL ;AX = AL * BL(8位)
DIV 无符号除 DIV BL ;AX / BL,商在 AL,余数在 AH
IMUL / IDIV 有符号乘/除
NEG 取补(求相反数) NEG AX ;AX = -AX

三、 逻辑操作类指令

作用:按位进行逻辑运算(与、或、非、异或等),常用于位操作、清零、置位、屏蔽等。

指令 功能 示例
AND 按位与 AND AL, 0FH ;保留低 4 位,高 4 位清零
OR 按位或 OR AL, 80H ;将最高位置 1
XOR 按位异或 XOR AX, AX ;将 AX 清零(常用技巧)
NOT 按位取反 NOT AL ;AL 每一位取反
TEST 测试(与 AND 相同但不保存结果,只影响标志位) TEST AL, 01H ;测试最低位是否为 1
SHL / SAL 逻辑左移 / 算术左移 SHL AX, 1 ;左移 1 位,低位补 0
SHR 逻辑右移 SHR AX, 1 ;右移 1 位,高位补 0
SAR 算术右移 SAR AX, 1 ;右移 1 位,高位保持原符号
ROL / ROR 循环左移 / 循环右移

四、 总结对比

类别 核心作用 典型指令 影响标志位
数据传送 复制数据 MOV, XCHG, PUSH, POP 通常不影响
算术运算 加减乘除 ADD, SUB, MUL, DIV 影响 OF, SF, ZF, CF 等
逻辑操作 按位运算 AND, OR, XOR, SHL, SHR 影响 ZF, SF, PF, CF 等

这三类指令是汇编程序的基础,配合控制转移类指令(如 JMP、CALL、LOOP 等)和处理器控制类指令,就能完成任何计算和控制任务。

回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-3-27 01:35 , Processed in 0.125461 second(s), 89 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表