当前位置:   article > 正文

使用keil安成Proteus电路仿真及stm32的简易程序开发(通过寄存器使用GPIO输出)_proteus新建stm32工程

proteus新建stm32工程

(一)安装Keil、Proteus电路仿真软件,实现C51程序设计和仿真

1、Proteus和Keil简介及安装

​    Proteus软件是英国Lab Center Electronics公司出版的[EDA工具软件]。它不仅具有其它EDA工具软件的仿真功能,还能仿真[单片机]及外围器件。它是比较好的仿真单片机及外围器件的工具。虽然国内推广刚起步,但已受到单片机爱好者、从事单片机教学的教师、致力于单片机开发应用的[科技工作者]的青睐。从[原理图]布图、代码调试到[单片机]与外围电路协同仿真,一键切换到[PCB设计],真正实现了从概念到产品的完整设计。是世界上唯一将[电路仿真]软件、PCB设计软件和[虚拟模型]仿真软件三合一的[设计平台],其处理器模型支持8051、HC11、PIC10/12/16/18/24/30/DSPIC33、AVR、[ARM]等,2010年又增加了[Cortex]和DSP系列处理器,并持续增加其他系列处理器模型。在编译方面,它也支持[IAR]、[Keil]和[MATLAB]等多种[编译器]。(摘自百度百科)

        

Keil是一款C语言软件开发系统,支持Windows系统。

Keil提供了包括编译器、宏汇编、链接器、库管理和一个功能强大的仿调试器等在内的完整开发方案,通过一个集成开发环境(μVision)将这些部分组合在一起。

安装教程

可于Proteus官网上下载相应安装包,打开安装包选择相应的安装路径继续安装直到完成即可。

2、绘制Proteus仿真图​及编写C51程序    

*本次实验仿真的C51程序实现的是简易流水灯功能

*打开Proteus软件,创建新工程。

*仿真图所需的元器件如下图,可在元件库中寻找,绘制的原理图如下。

  1. #include<reg51.h>
  2. char code led[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
  3. void delay(int ms){
  4. int i,j;
  5. for(i=ms;i>0;i--)
  6. for(j=120;j>0;j--);
  7. }
  8. void main()
  9. {
  10. while(1)
  11. {
  12. char i=0;
  13. for(i=0;i<8;i++)
  14. {
  15. P2=led[i];
  16. delay(300);
  17. }
  18. }
  19. }

该仿真使用的是C51单片机的P2端输出口,当P2输出为0时,led会亮,因此代码中led数组记录的是P2八个端口在不同时刻为0,其他端口为1的场景,主函数再用一个for循环依次输出即可,是一个简易使用流水灯的操作。最后将.c文件使用魔术棒输出为.hex文件导入仿真的C51中运行即可。

3、仿真结果

流水灯C51

(二)ARM开发,使用MDK编译简单STM32程序(点亮led灯)

1、环境配置及硬件接线

        安装stm32 pack软件和mdk,以及在官网上下载编译所需的固件库。

        该过程可自行搜索资源进行配置,下面只介绍具体的操作步骤。

        该实验使用的是stm32最小开发板,烧录接口使用的是usb转ttl插口,具体的接线为:将开发板上下的G接地,3.3v接面包板+极,接口处3v3接口连接开发板的供电口,GND接口连接开发板接地口TXD接口接A10,RXD接口接P9口,开发板B8口通过led灯+极连接-极口。具体接线图如下:

2、使用keil编写STM32程序

        *新建一个工程文件,配置并引入固件库,如何新建一个工程模板,可参考此篇博文:MDK5 Kil5中STM32工程的建立过程,此处不过多介绍。

        *编写main.c文件

        本文使用寄存器GPIO点亮led灯,就需要以下的几个步骤:

        1、使用gcc开启 GPIO 的端口时钟

        2、使用GPIO_Init函数初始化GPIO

        3、使用输入或输出的函数控制GPIO口

这里主要涉及gcc和GPIO两个外设,rcc使用的库函数为RCC APB2外设时钟控制,第一个参数选择外设,第二个参数使能或失能。

        GPIO库函数使用的的是GPIO_Delint,参数可以写GPIOA和GPIOB,分别表示开发板上的两种端口,作用为指定的GPIO外设复位。第二个使用的是GPIO_Init,这个函数的作用是用结构体的参数来初始化GPIO口,需要定义并赋值一个结构体变量,在调用该函数。之后则是GPIO的读写功能函数。

*编写main.c文件主程序

  1. #include "stm32f10x.h"
  2. int main(void)
  3. {
  4. GPIO_InitTypeDef GPIO_InitStructure; //定义结构体局部变量
  5. RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE);
  6. //结构体的参数设置
  7. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //引脚这里选择的是B8引脚
  8. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //点灯使用推挽输出
  9. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出速度
  10. GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化结构体
  11. GPIO_SetBits(GPIOB,GPIO_Pin_8);
  12. while(1)
  13. {
  14. GPIO_ResetBits(GPIOB,GPIO_Pin_8);
  15. }
  16. }

        在上面的代码中GPIO外设的8号引脚会自动配置为推挽输出、50MHz的速度,内部的主要执行逻辑为读取结构体的参数,执行判断和运算,最后写入到GPIO的配置寄存器。这里我们需要把输出的端口设置为低电平,所以使用GPIO_ResetBits,若要设置为高电平可以使用GPIO_SetBits函数。

3、烧录程序到开发板,点亮led灯

        *将.c文件使用魔术棒输出为.hex文件导入仿真的C51中运行即可。

         *使用FlyMcu烧录软件,将开发板接口接入电脑,软件的串口修改为开发板串口,开启使用RamIsp,烧录速度调节为115200,选择生成的.hex文件。

        *注意,需要将开发板上的BOOT0调节为0,BOOT1使用键帽调节为1,开启录入功能。

        *烧录成功

        在此代码的基础上通过添加延时函数交替出现GPIO_ResetBits和GPIO_SetBits函数,即可实现led灯的闪烁。实现结果如下:

STM32灯闪烁

(三)思考及总结

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

共同点:都需要使用寄存器或地址来访问或修改数据,都需要连接相应的端口,初始化相关端口的数据和设置。都需要转录相关的c语言程序通过寄存器来实现对内存的修改。

在数据的精确度方面,二者都需要满足一定的时序或操作顺序,避免出现系统报错或无法烧录的问题。

差别:对内存中的变量进行修改操作时,可以直接使用变量名来进行读取和修改,而对外部设备的操作通常需要通过特定的寄存器或地址进行读写。也就是说对比内存变量,外部设备的操作要更加复杂,因为需要设置和初始化相关的结构体数据类型。

内存中的修改可以直接在C程序代码中实现,而外部设备的操作需要追踪相关的函数和对应参数来实现。

对内存中的变量的修改操作主要受限于内存容量,而对外部设备的操作则受限于设备的特性和功能。

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

        首先STM32对应的编程需要更复杂的软件固件库来配置相关的编程环境,否则连初始化的编译都做不到,由于缺少相关的固件。其次,对keil也有严格的要求,需要管理员授权。其次,1单片机的架构相对简单,指令集和寄存器的数量较少,易于理解和使用。相比之下,STM32具有更复杂的架构和更多的寄存器,需要更多的学习和理解。再来是固件的选择上,相对应的烧录需要三种不同的方式来实现烧录过程,51单片机的GPIO控制相对简单,通过直接访问寄存器即可实现LED点灯操作。而STM32的GPIO控制需要借助复杂的库函数和配置文件,需要查找相应的函数。

3、嵌入式C程序经常会看见 register和volatile 关键字,请解释这两个变量修饰符的作用

        register修饰符暗示编译程序相应的变量将被频繁地使用,如果可能的话,应将其保存在CPU的寄存器中,以加快其存储速度。例如下面的内存块拷贝代码。

  1. /* Procedure for the assignment of structures, */
  2. /* if the C compiler doesn't support this feature */
  3.   #ifdef NOSTRUCTASSIGN
  4.   memcpy (d, s, l)
  5. {
  6. register char *d;
  7.   register char *s;
  8.   register int i;
  9.   while (i--)
  10.   *d++ = *s++;
  11.   }
  12. #endif

        

        volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。volatile 提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如 果没有 volatile 关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。所以遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。

中断服务程序中修改的供其它程序检测的变量,需要加volatile

多任务环境下各任务间共享的标志,应该加volatile

存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号