stm32与51 Proteus仿真初体验之点灯大师

一、一些必要知识

CPU

CPU,全名Central Processing Unit(中央处理器)。这是一块超大规模的集成电路,包含上亿的晶体管,是一台计算机的运算核心(Core)和控制核心(ControlUnit)。它的功能主要是解释计算机指令以及处理计算机软件中的数据。
它的主要构成是:运算器、控制器、寄存器

存储器映射

存储器本身没有地址,给存储器分配地址的过程叫存储器映射,一般由芯片厂商或用户分配。

内存映射

CPU分出去的地址空间与外设的片内RAM连接,这样CPU就能像访问内存一样去访问外设的片内RAM(内存),这就是内存映射

寄存器与寄存器映射

在存储器的区域单元中,每个单元对应不同的功能,当我们控制这些单元时就可以驱动外设工作。我们可以找到每个单元的呢起始地址,然后通过语言指针的操作方式来访问这些单元,如果每次都是通过这种地址的方式来访问,不仅不好记忆,还容易出错,这是我们可以根据每个单元功能的不同,以功能为名给这个内存单元取一个别名,这个别名就存在寄存器中,这个给已经分配好地址的有特定功能的内存单元取别名的过程,就叫做寄存器映射

ROM (Read Only Memory)程序存储器

ROM全称Read Only Memory,顾名思义,它是一种只能读出事先所存的数据的固态半导体存储器。ROM中所存数据稳定,一旦存储数据就再也无法将之改变或者删除,断电后所存数据也不会消失。其结构简单,因而常用于存储各种固化程序和数据。

在单片机中用来存储程序数据及常量数据或变量数据,凡是c文件及h文件中所有代码、全局变量、局部变量、‘const’限定符定义的常量数据、startup.asm文件中的代码(类似ARM中的bootloader或者X86中的BIOS,一些低端的单片机是没有这个的)通通都存储在ROM中。

为了便于使用和大批量生产,进一步发展出了可编程只读存储器(PROM)、可擦除可编程只读存储器(EPROM)。EPROM需要用紫外线长时间照射才能擦除,使用很不方便。1980s又出现了电可擦除可编程只读存储器(EEPROM),它克服了EPROM的不足,但是集成度不高、价格较贵。于是又发展出了一种新型的存储单元结构同EPROM类似的快闪存储器(FLASH MEMORY)。FLASH集成度高、功耗低、体积小,又能在线快速擦除,因而获得了快速发展。
FLASH 存储器
Flash 存储器(FLASH EEPROM)又称闪存,快闪。它是EEPROM的一种。它结合了ROM和RAM的长处。不仅具备电子可擦除可编辑(EEPROM)的性能,还不会断电丢失数据同时可以快速读取数据。它于EEPROM的最大区别是,FLASH按扇区(block)操作,而EEPROM按照字节操作。FLASH的电路结构较简单,同样容量占芯片面积较小,成本自然比EEPROM低,因此适合用于做程序存储器。

RAM (Random Access Memory)随机访问存储器

RAM又称随机存取存储器(电脑的内存条),存储单元的内容可按照需要随机取出或存入,且存取的速度与存储单元的位置无关。这种存储器在断电时,将丢失其存储内容,所以主要用于存储短时间使用的程序。

它主要用来存储程序中用到的变量。凡是整个程序中,所用到的需要被改写的量(包括全局变量、局部变量、堆栈段等),都存储在RAM中。

二、单片机介绍与仿真点灯

单片机,英文 Micro Controller Unit 简称MCU
内部集成了CPU、RAM、ROM、定时器、中断系统、通讯接口等一系列电脑的常用硬件功能,算是一个袖珍版计算机。

51单片机

名称由来

51单片机是对所有兼容Intel8031指令系统的单片机的统称,这一系列的单片机的始祖是Intel的8031单片机,后来随着flash ROM技术的发展,8031单片机取得了长足的进展成为了应用最广泛的8bit单片机之一,他的代表型号就是ATMEL公司的AT89系列。

51单片机主要特性

51子系列单片机由CPU、数据存储器RAM、程序存储器ROM、特殊功能寄存器、4个I/O口、串行口、定时器/计数器、中断系统等多个功能部件组成。

(1)MCS-51单片机的内核:8051CPU,CPU的内部集成有运算器和控制器,运算器完成运算操作(包括数据运算、逻辑运算等),控制器完成取指令、对指令译码以及执行指令。

(2)MCS-51单片机的片内资源:中央处理器(CPU)、数据存储器(RAM)、程序存储器(ROM)、定时/计数器(ROM)、并行输入输出(I/O)口、全双工串行口、中断系统、时钟电路。

(3)中央处理器(CPU):是整个单片机的核心部件,是8位数据宽度的处理器,能处理8位二进制数据或代码,CPU负责控制、指挥和调度整个单元系统协调的工作,完成运算和控制输入输出功能等操作。

(4)数据存储器(RAM):8051内部有128字节数据存储器(RAM)和21个专用寄存器单元,它们是统一编址的,专用寄存器有专门的用途,通常用于存放控制指令数据,不能用作用户数据的存放,用户能使用的RAM只有128个字节,可存放读写的数据,运算的中间结果或用户定义的字型表。

(5)程序存储器(ROM):8051共有4K字节程序存储器(ROM),用于存放用户程序和数据表格。

(6)定时/计数器(ROM):8051有两个16位的可编程定时/计数器,以实现定时或计数,当定时/计数器产生溢出时,可用中断方式控制程序转向。

(7)并行输入输出(I/O)口:8051共有4个8位的并行I/O口(P0、P1、P2、P3),用于对外部数据的传输。

(8)全双工串行口:8051内置一个全双工异步串行通信口,用于与其它设备间的串行数据传送,该串行口既可以用作异步通信收发器,也可以当同步移位器使用。

(9)中断系统:8051具备较完善的中断功能,有五个中断源(两个外中断、两个定时/计数器中断和一个串行中断),可基本满足不同的控制要求,并具有2级的优先级别选择。

(10)时钟电路:仅有一个时钟,8051内置最高频率达12MHz的时钟电路,用于产生整个单片机运行的时序脉冲,但需外接晶体振荡器和振荡电容。

最小系统原理图以STC89C52为例子

在这里插入图片描述

  • 右上角三角箭头代表VCC电源正极,经过一个开关,再经过两个滤波电容(电源进来可能有干扰不稳定)类似先用一个大水池(C5)把输进来的水流接住,再平缓的输出
  • 左下角晶振,给一个确定的周期,驱动程序一步一步向后执行
  • 9号IO口复位电路给电容上电充电过程中相当于短路,把RST口电平拉高(RST高电平复位,低电平不复位),充满电后断路接地,低电平

组成

在这里插入图片描述

命名规则
在这里插入图片描述
引脚八个一组,因为位数就是8位,一次控制8个引脚

从51到52

  • 51有的功能52都有内核是一样的,所以在使用方法上没什么区别
  • RAM:128提升到256
  • EEPROM:4k提升到8k
  • 多一个看门狗
  • 最高外接晶振提升1/4左右
  • 51现在基本淘汰,直接买52就可以了

#安装和熟悉Proteys电路仿真软件,完成一个C51程序设计和仿真。

Proteus仿真AT89C51点亮LED

电路如图
在这里插入图片描述
代码

#include <REGX51.H>
void main(void)
{
	
	P2=0x0E;
	
	while(1)
	{
	
	}
}
  • 左上角是晶振
  • RST连接复位电路
  • P2_0口置低电平点灯

stm32单片机

引脚定义

在这里插入图片描述

片上外设

在这里插入图片描述

GPIO模式

在这里插入图片描述

stm32命名规则

在这里插入图片描述

stm32最小系统电路

在这里插入图片描述

  • 最下方 复位电路,添加滤波电容,供电一般都会添加滤波电容,
  • vbat接备用电池,不用可以直接悬空
  • 晶振stm32一般8MHZ,电容起振电容
  • 复位电路,NRST低电平复位
  • 启动配置,作为开关功能,用跳线帽实现

Proteus仿真stm32点亮LED灯

在这里插入图片描述
步骤如下

  • 按图连接电路(一个外接电源提供高电平,一个限流电阻,黄色LED)

  • 点击芯片设置晶振为8M,否则运行时会报错,我遇到的情况是软件直接卡死
    在这里插入图片描述

  • 点击设置,配置供电网,配置为如下图,把VDDA VSSA移动到右边
    在这里插入图片描述
    在这里插入图片描述

  • 在keil中编写代码,设置GPIOA,PA0口为低电平

#include "stm32f10x.h"                  // Device header
int main(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	GPIO_InitTypeDef GPIO_initStructure;
	GPIO_initStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_initStructure.GPIO_Pin= GPIO_Pin_0;
	GPIO_initStructure.GPIO_Speed= GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_initStructure);
	
	
	GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);
	while (1) 
	{

	}
}

面包板连接stm32c8t6点亮LED

在这里插入图片描述

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

int main(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	while (1)
	{
		GPIO_ResetBits(GPIOA, GPIO_Pin_0);
		Delay_ms(500);
		GPIO_SetBits(GPIOA, GPIO_Pin_0);
		Delay_ms(500);
		
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
		Delay_ms(500);
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
		Delay_ms(500);
		
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0);
		Delay_ms(500);
		GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1);
		Delay_ms(500);
	}
}

三、5132问答

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

寻址方式不同
对于内存中的变量,已知地址,所以在C程序代码中直接操作寄存器改变目标地址指向的值,即寄存器映射

对于外设,不知道具体地址,外设上一般有自己的片内RAM(内存),所以CPU只需要与外设的RAM交互就可以操作外设(CPU分出地址空间与片内RAM物理连接即内存映射的方式)

相同点,不管用什么方法,最后一步都需要改变目标地址指向的值。

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

51单片机点灯
只需要设置IO口的电平

stm32点灯
开启GPIO时钟
选择端口并初始化
端口输出模式
设置传输速率
设置IO口电平

由此可以看出两者的一些区别

  • 51单片机IO口使用简单,单片机输出低电平的时候,驱动能力尚可,但是输出高电平的时候,就没有输出电流的能力。
  • stm32使用者可以掌握功耗,对每个外设的时钟都设置了开关,让用户可以精确控制,关闭不需要的设备,节能省电,而51只有一个时钟所以不需要配置,虽然方便,但是功耗无法控制。

四、register与volatile区别

volatile是易变的,不稳定的意思,volatile是关键字,是一种类型修饰符,用它修饰的变量表示可以被某些编译器未知的因素更改,比如操作系统、硬件或者其他线程等,遇到这个关键字声明的变量,编译器对访问该变量的代码不在进行优化,从而可以提供对特殊地址的稳定访问。

#include <stdio.h>
int pass = 1;
int main()
{
	while(pass)
	{
		;
	} 	
	return 0;
}

由于pass = 1,为真,编译器会优化此代码,将循环条件直接改为真,后续不再从内存中读取pass的值来判断循环是否停止。
加了volatile后,每次都会将pass的值导入cpu判断是否循环了。
结论
volatile忽略编译器的优化,保持内存可见性。

#include <stdio.h>
volatile int pass = 1; //加上volatile
int main()
{
	while (pass) {
	;
	} 
	return 0;
}

register注册登录的意思,这个关键字请求编译器尽可能的将变量存在CPU内部寄存器中,而不是通过内存寻址访问,以提高效率。注意是尽可能,不是绝对,因为寄存器空间有限无法存储太多。
  
注意事项:
1.register只是请求寄存器变量,不一定能够成功,

我们知道寄存器是有限的(各个部门),如果定义了很多register变量,可能会超过CPU的寄存器个数,超过容量,(各个部门超负载了)
这时候就没有办法都变为寄存器变量了,这个数量主要看机器性能决定

2.register变量必须是能被CPU所接受的类型。

这通常意味着register变量必须是一个单个的值,并且长度应该小于或者等于整型的长度。不过,有些机器的寄存器也能存放浮点数。 (这个我们很容易理解,不是什么事都能作为大事的)

3.因为register变量可能不存放在内存中,所以不能用“&”来获取register变量的地址。

4.用register修饰的变量只能是局部变量,不能是全局变量。CPU的寄存器资源有限,因此不可能让一个变量一直占着CPU寄存器 (人不可能一直只处理一件事情)

5.register修饰符暗示编译程序相应的变量将被频繁地使用,如果可能的话,应将其保存在CPU的寄存器中,所以请注意,.register仅仅是暗示而不是命令。 这就好比寄存器可以说明这件事比较重要,但是不能直接命令CPU去做一件事

6.局部静态变量不能定义为寄存器变量。不能写成:register static int a, b, c;

虽然它被称作最近快的变量,但是也是比较不安全的变量,现在使用不多

#include <stdio.h>
int main()
{
    register int i;
    int tmp=0;
    for(i=1;i<=100;i++)
        tmp+=i;
    printf("总和为 %d\n",tmp);
    return 0;
}

经测试同样的代码使用register int比int快

参考文章

https://blog.csdn.net/u011878611/article/details/132260504

https://blog.csdn.net/qq_46467126/article/details/120737655

https://blog.csdn.net/geek_monkey/article/details/86291377

https://blog.csdn.net/Alexayo/article/details/109964791

https://blog.csdn.net/asdfjkl01/article/details/39371961

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值