STM32/51单片机编程入门(点亮LED)

一、 安装并熟悉Proteus 电路仿真软件,完成一个C51程序设计和仿真

1.Proteus的简介

Proteus软件是英国Lab Center Electronics公司出版的EDA工具软件。它不仅具有其它EDA工具软件的仿真功能,还能仿真单片机及外围器件。

1.1Proteus的功能:

原理布图

PCB自动或人工布线

SPICE电路仿真

1.2Proteus的特点:

革命性的特点:

互动的电路仿真

仿真处理器及其外围电路

2.Proteus的安装

安装步骤:

1.右键以管理员身份运行安装程序

2.选择安装路径,点击Next

3.点击Next

4.等待安装完成

5.点击Finish

汉化步骤:

1.找到汉化补丁文件

2.将文件移动到Proteus目录下

3.替换目标中文件

4.运行并打开软件,如图示

3.Proteus的工程创建

3.1点击新建工程,输入工程名并选择安装路径。

3.2选择“从选中的模板中创建原理图(DEFAULT)”。

3.3选择“不创建PCB布板设计”。

3.4选择实验所需的系列、Controller、编译器

3.5点击Finish,完成创建

4.配置仿真器件

4.1配置LED灯

4.2选择三个电阻并双击电阻调整电阻大小为50Ω(电阻默认为10kΩ,电流过小,LED灯可能不亮)

4.3完成接线,如下图所示

5.使用Keil5生成.hex文件

安装Keil5软件:略

5.1创建工程

(1)点击 Project → New uVision Project …

(2)工程命名

(3)选择AT89C51芯片

(4)点击“是”确认

5.2编写主程序main.c

(1)点击新建文件

(2)编写代码

  #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);
		}
	}

 (3)点击保存文件,并命名文件(文件名以.c结尾)

(4)右键点击 Source Group 1 ,再点击 Add Existing Files to Group “Source Group 1”…

(5)选中led.c 文件,并点击 Add 。

5.3生成.hex文件

(1)点击魔术棒

(2)在Output中勾选Creat HEX File

(3)点击编译按钮,进行编译,生成.hex文件

6.进行仿真

(1)返回Proteus软件的原理图,双击 AT89C51 芯片,选择Program File文件,选择led.hex文件。

 (2)点击开始按钮

(3)调试结果

51单片机流水灯仿真

二、安装mdk5软件和stm32包,熟悉mdk开发环境,完成一个stm32的简单的通过寄存器方式,用某一个GPIO端口点亮LED等程序。

1.STM32流水灯Keil编写

1.1创建工程

(1)点击 Project → New uVision Project …

(2)工程命名

(3)选择STM32F103C8芯片

(4)本实验在添加库文件窗口无需操作,取消即可

(6)下载startup_stm32f10x_md.s作为启动文件

ST公司提供了 3 个启动文件给我们,分别用于不同容量的 STM32 芯片,这三个文件是:
startup_stm32f10x_ld.s,

startup_stm32f10x_md.s,

startup_stm32f10x_hd.s
其中,ld.s 适用于小容量 产品;md.s 适用于中等容量产品;hd 适用于大容量产品;

容量是指 FLASH 的大小:

小容量:FLASH≤32K
中容量:64K≤FLASH≤128K
大容量:256K≤FLASH

(7)将startup_stm32f10x_md.s文件复制到目录下

(8)双击Source Group 1,选择改变文件类型为All files,选择startup_stm32f10x_md.s

(7)下载SYSTEM(寄存器版本)文件夹(此文件夹代码在STM32F10x的芯片上通用)

同时在工程文件夹下新建HARDWARE文件夹,储存代码

(8)右键Target 1,选择Manage Project Items,

(9)在Manage Project Ltems中创建并添加USER、SYSTEM、HARDWARE的组(Groups),并在SYSTEM中添加三个.c文件

在HARDWARE中添加led.c、led.h文件(Files)

(10)创建test.c文件,并将其放在USER组下

1.2修改目标设置

(1)点击魔术棒

(2)在Output中勾选Creat HEX File

(3)在C/C++中设置sys、delay、usart的i路径

1.3主要代码编写

(1)led.c

#include "led.h"
//初始化 PB1 PC4 PD8为输出口.并使能这三个口的时钟 
//LED IO 初始化
void LED_Init(void)
{
	RCC->APB2ENR|=1<<2; //使能 PORTA 时钟 
	RCC->APB2ENR|=1<<3; //使能 PORTB 时钟 
//	RCC->APB2ENR|=1<<4; //使能 PORTC 时钟
//	RCC->APB2ENR|=1<<5; //使能 PORTD 时钟	
	GPIOB->CRL&=0XFF0FFFFF; 
	GPIOB->CRL|=0X00300000;//PB.5 推挽输出 
	GPIOB->ODR|=1<<5; //PB.5 输出高 
	
	GPIOB->CRL&=0XFFFFFFF0; 
	GPIOB->CRL|=0X00000003;//PB.0 推挽输出 
	GPIOB->ODR|=1<<0; //PB.0 输出高
	
	GPIOA->CRL&=0XFFFFFF0F; 
	GPIOA->CRL|=0X00000030;//PA.1 推挽输出 
	GPIOA->ODR|=1<<1; //PA.1 输出高
}

(2)led.h

#ifndef __LED_H
#define __LED_H
#include "sys.h"
//LED 端口定义
#define LED0 PBout(5) // DS0
#define LED1 PBout(0) // DS1
#define LED2 PAout(1) // DS2
void LED_Init(void); //初始化 
#endif

(3)test.c

#include "sys.h"
#include "delay.h"
#include "led.h"
int main(void)
{ 
	Stm32_Clock_Init(9); //系统时钟设置
	delay_init(72); //延时初始化
	LED_Init(); //初始化与 LED 连接的硬件接口
	while(1)
	{
		LED0=0;
		LED1=1;
		LED2=1;
		delay_ms(1000);
		LED0=1;
		LED1=0;
		LED2=1;
		delay_ms(1000);
		LED0=1;
		LED1=1;
		LED2=0;
		delay_ms(1000);
	} 
}

1.4尝试编译

(1)出现错误

(2)右键Target,修改ARM Compiler为v5.06

(3)编译成功

2.Proteus仿真(具体步骤请参考C51程序仿真)

2.1Proteus仿真工程

2.2进行仿真

STM32流水灯仿真


3.硬件连接

3.1STM32F103C8与USB转TTL线连接

STM32F103开发板USB转TTL线
GNDGND
PA9RXD
PA10TXD
3V33V3

3.2 LED的电路连接

LED-REDLED-YELLOWLED-GREEN
电源正极电源正极电源正极
B5B0A1

4.烧录

4.1下载烧录软件FlyMcu或mcuisp并打开(以FlyMcu为例)

4.2设置烧录软件,并选择.hex文件

4.3完成烧录

注意:接线帽需如图接通

烧录顺利完成

5.LED流水灯实况

STM32流水灯实况

三、(理论概念-常见嵌入式岗位面试题) 通过以上实践,结合阅读
ARM、STM32技术手册,深入思考STM32F103系列芯片的地址映射和寄存器映射原理,GPIO端口的初始化设置的一般步骤。


1.寄存器简介

寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。寄存器是存储器层次结构中的顶端,也是系统操作数据的快速途径。通常,寄存器都是以寄存器数组的方式来实现的,也可以使用单独的触发器、高速的核心存储器、薄膜存储器以及在数种机器上的其他方式来实现。根据功能的不同,寄存器可分为基本寄存器和移位寄存器两大类。

2.地址映射和寄存器映射原理

2.1地址映射原理(也叫存储器映射,内存映射)

地址映射是将物理地址空间映射到虚拟地址空间的过程。CPU通过虚拟地址来访问内存和IO设备,而实际访问的是物理地址。地址映射由硬件电路实现,如MMU(内存管理单元),操作系统也利用此技术管理进程的虚拟地址空间。

存储器本身不具有地址信息,它的地址是由芯片厂商或用户分配,给存储器分配地址的过程就称为存储器映射。如果给存储器再分配一个地址就叫存储器重映射。

2.2寄存器映射原理

寄存器映射则是将CPU内部的寄存器映射到虚拟地址空间中的特定区域,以便程序通过读写这些虚拟地址来访问寄存器。一般情况下,通过绝对地址访问内存单元较为复杂,而通过寄存器的方式来实现更加便利。

STM32 的外设地址:

 3.GPIO功能介绍

GPIO(General-Purpose Input/Output)是通用输入输出引脚,它是许多微控制器和芯片组上的数字接口,可以被软件配置为输入或输出。

GPIO在连接外部设备时发挥重要作用,它们可以使用寄存器级操作进行配置和控制,因此具有灵活性和可编程性。在输入模式下,GPIO口接收外部设备产生的电信号,并将其转换为数字信号传递给处理器。在输出模式下,GPIO口将处理器输出的数字信号转换为电信号,并向外部设备发送。

GPIO还有多种工作模式,例如中断输入模式、定时器输入捕获模式、PWM输出模式、模拟输入模式等。

4.GPIO端口的初始化设置

3.1使能GPIO口的时钟:

通过RCC相关的寄存器设置相应的GPIO口时钟使能位。

3.2GPIO端口参数设置:

对GPIO端口的工作模式,端口输出数据寄存器的值进行设置;根据需求对端口的引脚速率进行设置。

5.程序编写

5.1对单个GPIO口的初始化:

使能GPIOA的时钟:

GPIO_InitTypeDef GPIO_InitStruct;                    //定义初始化结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //使能GPIOA时钟

设置工作模式、IO属性、初始化GPIO:

GPIO_InitStruct.GPIO_Mode    = GPIO_Mode_Out_PP;     //配置模式
GPIO_InitStruct.GPIO_Pin     = GPIO_Pin_0;           //配置哪个IO口
GPIO_InitStruct.GPIO_Speed   = GPIO_Speed_50MHz;     //配置IO口速度,仅输出有效
GPIO_Init(GPIOA,&GPIO_InitStruct);                   //初始化GPIOA的参数为以上结构体

5.2实例

使能GPIOA的时钟:

RCC->APB2ENR|=1<<2; //使能 PORTA 时钟 

设置工作模式:

	GPIOB->CRL&=0XFF0FFFFF; 
	GPIOB->CRL|=0X00300000;//PB.5 推挽输出 
	GPIOB->ODR|=1<<5; //PB.5 输出高 

5.回答:

(1)嵌入式C程序代码对内存(RAM)中的各变量的修改操作,与对外部设备(寄存器--->对应相关管脚)的操作有哪些相同与差别?

相同点:

  1. 语法:在C语言中,无论是对内存中的变量进行修改,还是对外部设备进行操作,使用的都是同样的赋值语句。
  2. 硬件:无论是操作内存还是操作外部设备,都需要对硬件有一定的了解。需要理解内存的地址范围,以及设备的寄存器的地址和功能。

不同点:

  1. 操作对象:操作内存主要是操作RAM中的变量,而操作外部设备主要是操作设备的寄存器,这些寄存器通常对应着相关的硬件管脚。
  2. 操作权限:在操作内存时,程序通常具有相对较大的权限,可以访问和修改大部分内存区域。但在操作外部设备时,由于硬件的限制和保护,程序可能只能访问和修改特定的寄存器。
  3. 速度:内存的访问速度通常比外部设备的访问速度快很多。这是因为内存的访问是电子的,而外部设备的访问可能涉及到硬件的电磁信号等复杂的过程。
  4. 并发性:在操作内存时,可能会涉及到多任务、多线程的并发问题。而在操作外部设备时,由于硬件的限制,可能不存在这样的问题。
  5. 错误处理:在操作内存时,如果出现错误(如越界访问),程序可能会崩溃或者产生不可预测的结果。而在操作外部设备时,如果出现错误(如向错误的寄存器写入数据),可能只会影响到特定的硬件的功能。

(2)为什么51单片机的LED点灯编程要比STM32的简单?

1.硬件电路简单:51单片机连接简单的LED电路,只需将LED的正极连接到单片机的某个I/O引脚,负极接地即可。这种简单的连接方式使得编程更加容易。而STM32可能需要更加复杂的电路,如使用GPIO引脚和电阻来控制LED。

2.寄存器配置简单:51单片机的寄存器较少,配置起来相对简单。而STM32具有更多的寄存器和外设,需要更多的配置工作来实现LED点灯。

四、(理论概念-常见嵌入式岗位面试题) 与PC平台上的一般程序不同,嵌入式C程序经常会看见 register和volatile 关键字,请解释这两个变量修饰符的作用,并用C代码示例进行说明。

1.register

register修饰符用于提示编译器,将变量存储在寄存器中,以加快访问速度。寄存器是CPU内部的一种存储设备,访问速度比内存快得多。使用register修饰符可以减少变量的内存访问时间,提高程序的执行效率。但是,实际上是否将变量存储在寄存器中是由编译器决定的,因为现代编译器通常能够自动进行优化。

register int i;  
for (i = 0; i < 10; i++) {  
    // 循环体  
}

2.volatile

volatile修饰符用于告诉编译器,该变量可能会被意外地修改,不要在编译优化时做出错误的假设。在嵌入式系统中,某些内存地址可能会被外部设备或硬件直接修改,而不是通过程序来修改。使用volatile修饰符可以确保编译器不会对这些可能被意外修改的变量进行优化,以确保程序的正确性。

volatile int shared_variable;  
// 某个外部设备或硬件可以直接修改shared_variable的值

五、总结

虽然51单片机的LED点灯编程相对简单,但它的功能和性能也相对较低。而STM32具有更强大的处理能力和外设,适用于更复杂的应用场景。

参考:

[1]

Proteus使用教程并仿真51程序——LED流水灯_proteus 51 仿真_网盘已清空,链接已失效的博客-优快云博客

[2]

1、Proteus仿真STM32流水灯实验例程、详细步骤。_proteus例程_学者-老栋的博客-优快云博客[

[3]

【嵌入式08】STM32F103C8T6寄存器方式借助面包板点亮LED流水灯详解_噗噗的罐子的博客-优快云博客

[4]​​​​​STM32 LED实验(寄存器方式和HAL库方式) - 知乎 (zhihu.com)

[5]

STM32寄存器的简介、地址查找,与直接操作寄存器_stm32 基地址在那个文件_yummy说电子的博客-优快云博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值