• 利用keil arm编译器在proteus中仿真stm32


    也许很多人都会讨厌keil 或者stm32 cube繁杂的配置过程,选出型号之后还有诸多的配置,那么有没有一种办法用上keil arm的编译器来编译我们的stm32,又不使用其他不熟悉的编译器(如yagarto)《用proteus直接仿真stm32-可以完全丢弃编程器》呢?
    其实我们知道,我们使用stm32一般会有两套库文件,一套是HAL,一套是标准库。

    keil arm中使用的就是标准库。那么我们怎么来使用它呢?

    1、在proteus中配置好keil arm

    在配置前,我们要确保我们的keil arm已经在我们的机器上安装好了(keil arm 安装好就可以的,无所谓破不破解,因为我们只要用到它的编译器)。然后打开proteus,在compiler config中配置如下:
    在这里插入图片描述
    不会配置的,就直接点下面的check按钮则自动完成。

    2、新建工程绘制电路

    新建一个工程,并在器件库中找到stm32的芯片,如我们这里选择stm32f103r6,则电路绘制可以如下:
    在这里插入图片描述

    3、配置电路和芯片

    新建的芯片电源连接会有两个没有连接,VssA与VDDA,可以按照下面的连接来设置
    在这里插入图片描述
    电源电压,我们也设置到3.3V
    在这里插入图片描述
    最后,我们要给芯片配置一下频率为8MHZ,如下图:
    在这里插入图片描述

    4、代码

    /* Main.c file generated by New Project wizard
     *
     * Created:   周六 8月 13 2022
     * Processor: STM32F103R6
     * Compiler:  Keil for ARM
     */
    
     
    #include 
    #include  
     
    //IO口操作宏定义
    #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
    #define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
    #define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 
     
    #define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C 
    #define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C 
    #define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //PA输出 
    #define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //PB输出 
     
    #define LED0 PAout(8) // PA8 
    #define LED1 PAout(4) // PA4
     int flag=0;
    //时钟设置
    //RCC_CR_HSION,RCC_CR_HSEON,RCC_CR_HSERDY,RCC_CFGR_PLLSRC等在头文件stm32f103x6.h有定义
    void Clock_Init(unsigned char PLL) 
       { 
          unsigned char temp_value = 0;
          
          RCC->CR|=RCC_CR_HSION;    //使能内部高速时钟HSION
          while(!(RCC_CR_HSIRDY>>1));  //等待PLL锁定
          RCC->CR|=RCC_CR_HSEON;    //外部高速时钟使能HSEON 
          while(!(RCC_CR_HSERDY>>17)); //等待外部时钟就绪
          RCC->CFGR=0x00000400;      //APB1=DIV2;APB2=DIV1;AHB=DIV1;
          RCC->CFGR|=(PLL-2)<<18;      //设置 PLL值 2~16,本例为9倍频 
          RCC->CFGR|=RCC_CFGR_PLLSRC;  //PLLSRC选择外部时钟HSE为PLL输入源 
          RCC->CR|=RCC_CR_PLLON;       //使能PLL 
          while(!(RCC_CR_PLLRDY>>25)); //等待 PLL锁定
          RCC->CFGR|=RCC_CFGR_SW_PLL; //PLL作为系统时钟      
          while(temp_value!=RCC_CFGR_SWS_PLL) //等待PLL作为系统时钟设置成功
          { 
    	 temp_value=RCC->CFGR;
    	 temp_value&=0x0C;
          }       
       }
     
    //毫秒延时
    void delay_nms(unsigned int time)
    {    
       unsigned int i=0;  
       while(time--)
       {
          i=12000;  
          while(i--) ;    
       }
    }
     
    //为LED亮灭进行GPIO口初始化
    void LED_Init(void)
     { 
         
       RCC->APB2ENR|= RCC_APB2ENR_IOPAEN; //使能 PORTA时钟
       GPIOA->CRH&=0XFFF0FFF0;   //初始化PA8
        GPIOA->CRH|=3<<0;  		 //PA8 推挽输出  
        GPIOA->CRL&=0XFFF0FFFF;  //初始化PA4
        GPIOA->CRL|=3<<16;       //PA4 推挽输出  
       GPIOA->ODR|=1<<4;         //PA4 初始输出高
       GPIOA->ODR|=1<<4;         //PA8 初始输出高
       }
     
    //main函数
    int main (void)
     {    
       Clock_Init(9); //设PLL为系统时钟,频率为HSE外部时钟8MHz的9倍   
       LED_Init(); //GPIO初始化   
       while (1)
       {
          if(flag==1)
    	 break;
          LED0 = 0; //PA8输出0
          LED1 = 1; //PA4输出1
          delay_nms(100); //延时0.5S
          LED0 = 1; //PA8输出1
          LED1 = 0; //PA4输出0
          delay_nms(100); //延时0.5S
       }
       return 0;
    }   
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91

    5、运行效果

    在这里插入图片描述
    总结:
    这里我们使用的是标准库,而且没有通过stm32 cube的设备配置,直接通过了寄存器来设置端口,对于初学者不好理解,或者说从字面上不好理解,但如果真是准备扎实学习stm32的童鞋,那更能帮助咱们理解寄存器的使用。
    相比函数库去设定端口的代码更能够理解底层的机理些。
    不明白的可以去查看一下stm32的手册,收获一定更大!
    百度网盘链接提取码 密码:lwcg

  • 相关阅读:
    火星车初级java面向对象
    OCR-paddleocr
    用于标记蛋白质和抗体的Biotin-LC-Sulfo-NHS|CAS:191671-46-2
    【Kubernetes | Pod 系列】Pod的 YAML 清单文件详解
    vue——路由之路由跳转、路由传参、路由嵌套、路由模式
    java-net-php-python-ssm动漫论坛系统查重PPT计算机毕业设计程序
    git常用操作(二)
    Go Context 原理详解
    关于 SAP UI5 应用 ui5.yaml 里的 paths 映射问题
    渠道变革正当时, 数商云渠道商系统构建新能源汽车行业数字化渠道管理新模式
  • 原文地址:https://blog.csdn.net/haigear/article/details/126324709