菜鸟入门2,在ARM开发环境下编写一个stm32简单程序及在proteus上仿真一个简单的51程序

这次的任务主要围绕mdk5进行,首先是安装mdk5及注册机,然后是在arm开发环境下编译简单stm32程序,并且在proteus上仿真一个简单的51程序。

什么是mdk?

Keil MDK,也称MDK-ARM、Realview MDK、I-MDK、uVision4 等。Keil MDK是由三家国内代理商提供技术支持和相关服务。
MDK-ARM软件为基于Cortex-M、Cortex-R4、ARM7、ARM9处理器设备提供了一个完整的开发环境。 MDK-ARM专为微控制器应用而设计,不仅易学易用,而且功能强大,能够满足大多数苛刻的嵌入式应用。
MDK-ARM有四个可用版本,分别是MDK-Lite、MDK-Basic、MDK-Standard、MDK-Professional。所有版本均提供一个完善的C / C++开发环境,其中MDK-Professional还包含大量的中间库。

(此处参考百度百科,特别感谢)


1.安装mdk5遇到的问题及解决方法

首先,按照链接: mdk5 安装步骤.正常安装
接下来,是我遇到的问题,希望能够给你一些解决方法的参考
1.问题:在把注册机得到的注册码输入到这里在这里插入图片描述

会出现错误提示框。
解决方法: 用管理员的身份进入mdk5。

2.问题:注册机下载后,发现期限是2020年(已过期)
解决方法:从论坛中找到期限为2032年的mdk5注册机.并直接下载安装,操作如上。

操作成功如图在这里插入图片描述

2.在arm开发环境下编译简单stm32程序

准备工作
关于GPIO
1、设置GPIO口的引脚为输入或者输出模式。我们在进行点灯代码的时候,一般设置为推挽输出模式。

2、操作寄存器,往寄存器里置1或者清零操作——这个步骤,固件库已经提供了专门的GPIO_SetBits函数和GPIO_ResetBits函数,我们只要去调用即可实现对IO口的置1和清零。

3、实现多种花样的LED闪动,使得自己熟悉GPIO的编程过程。
此处参考文章.

关于stm32库函数中文使用手册
参见这里.

关于实例程序(闪烁的LED灯),参见 这里.

正式编写
1.首先建立一个文件夹
在这里插入图片描述
2打开 Keil uVision5 ,并新建一个工程。
具体操作参见 这里.

3工程建立好后,新建一个文件。
在这里插入图片描述
3.在建立的文本文件中输入C中的main函数并保存

在这里插入图片描述

4.保存后,将文件添加到工程中
在这里插入图片描述
在这里插入图片描述

6.编译,成功但有警告
在这里插入图片描述
.\LED.axf: Warning: L6304W: Duplicate input file .\system_stm32f10x.o ignored.

去查了资料,发现原因:
system_stm32f2xx_1.c文件出现了两次包含,就是程序中有两个相同的system_stm32f2xx_1.c文件,所以解决方法就是,去掉一个即可;在这里插入图片描述
编译成功无警告

7.接着复制以下代码。

#define PERIPH_BASE           ((unsigned int)0x40000000)
#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)
#define GPIOA_BASE            (APB2PERIPH_BASE + 0x0800)
#define GPIOB_BASE            (APB2PERIPH_BASE + 0x0C00)
#define GPIOC_BASE            (APB2PERIPH_BASE + 0x1000)
#define GPIOD_BASE            (APB2PERIPH_BASE + 0x1400)
#define GPIOE_BASE            (APB2PERIPH_BASE + 0x1800)
#define GPIOF_BASE            (APB2PERIPH_BASE + 0x1C00)
#define GPIOG_BASE            (APB2PERIPH_BASE + 0x2000)
#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C
#define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C
#define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C
#define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C
#define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C
#define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C   
#define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C 
 
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr))
 
 
#define LED0  MEM_ADDR(BITBAND(GPIOA_ODR_Addr,8))
//#define LED0 *((volatile unsigned long *)(0x422101a0)) //PA8
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  LEDInit( void )
{
     RCC->APB2ENR|=1<<2;  //GPIOA 时钟开启
     GPIOA->CRH&=0XFFFFFFF0;
     GPIOA->CRH|=0X00000003; 
}
 
//粗略延时
void  Delay_ms( volatile  unsigned  int  t)
{
     unsigned  int  i,n;
     for (n=0;n<t;n++)
         for (i=0;i<800;i++);
}
 
int  main( void )
{
     LEDInit();
     while (1)
     {
         LED0=0;
         Delay_ms(500);
         LED0=1;
         Delay_ms(500);
     }
}
 

在这里插入图片描述
编译成功

3.在proteus上仿真一个51程序

该系统为十字路口的交通灯系统,该十字路口有四个红绿灯,在仿真电路图中,横向竖向有两个红路灯和倒计时数码管。当横向绿灯亮60秒时,纵向的红灯亮相同的时间,随后是同时亮15秒黄灯,接着纵向绿灯亮三十秒,横向的红灯同时亮30秒。按下重置按钮,红路灯与数码管的状态回到刚开始。
代码如下

#include <reg51.h>

sbit czred=P0^0;
sbit czyellow=P0^1;
sbit czgreen=P0^2;
sbit nred=P0^3;
sbit nyellow=P0^4;
sbit ngreen=P0^5;

unsigned char redtime,yellowtime,greentime; 
unsigned char code num[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
unsigned char m;

void display(unsigned char a);
void delay();

void main()
{
	TMOD=0x01;
	TH0=0x3c;
	TL0=0xb0;
	ET0=1;EA=1;TR0=1;
	m=1;

	redtime=60;
	yellowtime=15;
	greentime=30;

	while(1)
	{
		switch(m)
		{case 1:
	  		display(redtime);
	  		 czred=1;
			 czyellow=1;
			 czgreen=0;
			 nred=0;
			 nyellow=1;
			 ngreen=1;
			 	break;
		case 2:
			display(yellowtime);
			czred=1;	
			czyellow=0;
			czgreen=1;
			nred=0;
			nyellow=1;
			ngreen=1; 
				break;
		case 3:
			display(greentime);
			czred=0;
			czyellow=1;
			czgreen=1;
			nred=1;
			nyellow=1;
			ngreen=0;
			break;
		case 4:
			display(yellowtime);
			czred=0;	
			czyellow=1;
			czgreen=1;
			nred=1;
			nyellow=0;
			ngreen=1; 
				break;
		case 5:
			display(yellowtime);
			czred=1;
			czyellow=0;
			czgreen=1;
			nred=1;
			nyellow=0;
			ngreen=1;
			break;
		}
	}
}


void display(unsigned char a) //数码管显示
{
	unsigned char gw,sw,i;
	gw=a%10;
	sw=a/10%10;
	
	for(i=0;i<2;i++)
		{
		P2=0xfd;
		P1=num[gw];
		delay();
		P2=0xff;
		P2=0xfe;
		P1=num[sw];
		delay();
		P2=0xff;
		}
}

void delay() //延时
	{
	unsigned char i;
	for(i=0;i<200;i++);
	}

void time0()interrupt 1		//中断
{
	unsigned char n;
	TH0=0x3c;
	TL0=0xb0;
	n=n+1;
	
	if(n==20)
	{   
		n=0;
		if(m==5)
				{ 
					if(yellowtime==0)
				        {
						m=1;
						redtime=15;
						}
				     else                        
	          			{
						yellowtime=yellowtime-1;
						m=5;
						} 
				}
	
	     if(m==1)
				{ 
		   			if(redtime==0)
	         			{	
						m=2;
						yellowtime=15;	
						}
	         		else                        
	          			{
						redtime=redtime-1;
						m=1;
						} 
				}
	        if(m==2)
				{ 
				
					if(yellowtime==0)
	         			{
						m=3;	
						greentime=30;
						}
	          		else
	         			{	
						yellowtime=yellowtime-1;	
						m=2; 
						}
				}
	if(m==3)
				{  
	       			if(greentime==0)
	          			{	
						m=4;
						yellowtime=15;	
						} 
	        		else
	         			{	
						greentime=greentime-1;
						 m=3;
						 } 
				}
	 if(m==4)
				{   
	         		if(yellowtime==0)
	          			{
					m=1;
			 		 redtime=60;
					 	}
	       			else
	         			{
						yellowtime=yellowtime-1;
					 m=4;
					 	}
	    }
	}
}

在keil5中生成hex文件在这里插入图片描述

并在proteus中仿真,仿真如图
交通灯闪烁情况
在这里插入图片描述

总结

以上就是今天要讲的内容,我学习到了如何在mdk5下编写程序,本文仅仅简单代表本小菜鸟对stm32的简单入门心得,特别鸣谢文中引用到的各路大佬的文章,我希望下次能呈现出更加通俗易懂又不浅薄的小经验。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值