当前位置:   article > 正文

Keil4与Proteus仿真程序实现流水灯实验&STM32实现通过寄存器实现流水灯实验

keil4

一、安装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... ...

main.c:

  1. //51单片机编程常用的头文件
  2. #include <reg51.h>
  3. #include <intrins.h>
  4. //延迟函数
  5. void delay_ms(int a)
  6. {
  7. int i,j;
  8. for(i=0;i<a;i++)
  9. {
  10. for(j=0;j<1000;j++) _nop_();
  11. }
  12. }
  13. void main(void)
  14. {
  15. while(1)
  16. {
  17. P0=0xfe;
  18. delay_ms(50);
  19. P0=0xfd;
  20. delay_ms(50);
  21. P0=0xfb;
  22. delay_ms(50);
  23. P0=0xf7;
  24. delay_ms(50);
  25. P0=0xef;
  26. delay_ms(50);
  27. P0=0xdf;
  28. delay_ms(50);
  29. P0=0xbf;
  30. delay_ms(50);
  31. P0=0x7f;
  32. delay_ms(50);
  33. }
  34. }

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文件,然后编写程序:

main.c

  1. #define PERIPH_BASE ((unsigned int)0x40000000)//AHB的地址
  2. #define APB2PERIPH_BASE (PERIPH_BASE + 0x10000) //APB2地址
  3. #define GPIOA_BASE (APB2PERIPH_BASE + 0x0800) //GPIOA地址
  4. #define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C //GPIOA_ODR地址
  5. #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
  6. #define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
  7. typedef struct{
  8. volatile unsigned int CR;
  9. volatile unsigned int CFGR;
  10. volatile unsigned int CIR;
  11. volatile unsigned int APB2RSTR;
  12. volatile unsigned int APB1RSTR;
  13. volatile unsigned int AHBENR;
  14. volatile unsigned int APB2ENR;
  15. volatile unsigned int APB1ENR;
  16. volatile unsigned int BDCR;
  17. volatile unsigned int CSR;
  18. } RCC_TypeDef;
  19. #define RCC ((RCC_TypeDef *)0x40021000)
  20. typedef struct
  21. {
  22. volatile unsigned int CRL;
  23. volatile unsigned int CRH;
  24. volatile unsigned int IDR;
  25. volatile unsigned int ODR;
  26. volatile unsigned int BSRR;
  27. volatile unsigned int BRR;
  28. volatile unsigned int LCKR;
  29. } GPIO_TypeDef;
  30. #define GPIOA ((GPIO_TypeDef *)GPIOA_BASE)
  31. void delay(unsigned int time)
  32. {
  33. unsigned int i=0;
  34. while(time--)
  35. {
  36. i=12000;
  37. while(i--);
  38. }
  39. }
  40. int main(void)
  41. {
  42. RCC->APB2ENR|=1<<2;
  43. GPIOA->CRL&=0x00000000;
  44. GPIOA->CRL|=0x33333333;
  45. GPIOA->ODR=0x01;
  46. while(1)
  47. {
  48. delay(10);
  49. GPIOA->ODR=GPIOA->ODR<<1;
  50. if(GPIOA->ODR==0x0100)
  51. {
  52. GPIOA->ODR=0x01;
  53. }
  54. }
  55. }

5.编写完程序后右键点击文件,添加文件stmLED.c

6.点击魔方块,添加stm32启动项文件

7.编译程序

成功编译

7.Jlink烧录程序

1.Jlink烧录程序的安装:Jlink软件下载和安装教程(参考CSDN)

2.点击仙女棒,然后进行下列勾选

3.点击Dubeg,然后settings选ST-LINK/V2,然后点击settings

4.然后勾选SW,输入Max1.8MHz,注意此时要插上stm32核心块,不然会显示错误Error,然后点击确定。

5.然后点击load,下载程序进入stm32,然后可以得到

流水灯视频如下

8.问题思考1:

1.嵌入式C程序代码对内存(RAM)中的各变量的修改操作,与对外部设备(寄存器--->对应相关管脚)的操作有哪些相同与差别?
2.为什么51单片机的LED点灯编程要比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点灯效果。

9.问题思考2:与PC平台上的一般程序不同,嵌入式C程序经常会看见 register和volatile 关键字,请解释这两个变量修饰符的作用,并用C代码示例进行说明。

在C语言中,`register`和`volatile`是两种特殊的变量修饰符,它们在嵌入式系统中经常使用,这是因为在嵌入式系统中,对硬件的直接访问和优化通常是非常重要的。

1. `register`关键字:
在C语言中,`register`是一个存储类修饰符,用于提示编译器一个变量可能被频繁访问,以便将其存储在寄存器中,从而提高访问速度。然而,实际上是否将其存储在寄存器中是由编译器决定的,因为现代编译器通常已经能够进行高度优化。

请注意,对于大多数现代的编译器,`register`关键字的使用已经没有过去那么重要,因为编译器有自己的优化策略。然而,在嵌入式系统中,有时仍然会用到它,因为在这些环境中,对硬件的直接控制经常需要频繁地访问特定的变量。

示例代码:

  1. register int i;
  2. for(i=0;i<100;i++)
  3. {
  4. //频繁使用变量1
  5. }

2. `volatile`关键字:

`volatile`是另一个存储类修饰符,用于告诉编译器一个变量可能会被意外的(即编译器无法预知的)方式改变。这通常发生在并行编程或硬件寄存器映射的情况下。

在并行编程中,一个线程可能在一个时刻改变一个变量的值,而另一个线程可能在另一个时刻读取这个值。在这种情况下,编译器不能对这个变量进行优化,因为它不能确定变量的值何时会改变。

同样地,当直接访问硬件寄存器时,寄存器的值可能会在任何时候改变(例如,由于硬件事件或中断)。因此,使用`volatile`关键字可以确保编译器不会优化这个变量。

示例代码:

  1. volatile int flag;
  2. //假设flag是一个硬件寄存器的映射,该寄存器的的值可能会在任何时候改变
  3. if(flag)
  4. {
  5. //执行一些操作
  6. }


以上示例中,如果`flag`没有使用`volatile`修饰,编译器可能会优化掉对`flag`的读取操作,因为在它看来,`flag`的值并没有改变。然而,实际上`flag`的值可能已经改变了,这就会导致程序的行为出错。通过使用`volatile`关键字,我们可以确保这种情况不会发生。

10.总结

1. C51不需要分频,且为8位单片机,STM32需要时钟分频且为32位单片机,功能更复杂,C51         编写流水灯程序时比STM32更简单。

 2. stm32存储器映射是给绝对地址命名个别名,通过寄存器更改绝对地址里面的值。

 3.  寄存器是CPU内部的组成部分,通过内部总线与CPU直接相连,内存是通过外部地址总线与C        PU相连,通过外部总线寻址,通过寄存器修改变量的值比内存更快。

 4. register声明的变量尽可能直接放在寄存器中存储,volatile声明的变量只能从绝对地址中访问。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/434925
推荐阅读
相关标签
  

闽ICP备14008679号