最近准备面试一家公司,公司主要用8位机去做的,所以现在我来先了解一下51,我学习单片机是直接从STM32开始学的,最真实的感受就是太吃力了。

一、硬件基础差异

维度

C51(8051 系列)

STM32(ARM Cortex-M)

对编程的影响

位宽/架构

8 位,经典哈佛结构(程序/数据存储器分离)

32 位,改进哈佛 + 总线矩阵

C51 运算慢、内存小,必须手动管理存储区;STM32 接近“电脑式”编程

主频/性能

通常 12~24MHz,指令多周期

几十~几百 MHz,单周期指令

C51 适合简单控制,STM32 可跑复杂算法/RTOS

内存

RAM 几十~几百字节,Flash 几 KB

RAM/Flash 几十 KB~几 MB

C51 变量必须指定存储类型,否则溢出

外设

基础(GPIO、定时器、串口)

丰富(ADC/DAC、DMA、USB、CAN 等)

C51 直接操作寄存器;STM32 有 HAL 抽象层

二、开发环境与编译器差异

  • C51

    :只能用 Keil C51(uVision 老版本),严格的“方言 C”。不支持标准 C 的很多特性,必须用扩展关键字。

  • STM32

    :Keil MDK / STM32CubeIDE / IAR / GCC 都行,使用标准 C/C++,配合 STM32CubeMX + HAL/LL 库,代码更规范、可移植性强。

C51 存储类型修饰符

  • data:片内直接寻址 RAM(最快,128 字节)

  • idata:片内间接寻址 RAM(全 256 字节)

  • xdata:片外数据存储器(最常用外部扩展)

  • code:程序存储器(ROM/Flash,只读,常用于常量表)

  • bdata:可位寻址区(20H~2FH)

unsigned char data flag;     // 片内快速变量unsigned int xdata buffer[100];  // 外部 RAM 数组unsigned char code table[] = {1,2,3};  // 放在 Flash

四、特殊关键字对比

C51 有 19 个扩展关键字,STM32 几乎全用标准 C。

关键字

C51 作用

STM32 对应方式

示例(C51)

sfr

定义特殊功能寄存器(SFR)

直接用寄存器结构体或 HAL

sfr P1 = 0x90;

sbit

定义 SFR 的某一位(最常用!)

HAL_GPIO 或 BSRR 寄存器

sbit LED = P1^7;

bit

定义普通 1 位变量

bool / uint8_t

bit flag;

interrupt

定义中断服务函数

NVIC + 函数名固定

void isr() interrupt 1

using

指定寄存器组(0~3)

using 1

reentrant

可重入函数(支持递归/中断调用)

标准 C 支持

void func() reentrant

at

指定变量绝对地址

attribute

((at())) 或 linker

unsigned char xdata var _at_ 0x8000;

small/large/compact

内存模型(影响指针大小和代码效率)

small(默认)

// C51 点灯(超级简洁)sbit LED = P1^7;LED = 0;   // 亮灯(低电平有效)// STM32 点灯(HAL 风格)HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);

STM32 HAL → C51 完整重写

1. 点灯实验
#include <reg52.h>sbit LED = P1^0;          // STM32: LED_Pin = GPIO_PIN_0void main(void){    LED = 1;              // STM32: HAL_GPIO_WritePin(..., GPIO_PIN_SET);    while(1)    {        LED = 0;          // 亮灯(低电平有效)        // 简单延时(实际项目用定时器代替)        unsigned int i = 50000;         while(i--);               LED = 1;          // 灭灯        i = 50000;         while(i--);    }}
2. 按键实验(检测按键)

#include <reg52.h>sbit LED  = P1^0;sbit KEY  = P3^7;         // STM32: KEY_Pin = GPIO_PIN_7 (低电平按下)void Delay_ms(unsigned int ms)   // 简单软件延时(面试可改成定时器){    unsigned int i, j;    for(i = ms; i > 0; i--)        for(j = 120; j > 0; j--);}void main(void){    LED = 1;                  // 初始灭灯    while(1)    {        if(KEY == 0)          // STM32: if(HAL_GPIO_ReadPin(...) == GPIO_PIN_RESET)        {            Delay_ms(20);     // 消抖(STM32常用HAL_Delay)            if(KEY == 0)      // 再次确认            {                LED = ~LED;   // 翻转LED(STM32: HAL_GPIO_TogglePin)                while(KEY == 0);  // 松手检测(防止连击)            }        }    }}
3. 定时器实验
#include <reg52.h>sbit LED = P1^0;                  // STM32: LED_Pinunsigned char count = 0;          // 软件计数(实现500ms)// ================== STM32 HAL_TIM 等价中断服务函数 ==================void timer0_isr() interrupt 1     // interrupt 1 = 定时器0{    TH0 = 0x3C;                   // 重新装50ms初值(STM32: __HAL_TIM_SET_COUNTER)    TL0 = 0xB0;    count++;    if(count >= 10)               // 10次 × 50ms = 500ms    {        count = 0;        LED = ~LED;               // 翻转LED(STM32: HAL_GPIO_TogglePin)    }}void main(void){    // ================== STM32 MX_TIMx_Init 等价初始化 ==================    TMOD = 0x01;                  // 定时器0,方式1    TH0  = 0x3C;                  // 50ms初值    TL0  = 0xB0;    TR0 = 1;                      // 启动定时器(HAL_TIM_Base_Start)    ET0 = 1;                      // 允许定时器0中断    EA  = 1;                      // 开总中断(__enable_irq())    LED = 1;                      // 初始灭灯    while(1)    {        // 主循环可以空着,也可以放其他非阻塞任务(STM32 while(1)风格)    }}

感觉要寄了,

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐