赞
踩
一、安装Keil4和Proteus8.9仿真程序
Keil4的安装程序(附带下载地址)(参考CSDN)
【仿真】Proteus8.9下载与安装教程(超详细)(参考CSDN)
二、在Proteus中创建工程,对原理图进行创建
1.打开Proteus,创建新工程
2.创建新工程,选择工程保存路径
3.选择从选中的模版中创建原理图,选择DEFAULT(默认)
4.因为此次实验不需要PCB,所以选择不创建PCB布版设计
5.然后点击创建固定项目,在第二栏中选择AT89C51,其他都默认
6.然后进入最后一步,点击完成即可
7.进入原理图绘制界面,然后自行绘制,可参考Protues使用教程(CSDN - 专业开发者社区)
绘制结束
原理图参考如下:
至此,原理图创建完成
三、在Keil4创建工程,并且编译程序(流水灯)
1.创建新项目,并且点击New uVision Project
2.在新弹出的窗口中输入工程文件名称和选择工程的保存路径
3.在弹出的窗口中选择数据库,选择Atmel,在下拉选项中选择AT89C51
4.然后点击是(Y)
5.进入主界面创建一个新文件新文件
6.编写程序,然后右键点击文件夹,点击Add Files to Group... ...
- //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);
- }
- }
7.然后点击类似于仙女棒的东西,然后点击生成hex文件
8.编译文件,生成hex文件
没有任何警告和错误,且成功输出hex文件
四、将Keil4生成hex文件导入Proteus,然后进行仿真
1.双击单片机,然后选择刚才生成的hex文件
2.然后点击左下角仿真按钮,进行仿真
五、仿真结果
六.STM32流水灯实验
1.安装Keil5(keil5安装教程_Matcha_ice_cream的博客-CSDN博客)
2.创建文件名,选择保存路径
3.选择stm32f103zet6对应的库文件,搜索stm32f103ze
4.创建stmLED.c文件,然后编写程序:
- #define PERIPH_BASE ((unsigned int)0x40000000)//AHB的地址
- #define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) //APB2地址
- #define GPIOA_BASE (APB2PERIPH_BASE + 0x0800) //GPIOA地址
- #define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C //GPIOA_ODR地址
- #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
- #define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
- typedef struct{
-
- volatile unsigned int CR;
- volatile unsigned int CFGR;
- volatile unsigned int CIR;
- volatile unsigned int APB2RSTR;
- volatile unsigned int APB1RSTR;
- volatile unsigned int AHBENR;
- volatile unsigned int APB2ENR;
- volatile unsigned int APB1ENR;
- volatile unsigned int BDCR;
- volatile unsigned int CSR;
- } RCC_TypeDef;
-
- #define RCC ((RCC_TypeDef *)0x40021000)
- typedef struct
- {
- volatile unsigned int CRL;
- volatile unsigned int CRH;
- volatile unsigned int IDR;
- volatile unsigned int ODR;
- volatile unsigned int BSRR;
- volatile unsigned int BRR;
- volatile unsigned int LCKR;
- } GPIO_TypeDef;
- #define GPIOA ((GPIO_TypeDef *)GPIOA_BASE)
- void delay(unsigned int time)
- {
- unsigned int i=0;
- while(time--)
- {
- i=12000;
- while(i--);
- }
- }
-
- int main(void)
- {
- RCC->APB2ENR|=1<<2;
- GPIOA->CRL&=0x00000000;
- GPIOA->CRL|=0x33333333;
- GPIOA->ODR=0x01;
- while(1)
- {
- delay(10);
- GPIOA->ODR=GPIOA->ODR<<1;
- if(GPIOA->ODR==0x0100)
- {
- GPIOA->ODR=0x01;
- }
- }
- }
5.编写完程序后右键点击文件,添加文件stmLED.c
6.点击魔方块,添加stm32启动项文件
7.编译程序
成功编译
1.Jlink烧录程序的安装:Jlink软件下载和安装教程(参考CSDN)
2.点击仙女棒,然后进行下列勾选
3.点击Dubeg,然后settings选ST-LINK/V2,然后点击settings
4.然后勾选SW,输入Max1.8MHz,注意此时要插上stm32核心块,不然会显示错误Error,然后点击确定。
5.然后点击load,下载程序进入stm32,然后可以得到
流水灯视频如下
寄存器:寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果。寄存器是常用的时序逻辑电路,但这种时序逻辑电路只包含存储电路。寄存器的存储电路是由锁存器或触发器构成的,因为一个锁存器或触发器能存储1位二进制数,所以由N个锁存器或触发器可以构成N位寄存器。按照功能的不同,可将寄存器分为基本寄存器和移位寄存器两大类。基本寄存器只能并行送入数据,也只能并行输出。移位寄存器中的数据可以在移位脉冲作用下依次逐位右移或左移,数据既可以并行输入、并行输出,也可以串行输入、串行输出,还可以并行输入、串行输出,或串行输入、并行输出,十分灵活,用途也很广。
51单片机和STM32单片机在寄存器方面的差异主要体现在开发方式和系统资源上。
开发方式:51单片机主要通过直接操作寄存器进行编程,而STM32则主要采用库函数编程方式。
系统资源:STM32单片机的资源通常比51单片机更多。在寄存器方面,STM32可能具有更多的寄存器和更复杂的寄存器映射。例如,STM32F103系列芯片具有比51单片机更复杂的地址映射和寄存器映射,这可能需要更复杂的设置和编程。
总的来说,51单片机和STM32单片机在寄存器方面的差异主要体现在开发方式和系统资源上。
1)嵌入式C程序代码对内存(RAM)中的各变量的修改操作,与对外部设备(寄存器--->对应相关管脚)的操作有哪些相同与差别?
相同点:
两者都需要使用C语言进行编程。
两者都需要通过赋值操作来修改或控制。
两者都需要了解相应的内存地址或寄存器地址。
不同点:
对内存中的变量进行修改是直接在RAM中进行操作,而对外部设备的操作通常需要通过特定的寄存器间接实现。
对内存中的变量进行修改通常不会涉及到硬件的实时反应,而对外部设备的操作往往会有实时的硬件反应,比如改变LED的状态。
对内存中的变量进行修改不会涉及到中断、异常处理等问题,而对外部设备的操作可能会涉及到这些问题。
2)为什么51单片机的LED点灯编程要比STM32的简单?
51单片机比STM32简单的原因可能有以下几点:
51单片机的硬件结构相对简单,其I/O操作也相应简单。而STM32系列微控制器具有更多的功能和特性,因此在进行编程时可能需要考虑更多的因素。
51单片机的寄存器较少,因此在进行编程时需要考虑的寄存器操作也相对较少。而STM32系列微控制器具有更多的寄存器,因此在进行编程时可能需要考虑更多的寄存器操作。
51单片机的指令集相对简单,因此在进行编程时可能更容易理解和使用。而STM32系列微控制器的指令集更加复杂,因此在进行编程时可能需要更多的学习和理解。
51单片机的LED点灯编程通常是通过对I/O口的直接操作实现的,而STM32系列微控制器可能需要更多的配置和操作才能实现相同的LED点灯效果。
在C语言中,`register`和`volatile`是两种特殊的变量修饰符,它们在嵌入式系统中经常使用,这是因为在嵌入式系统中,对硬件的直接访问和优化通常是非常重要的。
1. `register`关键字:
在C语言中,`register`是一个存储类修饰符,用于提示编译器一个变量可能被频繁访问,以便将其存储在寄存器中,从而提高访问速度。然而,实际上是否将其存储在寄存器中是由编译器决定的,因为现代编译器通常已经能够进行高度优化。
请注意,对于大多数现代的编译器,`register`关键字的使用已经没有过去那么重要,因为编译器有自己的优化策略。然而,在嵌入式系统中,有时仍然会用到它,因为在这些环境中,对硬件的直接控制经常需要频繁地访问特定的变量。
示例代码:
- register int i;
- for(i=0;i<100;i++)
- {
- //频繁使用变量1
- }
2. `volatile`关键字:
`volatile`是另一个存储类修饰符,用于告诉编译器一个变量可能会被意外的(即编译器无法预知的)方式改变。这通常发生在并行编程或硬件寄存器映射的情况下。
在并行编程中,一个线程可能在一个时刻改变一个变量的值,而另一个线程可能在另一个时刻读取这个值。在这种情况下,编译器不能对这个变量进行优化,因为它不能确定变量的值何时会改变。
同样地,当直接访问硬件寄存器时,寄存器的值可能会在任何时候改变(例如,由于硬件事件或中断)。因此,使用`volatile`关键字可以确保编译器不会优化这个变量。
示例代码:
- volatile int flag;
- //假设flag是一个硬件寄存器的映射,该寄存器的的值可能会在任何时候改变
- if(flag)
- {
- //执行一些操作
- }
以上示例中,如果`flag`没有使用`volatile`修饰,编译器可能会优化掉对`flag`的读取操作,因为在它看来,`flag`的值并没有改变。然而,实际上`flag`的值可能已经改变了,这就会导致程序的行为出错。通过使用`volatile`关键字,我们可以确保这种情况不会发生。
1. C51不需要分频,且为8位单片机,STM32需要时钟分频且为32位单片机,功能更复杂,C51 编写流水灯程序时比STM32更简单。
2. stm32存储器映射是给绝对地址命名个别名,通过寄存器更改绝对地址里面的值。
3. 寄存器是CPU内部的组成部分,通过内部总线与CPU直接相连,内存是通过外部地址总线与C PU相连,通过外部总线寻址,通过寄存器修改变量的值比内存更快。
4. register声明的变量尽可能直接放在寄存器中存储,volatile声明的变量只能从绝对地址中访问。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。