第一集
看完第一集序言,我对 Ai8051U 的能力有了更具体的认识:它不仅能驱动显示屏、 实现录放音、支持手写输入,还能完成硬件乘除运算。这些功能让我意识到,单 片机的应用远比我想象的广泛,也让我这个刚入门的新手对后续的学习充满期待。 视频中老师通过简单的烧录操作,就让开发板实现了多个功能,操作过程清晰明了, 让我对硬件开发不再感到陌生。接下来,我打算跟着教程一步步实践,把每个外设都 亲自调试一遍,把基础打牢,再尝试做一些小作品,把学到的知识真正用起来。
第二集 通过本集学习,我对实验箱的硬件和软件进行了更深入的学习。这个嵌入式开发平台拥有丰富的硬件资源和 完善的开发工具,为单片机学习和项目实践提供了强大的支持。接下来,我将详细列举并分析部分核心硬件模块的功能及其应用场景: 1. USB Link 1D接口:这是一款高效的烧录调试工具,支持程序的快速下载和在线调试功能。配合Keil或IAR等开发环境使用,可以极大提升开发效率。
2. USB转双串口模块:该模块可用于各类串口通信实验,性能稳定可靠,能够完全替代市面上常见的CH340芯片方案,为通信实验提供便利。
3. 示波器BNC输入旁的红色调节器:这个精密的电位器用于实时调整输入信号的波形参数,在进行信号采集和分析实验时特别实用。
4. 立体线路输出接口:具备标准的音频输出端子,可直接连接音响设备,适用于音频处理和播放相关的实验项目。
5. 立体声耳机输出接口:除了线路输出外,还配备了3.5mm耳机接口,方便开发者进行音频效果的实时监听。
6. OLED显示屏:这块高对比度的显示屏功耗低、响应快,非常适合显示各类传感器数据或系统状态信息。
7. TFT彩色液晶屏:支持全彩显示,不仅可以呈现丰富的图形界面,还能播放动态画面,为交互式项目提供了视觉展示方案。
8. 掉电检测电压调节电路:这个功能模块允许用户设置电压检测阈值,当系统电压低于设定值时触发中断,使系统能在断电前 及时保存关键数据,确保数据安全。
9. 矩阵键盘:采用4x2的扫描矩阵设计,仅需8个IO口即可实现8个按键的输入检测,在节省IO资源的同时保持了良好的操作性。
10. ADC键盘:通过创新的模拟电路设计,仅需一个ADC引脚就能识别16个不同的按键输入,这大大简化了多按键系统的硬件设计。
11. QSPI/SPI FLASH存储器:提供高速的外部存储解决方案,既能保存大量数据,也支持与显示屏配合使用,实现数据的可视化展示。
12. LCD对比度调节电路:通过电位器可灵活调节显示屏的对比度,确保在各种光照条件下都能获得最佳的视觉效果。
第三集 一、Keil开发环境的学习与实践 在本单元的学习过程中,我对Keil集成开发环境(IDE)的基本操作和功能有了更深入的了解。通过学习手册,掌握了基本的代码格式调整技巧,包括但不限于缩进、代码对齐、注释规范等,使代码的可读性和规范性得到提升。此外,我还熟悉了Keil的工程管理、编译选项设置、调试工具使用等关键功能,为进一步的嵌入式开发打下基础。
二、GPIO控制LED的实验探索 1. GPIO工作模式的理解 在本实验中,我学习了如何通过配置GPIO(通用输入输出端口)的工作模式来控制外围设备。具体来说,通过在代码中设置 `P0M1`、`P0M0`、`P4M1`、`P4M0` 等寄存器,可以将P0和P4端口分别初始化为特定的工作模式(如推挽输出、开漏输出、高阻输入等)。这让我更加清晰地认识到寄存器配置在嵌入式硬件控制中的重要作用。
2. LED点亮的实现 在上机实践中,我运行了一个基本的LED点亮程序。核心逻辑如下: - 首先配置P0和P4为推挽输出模式(`PxM1=0x00, PxM0=0x00`)。 - 然后通过P00 = 0(拉低电平)来控制LED灯亮。 - 最后通过`while(1)`保持LED持续点亮状态。
这个过程让我理解了GPIO输出控制的底层原理,以及如何通过软件指令精确操控硬件设备。
三、代码编写与调试的经验 1. 代码规范化意识增强 在本实验中,我更加注意代码的规范性,比如: 寄存器初始化尽量放在`main()`函数开头。 使用注释清晰说明关键代码段的作用。 避免冗余代码,确保逻辑简洁明了。
2. 调试能力提升 在编译和烧录过程中,学习了一些常见的错误排查技巧,如: 检查Keil的编译警告信息,修正潜在的语法问题。 使用Keil的调试模式单步执行,观察GPIO状态是否符合预期。 若LED未亮,需检查硬件连接是否正确(如限流电阻、共阴/共阳接法等)。
四、学习心得与后续目标 本次实验不仅让我掌握了Keil的基本使用方法,也加深了对GPIO控制和寄存器配置的理解。更重要的是,我认识到嵌入式开发不仅仅是编写代码,更要结合硬件原理进行综合调试。
接下来的学习计划: 1. 进一步探索GPIO的其他工作模式(如开漏模式、高阻输入模式等)。 2. 学习如何结合定时器实现LED闪烁、呼吸灯等更复杂的效果。 3. 熟练掌握Keil的更多高级调试功能,提升开发效率。
通过本次实践,我对嵌入式系统的软硬件协同工作有了更直观的认识,这将为后续的深入学习奠定坚实基础。
第四集 一、学习成果概述 在本集的学习中,我在实际操作方面取得了显著的进步。按照学习手册的详细指导,我成功完成了基本的格式调整工作, 这为我后续的学习奠定了坚实的基础。这一过程不仅提升了我的动手能力,也让我对嵌入式开发的初步流程有了更直观的认识。 二、Keil软件的深入学习 通过本集内容,我对Keil软件有了更深入的了解,掌握了这款开发工具的一些特色功能和操作技巧。特别是在进行LED灯实验时, 我学习到了许多实用的编程注意事项,这些知识对我后续的学习和开发工作有着重要的指导意义。 (一)硬件初始化方法 在实验中,我学会了如何对硬件进行初始化。这是嵌入式开发中的一个重要步骤,确保硬件设备在程序运行前处于正确的状态。 例如,在点亮LED灯的实验中,我通过设置P0和P4端口的模式,为后续的LED控制做好了准备。 (二)I/O端口的工作模式设置 I/O端口的工作模式设置是控制硬件设备的关键。通过本集的学习,我掌握了如何根据需要设置端口的工作模式。在实验中,我 将P0和P4端口设置为推挽输出模式,这是点亮LED灯所必需的配置。 (三)无限循环的基本结构 在嵌入式程序中,无限循环是一种常见的结构,用于持续执行某些任务。通过本集的学习,我理解了无限循环的基本结构, 并在实验中应用了这一结构。在点亮LED灯的程序中,我使用了一个无限循环来持续点亮LED灯。 三、实验代码与分析 以下是我在本集实验中编写的点亮LED灯的代码: #include "ai8051u.h" void main(void) { // 设置P0、P4端口为推挽输出模式 P0M1 = 0x00; P0M0 = 0x00; P4M1 = 0x00; P4M0 = 0x00; // 初始化端口状态 P40 = 0; // 主程序循环 while(1) { P00 = 0; // 点亮LED } }
(一)端口模式的配置 在代码中,我通过设置P0M1、P0M0、P4M1和P4M0寄存器,将P0和P4端口设置为推挽输出模式。这是点亮LED灯的关键步骤, 因为只有正确配置端口模式,才能确保LED灯能够正常工作。 (二)嵌入式程序的基本结构 通过本集的学习,我理解了嵌入式程序的基本结构。在本实验中,我使用了一个无限循环来持续点亮LED灯。这种结构在嵌入式 开发中非常常见,用于实现持续的任务执行。 (三)51单片机的基本I/O操作方式 在实验中,我通过控制P00引脚的电平来点亮LED灯。这是51单片机基本I/O操作的一个典型示例。通过本集的学习,我掌握了 如何通过编程控制单片机的I/O引脚,从而实现对硬件设备的控制。 四、学习总结 通过本集的学习,我不仅成功完成了点亮LED灯的实验,还深入理解了端口模式的配置、嵌入式程序的基本结构以及51单片机的基 本I/O操作方式。这些知识为我后续更复杂的嵌入式开发打下了坚实的基础。我将继续努力,深入学习嵌入式开发的更多知识和技能, 不断提升自己的开发能力。 在学习过程中,我还通过手册对一些基本的格式进行了调整,并成功完成了相关操作。同时,我也通过观看视频,进一步了解了 Keil软件的格式和功能。通过这些学习,我不仅提升了编程能力,也对嵌入式开发有了更深入的认识。 第五集 (一)宏定义替换机制 1. 宏定义语法 通过`#define printf printf_hid`的语法,我理解了宏定义的替换规则。这种替换本质上是一种预处理阶段的文本替换 ,左边的标识符会被右边的文本完全取代。宏定义在C语言中非常有用,尤其是在需要重定向标准函数时。
#define printf printf_hid
- 替换规则:在预处理阶段,所有出现的`printf`都会被替换为`printf_hid`。 - 应用场景:在嵌入式开发中,标准的`printf`函数可能不适用,通过宏定义可以将其重定向到适合硬件的输出函数,如通过USB-CDC输出调试信息。 (二)`printf`函数的格式控制 1. 格式控制字符串 我详细学习了`fmt`参数的结构和功能,`fmt`是格式控制字符串,包含普通字符和转换说明。 - 普通字符:直接输出的文本内容。 - 转换说明:以`%`开头的特殊标记,用于格式化输出。 2. 关键格式说明符 我重点掌握了以下几个关键格式说明符: - 科学计数法表示: - `%e`或`%E`:以指数形式输出。 - 示例:`printf("%e", 1234.5678);` 输出 `1.234568e+03`。 - 智能选择输出格式: - `%g`或`%G`:自适应输出,根据数值的大小选择合适的格式。 - 示例:`printf("%g", 1234.5678);` 输出 `1234.57`。 - 指针地址输出: - `%p`:输出地址。 - 示例:`printf("%p", &variable);` 输出变量的地址。 - 特殊转义字符: - `\b`:退格符。 - `\ddd`:表示1-3个八进制的数字。 - `\a`:警告字符。 - `\f`:换页符。 (三)进制转换知识 1. 二进制 - 基于0和1的四位表示法(如`0000`、`0001`、`0011`等)。 - 示例:`0000`表示0,`0001`表示1,`0011`表示3。 2.八进制 - 0-7的数字系统(1-7及10-14等)。 - 示例:`1`表示1,`7`表示7,`10`表示8,`14`表示12。 3. 十六进制 - 0x前缀的16进制数(`0x1`、`0x2`等)。 - 示例:`0x1`表示1,`0x2`表示2,`0xA`表示10,`0xF`表示15。
第六集 一、GPIO核心概念与工作模式深度解析 1. GPIO本质理解 通用输入输出端口(General Purpose Input/Output)是现代微控制器的基本功能模块, 其本质是通过可编程引脚实现数字信号的输入检测与输出控制。每个GPIO引脚均可独立配置为 输入或输出模式,通过高低电平的变化实现与外部设备的交互。
2. 四种工作模式的工程特性 (1) 准双向口模式: 在传统8051架构中广泛使用,具备弱上拉特性,适用于大部分基础I/O应用场景
(2) 推挽输出模式: 提供强大的驱动能力,可同时输出较大的拉电流和灌电流,适合驱动LED等负载
(3) 高阻输入模式: 具有极高的输入阻抗,适用于模拟信号采集或总线通信等对信号完整性要求高的场景
(4) 开漏模式: 支持线与逻辑,是I2C、单总线等通信协议的标准配置模式
二、电气特性关键技术要点 1. 驱动能力指标 深入理解了拉电流(输出高电平时的供电能力)和灌电流(吸收外部电流的能力)的概念: - 不同工作模式下电流承载能力的差异 - 芯片手册中电气参数表的解读方法 - 实际工程中的负载匹配原则
2. 按键检测系统方案 掌握基于GPIO的按键检测完整技术链: - 硬件设计:上拉/下拉电阻的配置原则 - 软件处理:消抖算法的实现方法 - 状态检测:前沿/后沿触发的区别与应用
三、典型应用场景对比分析 1. 即时响应控制模式(任务1) 特点:输入输出保持同步变化 应用场景:需要实时跟随操作的场合,如测试按钮、紧急开关等
2. 反向逻辑控制模式(任务2) 特点:输入输出呈反相关系 应用场景:反相器电路、负逻辑系统设计
3. 状态切换控制模式(任务3) 特点:单次触发改变保持状态 关键技术点: - 状态变量的定义与使用 - 按键释放检测的重要性 - while循环在实际应用中的正确使用方法 典型应用:电子开关、模式切换按钮等
四、工程实践问题解决方案 1. 按键失效的排查思路 (1) 硬件层面: - 接触不良的检测方法 - 上拉电阻阻值的选择原则 - 电源稳定性的测量手段
(2) 软件层面: - 消抖时间的优化调整 - 状态机设计的关键要点 - 中断与轮询的选择策略
2. 性能优化方向 - 降低轮询频率的节能设计 - 多任务环境下的优先级管理 - 抗干扰措施的实施方案
五、学习成果转化与进阶规划 1. 知识体系构建 通过三个典型任务的对比学习,建立了: - 从硬件连接到软件控制的完整认知 - 不同控制策略的适用性分析方法 - 调试方法论的初步框架
2. 后续学习方向 (1) 拓展应用: - 矩阵键盘的实现原理 - 编码器接口的设计方法 - 触摸感应技术的基础
(2) 深入原理: - GPIO内部电路结构分析 - 端口复用机制 - 低功耗模式下的I/O配置
本单元的学习不仅掌握了GPIO的基本使用方法,更重要的是建立了嵌入式I/O系统的完整知识架构。 通过典型任务的对比实践,培养了从多角度分析问题的能力,这种系统性思维将有效指导后续复杂外设的开发工作。 在实验过程中积累的调试经验,特别是关于按键失效问题的排查思路,对提升工程实践能力具有直接价值。
第七集 定时器的核心功能与特点 主要作用 1. 计时与定时控制 构建软件计时系统,实现精准的时间计量 支持周期性任务调度,使程序能每隔固定时间执行特定操作 2. 程序效率优化 替代传统的长时间delay函数 避免 CPU 在延时期间的资源浪费,显著提高程序运行效率和处理速度 3. 硬件结构 24 位定时器(由 8 位预分频器 + 13 位自动重装载计数器组成) 可通过配置实现灵活多样的定时需求 定时参数计算公式 1. 定时频率计算 plaintext 定时频率 = Sysclk(HZ) / [(TOMPS + 1) × (65536 - [TH0,TL1]) × T] 其中: Sysclk:系统时钟频率(单位:Hz) TOMPS:预分频系数 [TH0,TL1]:定时器高低位寄存器组合值 T:时钟周期相关系数 2. 定时时间计算 plaintext 定时时间 = [(TOMPS + 1) × (65536 - [TH0,TL1]) × T] / Sysclk(HZ) 3. 定时器寄存器值计算 plaintext [TH0,TL1] = 65536 - [Sysclk × 定时时间 / (T × (TMOPS + 1))] 乱码问题及解决方案 问题根源:8051 和 80251 芯片存在编码限制,无法正确处理包含 0xFD 编码的汉字 表现现象:程序中使用此类汉字会导致显示乱码 解决方法:使用\XFD进行特殊处理,避免编码冲突 函数的基本要素 1. 函数定义 包含返回值类型、函数名和入口参数 必须实现函数的具体功能 示例:int max(int a, int b) { return a > b ? a : b; } 2. 函数声明 用于告知编译器函数的接口信息 必须在头文件中或被调用之前声明 声明末尾必须加分号 示例:int max(int a, int b);
3. 函数调用 在需要使用函数的位置直接调用 格式:函数名 + 括号 + 分号 多参数之间用逗号分隔 示例:int result = max(5, 8);
实验1
- #include "config.h"
-
- void main(void)
- {
-
- SYS_Init();
- while (1)
- {
-
- printf_usb("Hello World !\r\n");
-
-
- }
- }
-
- void SYS_Init(void)
- {
- EnableAccessXFR();
- IAP_SetTimeBase();
-
- P0M0 = 0x00; P0M1 = 0x00;
- P1M0 = 0x00; P1M1 = 0x00;
- P2M0 = 0x00; P2M1 = 0x00;
- P3M0 = 0x00; P3M1 = 0x00;
- P4M0 = 0x00; P4M1 = 0x00;
- P5M0 = 0x00; P5M1 = 0x00;
- P6M0 = 0x00; P6M1 = 0x00;
- P7M0 = 0x00; P7M1 = 0x00;
-
- delay_ms(1);
- USBLIB_Init();
- delay_ms(1);
-
- EnableGlobalInt();
- }
-
- void delay_us(uint16_t us)
- {
- do
- {
- NOP(14);
- } while (--us);
- }
- void delay_ms(uint16_t ms)
- {
- uint16_t i;
-
- do
- {
- i = MAIN_Fosc / 10000;
- while (--i);
- } while (--ms);
- }
-
-
- void USBLIB_Init(void)
- {
- usb_init();
- USB_SetIntPriority(0);
- set_usb_ispcmd("@STCISP#");
-
- }
-
- void USBLIB_WaitConfiged(void)
- {
- while (DeviceState != DEVSTATE_CONFIGURED)
- WDT_Clear();
- }
-
- void USBLIB_OUT_Done(void)
- {
- if (bUsbOutReady)
- {
- USB_SendData(UsbOutBuffer, OutNumber);
-
- usb_OUT_done();
- }
- }
复制代码
实验2
- #include "config.h"
- void main(void)
- {
-
- SYS_Init();
-
- while (1)
- {
- USBLIB_OUT_Done();
- }
- }
-
-
- void SYS_Init(void)
- {
- EnableAccessXFR();
- IAP_SetTimeBase();
-
- P0M0 = 0x00; P0M1 = 0x00;
- P1M0 = 0x00; P1M1 = 0x00;
- P2M0 = 0x00; P2M1 = 0x00;
- P3M0 = 0x00; P3M1 = 0x00;
- P4M0 = 0x00; P4M1 = 0x00;
- P5M0 = 0x00; P5M1 = 0x00;
- P7M0 = 0x00; P7M1 = 0x00;
-
- delay_ms(1);
- USBLIB_Init();
- delay_ms(1);
-
-
-
- EnableGlobalInt();
- }
-
- void delay_us(uint16_t us)
- {
- do
- {
- NOP(14);
- } while (--us);
- }
-
-
-
- void delay_ms(uint16_t ms)
- {
- uint16_t i;
-
- do
- {
- i = MAIN_Fosc / 10000;
- while (--i);
- } while (--ms);
- }
-
- void USBLIB_Init(void)
- {
- usb_init();
- USB_SetIntPriority(0);
- set_usb_ispcmd("@STCISP#");
-
- }
-
-
- void USBLIB_WaitConfiged(void)
- {
- while (DeviceState != DEVSTATE_CONFIGURED)
- WDT_Clear();
- }
-
-
- void USBLIB_OUT_Done(void)
- {
- if (bUsbOutReady)
- {
-
- if (UsbOutBuffer[0] == 6)
- printf_usb("Hello World !\r\n");
- else if (UsbOutBuffer[0] == 7)
- printf_usb("China !\r\n");
- usb_OUT_done();
- }
- }
复制代码
实验3
- #include "config.h"
- void main(void)
- {
- SYS_Init();
- while (1)
- {
-
- }
- }
-
-
- void SYS_Init(void)
- {
- EnableAccessXFR();
- IAP_SetTimeBase();
-
- P0M0 = 0x00; P0M1 = 0x00;
- P1M0 = 0x00; P1M1 = 0x00;
- P2M0 = 0x00; P2M1 = 0x00;
- P3M0 = 0x00; P3M1 = 0x00;
- P4M0 = 0x00; P4M1 = 0x00;
- P5M0 = 0x00; P5M1 = 0x00;
- P6M0 = 0x00; P6M1 = 0x00;
- P7M0 = 0x00; P7M1 = 0x00;
-
- delay_ms(1);
- USBLIB_Init();
- delay_ms(1);
-
- EnableGlobalInt();
- }
- void delay_us(uint16_t us)
- {
- do
- {
- NOP(14);
- } while (--us);
- }
-
- void delay_ms(uint16_t ms)
- {
- uint16_t i;
-
- do
- {
- i = MAIN_Fosc / 10000;
- while (--i);
- } while (--ms);
- }
-
- void USBLIB_Init(void)
- {
- usb_init();
- USB_SetIntPriority(3);
- set_usb_OUT_callback(USBLIB_OUT_Callback);
- set_usb_ispcmd("@STCISP#");
-
- }
-
-
- void USBLIB_WaitConfiged(void)
- {
- while (DeviceState != DEVSTATE_CONFIGURED)
- WDT_Clear();
- }
-
- void USBLIB_OUT_Callback(void)
- {
- if (UsbOutBuffer[0] == 6)
- printf_usb("Hello World !\r\n");
- else if (UsbOutBuffer[0] == 7)
- printf_usb("China !\r\n");
- }
-
复制代码
|