任务要求
1. 安装并熟悉Proteus 电路仿真软件,完成一个C51程序设计和仿真
2. 安装mdk5软件和stm32包,熟悉mdk开发环境,完成一个stm32的简单的通过寄存器方式,用某一个GPIO端口点亮LED等程序。安装过程、示例程序可以参考网上代码(注意:没有stm32开发板硬件之前,可只做程序的编译和仿真测试)
3. (理论概念-常见嵌入式岗位面试题) 通过以上实践,结合阅读ARM、STM32技术手册,深入思考STM32F103系列芯片的地址映射和寄存器映射原理,GPIO端口的初始化设置的一般步骤。回答:1)嵌入式C程序代码对内存(RAM)中的各变量的修改操作,与对外部设备(寄存器--->对应相关管脚)的操作有哪些相同与差别?2)为什么51单片机的LED点灯编程要比STM32的简单?
4. (理论概念-常见嵌入式岗位面试题) 与PC平台上的一般程序不同,嵌入式C程序经常会看见 register和volatile 关键字,请解释这两个变量修饰符的作用,并用C代码示例进行说明。
实验内容
任务1
完成一个C51程序设计和仿真
步骤1
安装Proteus
引用https://blog.youkuaiyun.com/ssj925319/article/details/108929227
下面来了解下如何安装Proteus软件,安装过程也十分简单。
首先需要下载Proteus的压缩包,链接如下。
链接:https://pan.baidu.com/s/1eURfI-nSSXHQfL1cgaSdKg
提取码:lse6
步骤2使用Proteus
创建工程
步骤3绘制原理图
步骤4编写51程序
//51单片机编程常用的头文件
#include <reg51.h>
#include <intrins.h>
//延迟函数
void delay_ms(int a)
{
int i,j;
for(i=0;i<a;i++)
{
for(j=0;j<1000;j++) _nop_();
}
}
void main(void)
{
while(1)
{
P0=0xfe;
delay_ms(50);
P0=0xfd;
delay_ms(50);
P0=0xfb;
delay_ms(50);
P0=0xf7;
delay_ms(50);
P0=0xef;
delay_ms(50);
P0=0xdf;
delay_ms(50);
P0=0xbf;
delay_ms(50);
P0=0x7f;
delay_ms(50);
}
}
步骤5将生成的hex文件加入protues仿真中去
步骤6仿真结果
任务2完成一个stm32的简单的通过寄存器方式,用某一个GPIO端口点亮LED
安装及使用参考教程
https://www.bilibili.com/video/BV1th411z7sn?p=4&vd_source=07ac35c902c946868feed868ebe4291d
步骤1安装keil并配置相关环境
步骤2初始化引脚
步骤3下载并测试
步骤4实验结果
任务3
1)嵌入式 C 程序代码对内存 (RAM) 中的各变量的修改操作,与对外部设备(寄存器--->对应相关管脚)的操作有以下相同与差别:
相同点:
a. 都是通过指令来完成,如数据传输指令、算术指令等。
b. 都需要考虑数据类型和数据宽度,如整型、浮点型等。
c. 都需要考虑访问权限,如只读、读写等。
差别:
a. 对内存中的变量操作,直接通过地址访问,而对外部设备操作需要通过寄存器间接访问。
b. 对内存中的变量操作,可以直接通过指针访问,而对外部设备操作通常需要通过特定的寄存器进行访问。
c. 对内存中的变量操作,通常不需要考虑时序问题,而对外部设备操作需要考虑时序,如读写操作的时序、锁存器等。
2)51 单片机的 LED 点灯编程比 STM32 的简单,主要原因有以下几点:
a. 51 单片机只有几个外部中断引脚,而 STM32 有丰富的外设引脚,如 USART、SPI、I2C 等,因此 STM32 的 GPIO 配置相对复杂。
b. 51 单片机的 GPIO 端口配置相对简单,通常只需配置方向寄存器和速度寄存器,而 STM32 的 GPIO 端口配置需要考虑更多的参数,如复用功能、时钟源等。
c. 51 单片机的 LED 驱动通常只需配置一个方向寄存器,即可实现点亮或熄灭,而 STM32 需要配置多个寄存器,如方向寄存器、速度寄存器、复用寄存器等。
d. 51 单片机的程序结构相对简单,而 STM32 的程序结构更复杂,需要处理更多的中断、任务等。
任务4
在嵌入式 C 程序中,register 和 volatile 是两个常用的变量修饰符,它们在 PC 平台上一般不常用。下面分别介绍这两个关键字的作用及使用示例:
- register 关键字:
register 关键字用于声明寄存器变量。在嵌入式系统中,由于存储空间有限,寄存器是一种较为常用的存储方式。使用 register 关键字可以告诉编译器该变量应该存储在寄存器中,而不是内存中。这样可以节省存储空间,同时提高程序的运行速度。
使用示例:
c复制代码
register int counter;
- volatile 关键字:
volatile 关键字用于声明易变(易被修改)的变量。在嵌入式系统中,有些变量的值可能会被其他程序或硬件设备实时修改,例如中断服务程序(ISR)或硬件设备驱动。使用 volatile 关键字可以确保编译器不会对这类变量进行优化,从而确保程序能够正确地读取到这些变量的最新值。
使用示例:
c复制代码
volatile int button_state;
这里是一个简单的嵌入式 C 程序,使用了 register 和 volatile 关键字:
c复制代码
#include <avr/io.h> #include <util/delay.h> register int counter = 0; volatile int button_state = 0; void isr_button_click() { button_state = 1; } int main() { DDRD |= (1 << PD2); // 设置 PD2 为输入 PORTD |= (1 << PD2); // 初始化 PD2 为高电平 while (1) { if (button_state) { counter++; _delay_ms(100); button_state = 0; } } }
在这个程序中,我们使用了 register 关键字声明了计数器变量 counter,使用 volatile 关键字声明了按键状态变量 button_state。计数器变量 counter 存储在寄存器中,以节省存储空间;按键状态变量 button_state 使用了 volatile 关键字,以确保在 ISR 中修改它的值时,主程序能够立即看到修改后的结果