赞
踩
CPU,全名Central Processing Unit(中央处理器)。这是一块超大规模的集成电路,包含上亿的晶体管,是一台计算机的运算核心(Core)和控制核心(ControlUnit)。它的功能主要是解释计算机指令以及处理计算机软件中的数据。
它的主要构成是:运算器、控制器、寄存器
存储器本身没有地址,给存储器分配地址的过程叫存储器映射,一般由芯片厂商或用户分配。
CPU分出去的地址空间与外设的片内RAM连接,这样CPU就能像访问内存一样去访问外设的片内RAM(内存),这就是内存映射
在存储器的区域单元中,每个单元对应不同的功能,当我们控制这些单元时就可以驱动外设工作。我们可以找到每个单元的呢起始地址,然后通过语言指针的操作方式来访问这些单元,如果每次都是通过这种地址的方式来访问,不仅不好记忆,还容易出错,这是我们可以根据每个单元功能的不同,以功能为名给这个内存单元取一个别名,这个别名就存在寄存器中,这个给已经分配好地址的有特定功能的内存单元取别名的过程,就叫做寄存器映射。
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又称随机存取存储器(电脑的内存条),存储单元的内容可按照需要随机取出或存入,且存取的速度与存储单元的位置无关。这种存储器在断电时,将丢失其存储内容,所以主要用于存储短时间使用的程序。
它主要用来存储程序中用到的变量。凡是整个程序中,所用到的需要被改写的量(包括全局变量、局部变量、堆栈段等),都存储在RAM中。
单片机,英文 Micro Controller Unit 简称MCU
内部集成了CPU、RAM、ROM、定时器、中断系统、通讯接口等一系列电脑的常用硬件功能,算是一个袖珍版计算机。
51单片机是对所有兼容Intel8031指令系统的单片机的统称,这一系列的单片机的始祖是Intel的8031单片机,后来随着flash ROM技术的发展,8031单片机取得了长足的进展成为了应用最广泛的8bit单片机之一,他的代表型号就是ATMEL公司的AT89系列。
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的时钟电路,用于产生整个单片机运行的时序脉冲,但需外接晶体振荡器和振荡电容。
命名规则
引脚八个一组,因为位数就是8位,一次控制8个引脚
#安装和熟悉Proteys电路仿真软件,完成一个C51程序设计和仿真。
电路如图
代码
#include <REGX51.H>
void main(void)
{
P2=0x0E;
while(1)
{
}
}
步骤如下
按图连接电路(一个外接电源提供高电平,一个限流电阻,黄色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) { } }
#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); } }
寻址方式不同
对于内存中的变量,已知地址,所以在C程序代码中直接操作寄存器改变目标地址指向的值,即寄存器映射
对于外设,不知道具体地址,外设上一般有自己的片内RAM(内存),所以CPU只需要与外设的RAM交互就可以操作外设(CPU分出地址空间与片内RAM物理连接即内存映射的方式)
相同点,不管用什么方法,最后一步都需要改变目标地址指向的值。
51单片机点灯
只需要设置IO口的电平
stm32点灯
开启GPIO时钟
选择端口并初始化
端口输出模式
设置传输速率
设置IO口电平
由此可以看出两者的一些区别
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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。