MDK简介
MDK(Microcontroller Development Kit)是由 ARM 公司开发的一款综合性的开发环境,专门用于嵌入式系统中的微控制器(MCU)开发。MDK 常常也被称为 Keil MDK,因为其前身是由 Keil 开发的产品。MDK 提供了一个完整的工具链,包括集成开发环境(IDE)、编译器、调试器和软件库等,支持 ARM Cortex-M 处理器系列的开发。
MDK安装 = MDK软件安装 + 器件支持包
MDK软件下载:https://www.keil.com/download/product/
器件支持包下载:https://www.keil.com/dd2/pack/
开发板光盘路径:A 盘\6,软件资料\1,软件\1,MDK5
最新版本查看
每个版本支持不同的器件和功能。
查看当前使用的版本号
MDK版本查看
USB接口和type-c接口传输USB电平标准,通过CH340C芯片将USB电平标准转换为TTL/COMS电平到开发板
安装CH340 USB虚拟串口驱动后,才能识别CH340C通信的协议。
部分编译和全局编译的区别。
全局编译是指重新编译整个项目的所有源文件,无论是否修改。
优点1.保证一致性,重新编译整个项目可以确保所有文件都是基于相同的代码版本生成的。2.避免依赖错误,不会因为部分文件未重新编译而导致依赖错误。
缺点1.编译时间长,重新编译整个项目可能需要较长的时间,特别是对于大型项目而言,会增加开发迭代周期。2.资源消耗大,需要占用更多的 CPU 和内存资源。
部分编译是指仅编译已修改的源文件以及与之相关联的依赖文件,而不重新编译整个项目。
优点1.快速编译。仅编译修改的文件,节省了编译时间,加快了开发迭代的速度。2.减少资源消耗。不必重新编译所有文件,减少了 CPU 和内存的占用。
缺点是可能导致依赖关系错误。如果修改的文件依赖于其他文件的更改,但这些文件未被重新编译,可能会导致依赖关系错误,需要手动进行整体编译或者清理后重新编译。
这个程序占用了FLASH的,5296+362+28 == 5652字节
占用SRAM,28+1900 == 1928字节
编译完生成的.hex文件
双击LED,打开.map文件,拉到最后面,也可以看到FLASH和SRAM的占用情况。
ATK-XISP.exe软件只支持下载到内部FLASH
程序内外部flash的保存
这个是默认没有勾选的,没有勾选的话,会默认将程序保存到内外部的flash
勾选的话则会将程序保存到内部的flash中。
第一种模式中,BOOT1下的X表示0/1都可以
第二种模式就是ISP下载
第三种启动模式用的少,一般是用来调试的。
ISP下载程序一般步骤:
1,BOOT0接高电平,BOOT1接低电平
2,按复位键
程序执行一般步骤:
1, BOOT0接低电平,BOOT1接任意
2,按复位键
一键下载电路,是利用串口的DTR和RTS信号,分别控制STM32的复位和BOOT0引脚,配合ATK-XISP.exe软件,设置:DTR低电平复位,RTS高电平进BootLoader,这样, BOOT0和STM32的复位引脚,完全由下载软件自动控制,从而实现一键下载。
左边use是软件仿真,右边use是硬件仿真
在setting中可以选择仿真接口
DAP仿真调试
当前内核的时钟设置
这里设置完后,可以使用DAP仿真调试,打断点,进行测试delay的精确度。
结束仿真报错解决方法 --- 原因:MDK5.23以后的版本对中文支持不友好
解决办法:
仿真结束前将所有断点清除将工程路径改浅,并改成全英文路径。(或者把工程拉到桌面)
Call Stack 窗口:查看函数调用关系&局部变量
Watch窗口:查看函数首地址&变量值
这里也可以查看在程序执行中,变量具体的值。
Watch窗口:设置全局变量在被读或写后自动停止运行
类似于断点的用途。
Memory窗口:内存查看窗口
这里需要注意的是:M3/M4/M7内核是小端模式,内存的值得倒着读
如,定义全局变量uint16_t temp[10] = {15,14,13};
那么打开memory窗口后搜索temp。
这里就需要在2个字节中倒着查看。
15在上图中是0F 00,我们倒着看则是0x000F。以此类推。
Peripheral窗口:查看寄存器的值
调试时,使用该功能可以确定配置寄存器是否有问题
了解寄存器具体的设置情况
内核的寄存器,从上向下顺序依次如下,
中断控制器。系统控制以及配置定时器。
System Tick Timer(SysTick)是一个定时器,用于生成系统节拍时钟中断,以便实现系统滴答功能。SysTick是ARM Cortex-M系列处理器中的一个标准外设,广泛用于操作系统的时间管理、任务调度等功能。
错误汇报。
仿真时要注意的点
仿真时,使用MDK的Level 0等级优化调试停止在断点处时,只是内核停止,外设会继续运行断点的设置要有时间观念,考虑是否会打断正常通信
如果没使用Level 0等级优化,可能会造成下面这种情况
变量已经正常使用了,但是会显示上图信息。
保存配置的文件查看
右键,打开文件所在位置。找到
Tab键实用快捷键
代码段整体左移4个空格:选中代码段 + Shift键 + TAB键
代码段整体右移4个空格:选中代码段 + TAB键
快速定位函数或变量被定义的地方
然后再次编译工程,这时就会发现编译速度变慢。
选中该函数或变量 + 鼠标右键 + 选择Go to Definition of “xxx”
快捷方式:选中该函数或变量 + F12
快速注释&快速取消注释
选中要注释的代码段 + 鼠标右键 + 选择Advanced à Comment Selection
快捷方式:选中要注释的代码段 +
要取消注释的代码段 + 鼠标右键 + 选择Advanced à Uncomment Selection
快捷方式:选中要取消注释的代码段 +
查找功能:
窗口视图管理
窗口视图恢复默认状态的方法:window --> Reset View to Defaults + Reset
stdint.h 是从 C99 中引进的一个标准 C 库的文件
路径:D:\MDK5.34\ARM\ARMCC\include
规范了定义格式。
带参数的宏定义
#define LED1(x) do{ x ? \
HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_RESET); \
}while(0)
建议使用 do{ ... }while(0) 来 构造宏定义
这样不会受到大括号、分号、运算符优先级等的影响,总是会按你期望的方式调用运行!
主要防止下面这种情况
if (!test)
LED1(1);
在hal库中使用了大量下面这种结构体的封装格式
typedef struct
{
uint32_t Pin ; /* 引脚号 */
uint32_t Mode ; /* 工作模式 */
uint32_t Pull ; /* 上下拉 */
uint32_t Speed ; /* IO速度 */
} GPIO_InitTypeDef;
摘自:stm32f1xx_hal_gpio.h
指针的复习
1.指针就是内存的地址
2.指针变量是保存了指针的变量
指针使用的2大最常见问题:
1,未分配(申请)内存就用
2,越界使用