ARM开发环境入门

    科技2024-07-19  63

    目录

    实验要求实验过程及结果一、在arm开发环境下编译stm32程序二、在proteus上仿真一个51程序

    实验要求

    安装mdk5软件和stm32包,熟悉mdk开发环境,完成一个stm32的简单程序的编译。安装过程可参考网上或者“STM32底座实验指导书”第1章。示例程序可以参考网上代码,或者“STM32底座实验指导书”第3章的“LED闪烁”。(注意,没有硬件之前,只能做程序的编译和仿真测试,无法下载到硬件上运行)安装并熟悉Proteus 电路仿真软件,完成一个51程序设计和仿真

    实验过程及结果

    mdk5.10的安装及破解参照压缩包中的安装手册

    一、在arm开发环境下编译stm32程序

    1、首先打开keil uVision5,新建一个工程 2、在STM32芯片中选择STM32F103RB芯片

    3、新建文件输入代码

    代码如下

    #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)) 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); } }

    4、在工程下添加.c文件 5、编译程序 6、进行如下设置 7、调试程序

    二、在proteus上仿真一个51程序

    代码如下

    #include<reg51.h> #define uchar unsigned char #define uint unsigned int  uchar code table[]={  //共阴极数码管码表 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71,  0xC9,0xFF,0x40     };//设置码,测试码,不计时码   voiddelay(uint x);//延时函数  voiddisplay(uchar,uchar,uchar,uchar);//数码管显示函数 void scankeys(); //键盘函数 void traffic(); //交通灯函数   uchar num,num1,num2,  //1南北 2东西 shi1,ge1,shi2,ge2, value1,value2,//南北绿灯时间黄灯时间 value3,value4,//东西绿灯时间黄灯时间  count1,count2,flag1,flag2;//南北标记东西标记 南北设置标记东西设置标记   voidmain(){        TMOD=0x01;   //设置定时器0位工作模式1(M1,M0位0,1)    TH0=(65536-45872)/256;  //装初值11.0592M晶振定时50ms数为45872    TL0=(65536-45872)%256;   EA=1;  //开总中断    ET0=1;  //开定时器0中断   TR0=1;  //启动定时器0   /*初状态*/    value1=15;   //南北黄绿灯默认值   value2=5;     value3=10;   //东西黄绿灯默认值   value4=5; num1=value1;//南北数码管先绿灯时间   num2=value2+value1;//东西红灯时间  20s     P1=0x41;//初始状态:东西红灯南北绿灯   20 15     while(1){     if(num==20)    //定时器1s    {     num=0;     num1--;     num2--;     traffic();            shi1=num1/10;     ge1=num1%10;       shi2=num2/10;     ge2=num2%10;      }       scankeys();       display(shi1,ge1,shi2,ge2);traffic(){   if(num1==0){         //1南北     count1++;        //南北标志位     if(count1==1){                    //南北方向红灯15s倒计时结束,      P1=0x42;                      //东西方向仍为红 灯,南北方向变为黄灯       num1=value2;      //黄灯时间为5s    }     if(count1==2){       //南北方向黄灯5s倒计时结束,      P1=0x14;       //东西方向变为绿灯,南北方向变为红灯      num1=value3+value4;     //南北方法红灯时间为15s    }     if(count1==3){       //南北方向红灯15s倒计时结束,      P1=0x41;       //东西方向变为红灯,南北方向变为绿灯      num1=value1;      //南北方向绿灯时间15s     count1=0;       //重置南北标志位      }  } if(num2==0){        // 2东西    count2++;        //东西标志位     if(count2==1){        //东西方向红灯20s 倒计时结束,      P1=0x14;       //东西方向变为绿灯,南北方向变为红灯      num2=value3;        //东西方向绿灯时间10s    }     if(count2==2){       //东西方向绿灯10s倒计时结束,      P1=0x24;       //东西方向变为黄灯,南北方向变为仍为红灯      num2=value4;      //东西方向黄灯时间5s    }     if(count2==3){       //东西方向黄灯时间5s倒计时结束,      P1=0x41;       //东西方向变为红灯,南北方向变为绿灯      num2=value1+value2;     //东西方向红灯时间20s     count2=0;       //重置东西标志位    }        } }  /************************************数码管显示子函数********************************************/   voiddisplay(uchar shi1,uchar ge1,uchar shi2,uchar ge2)  {      uchar temp;   temp=P2;   P2=0xfe;   P0=table[shi1];   delay(5);      P2=0xfd;   P0=table[ge1];   delay(5);      P2=0xfb;   P0=table[shi2];   delay(5);      P2=0xf7;   P0=table[ge2];   delay(5);/************************************* 延时子函数 ********************************************/voiddelay(uint x){   uint i,j;  for(i=x;i>0;i--)   for(j=110;j>0;j--);}/*************************4*4矩阵键盘功能子函数 ******************** 说明:     *******************************************************************/   voidscankeys()   {   uchar temp,key;   P3=0xfe;   //第一行线 temp=P3;  temp=temp&0xf0;  if(temp!=0xf0)  {    delay(10);  //按键去抖   temp=P3;   temp=temp&0xf0;   if(temp!=0xf0)   {      temp=P3;     switch(temp)     {       case0xee: key=0;  break;      case0xde: key=1;  break;      case0xbe: key=2;  break;      case0x7e: key=3;  break;     }      while(temp!=0xf0)     {       temp=P3;      temp=temp&0xf0;     }if(key==0)        //按键1:    {         TR0=~TR0;        //定时器取反      flag1=~flag1;     //南北能够设置标志 0有效     flag2=~flag2;          //东西能够设置标志    }       if(key==1&&flag1==0)    //按键2:    {      TR0=0;      P1=0x44;      //禁止东南西北车辆全为红灯可以设置      shi1=ge1=shi2=ge2=16;  //数码管显示设置符号    }       if(key==2&&flag2==0)    //按键3:    {      TR0=1;      num=0;       //定时器初始化     P1=0x41;       //重新开始初状态     num1=value1;      //南北数码管绿灯时间     num2=value2+value1;    //东西数码管红灯时间 shi1=num1/10;       ge1=num1%10;     shi2=num2/10;     ge2=num2%10;    }       if(key==3&&P1==0x44){  //按键4:     P1=0xff;     delay(1000);     P1=~P1;      shi1=ge1=shi2=ge2=17;     P1=0x44;    }     }  }    P3=0xfd;//第二行线  temp=P3;  temp=temp&0xf0;  if(temp!=0xf0)  {  delay(10);   temp=P3;   temp=temp&0xf0;   if(temp!=0xf0){    temp=P3;    switch(temp)    {      case0xed: key=0;break;     case0xdd: key=1;break;     case0xbd: key=2;break;     case0x7d: key=3;break;    }    while(temp!=0xf0)   {     temp=P3;    temp=temp&0xf0;   }       if(key==0&&P1==0x44){//按键5:      num1=value1;     if(num2!=159){//@@@@保证交通合理,红灯最大值计时 159s,绿灯不再增加     num1++;     value1=num1;    }      shi1=num1/10;    ge1=num1%10;      num2=value1+value2;//显示东西红灯时间    shi2=num2/10;    ge2=num2%10;     }    if(key==1&&P1==0x44){//按键6:    num1=value2;    if(num2!=159)    {      num1++;     value2=num1;    }  shi1=num1/10;    ge1=num1%10;     num2=value1+value2;//显示东西红灯时间    shi2=num2/10;    ge2=num2%10;    }     if(key==2&&P1==0x44&&value1>3){//按键7:    num1=value1;      num1--;    value1=num1;      shi1=num1/10;    ge1=num1%10;     num2=value1+value2;//显示东西红灯时间    shi2=num2/10;    ge2=num2%10;    }    if(key==3&&P1==0x44&&value2>3){//按键8:      num1=value2; num1--;    value2=num1;      shi1=num1/10;    ge1=num1%10;     num2=value1+value2;//显示东西红灯时间    shi2=num2/10;    ge2=num2%10;    }   }    }     ||||||||||||||||||    P3=0xfb;//第三行线  temp=P3;  temp=temp&0xf0;  if(temp!=0xf0)  {    delay(10);  temp=P3;   temp=temp&0xf0;   if(temp!=0xf0){    temp=P3;    switch(temp)    {      case0xeb: key=0;break;     case0xdb: key=1;break;     case0xbb: key=2;break;     case0x7b: key=3;break;    }    while(temp!=0xf0)   {     temp=P3;    temp=temp&0xf0;   }    if(key==0&&P1==0x44){//按键9:       num2=value3;    if(num1!=159){     num2++;     value3=num2;}      shi2=num2/10;    ge2=num2%10;      num1=value3+value4;//显示南北红灯时间    shi1=num1/10;    ge1=num1%10;      }    if(key==1&&P1==0x44){//按键10:    num2=value4;      if(num1!=159){     num2++;     value4=num2;    }      shi2=num2/10;    ge2=num2%10;  num1=value3+value4;//显示南北红灯时间    shi1=num1/10;    ge1=num1%10;    }     if(key==2&&P1==0x44&&value3>3){//按键11:    num2=value3;      num2--;    value3=num2;      shi2=num2/10;    ge2=num2%10;      num1=value3+value4;//显示南北红灯时间    shi1=num1/10;    ge1=num1%10;     }    if(key==3&&P1==0x44&&value4>3){//按键12:    num2=value4;  num2--;    value4=num2;      shi2=num2/10;    ge2=num2%10;     num1=value3+value4;//显示南北红灯时间    shi1=num1/10;    ge1=num1%10;     }   }    }    P3=0xf7;//第四行线    2未用  temp=P3;  temp=temp&0xf0;  if(temp!=0xf0)  {    delay(10);  temp=P3;   temp=temp&0xf0;   if(temp!=0xf0){    temp=P3;    switch(temp)    {      case0xe7:      key=0;      break;     case0xd7:      key=1;      break;     case0xb7:      key=2;      break;     case0x77:      key=3;      break;    }    while(temp!=0xf0)   {     temp=P3;  temp=temp&0xf0;   }    if(key==0&&P1==0x44){//按键13:    P1=0x41;     shi1=ge1=shi2=ge2=18;     }    if(key==1&&P1==0x44){//按键14:    P1=0x14;     shi1=ge1=shi2=ge2=18;    }     if(key==2&&P1==0x44){//按键15:       }    if(key==3&&P1==0x44){//按键16:       }   }    }    }/************************定时器T0 中断子程序 *********************************/   voidT0_time() interrupt 1   {   TH0=(65536-45872)/256;    //定时50ms  TL0=(65536-45872)%256;  num++; } 

    功能:十字路口的交通灯控制系统,四组灯(红黄绿)对应十字路口的四个方向,用两位的数码管显示剩余的时间。

    Processed: 0.008, SQL: 8