从零开始学STM32(开贴记录我的学习历程)

2019-07-24 13:22发布

本人以前学过51单片机,知道ARM这个东西后一直向往,最近终于入手一块“战舰V3 精英板”(买板子的时候,没注意看板子资源,看到“精英”二字,以为是STM32F103ZET6板子里面最牛的,而且看价格还不是最贵的,果断买了精英板),经过几天的C语言学习、keil安装及使用学习、Jlink使用学习、工程模板(基于固件库)建立……我的STM32学习终于走上正轨。之前听过别人分享如何学习STM32,其中强调了一点,就是加入一个论坛,在论坛中跟大家一起学习,共同进步,于是今天就开贴(以前水过,从来没发过贴),从零开始学习STM32(以前学过51,但是没了解过STM32,不知道算不算从零开始),记录我的学习历程,记录一个系统性地学习STM32的过程,以求跟坛友共同进步,同时以后传递给别人准备学STM32的人一些经验。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
49条回答
忘月19920216
1楼-- · 2019-07-25 14:39
【2016-03-05】跑马灯
由于刚入手板子,又是周末,虽然我视频还没看到跑马灯这里来,但是还是忍不住想自己写下程序到板子上跑一下;
1、查看板子电路图,找到个LED分别连到MCU的IO口的哪个引脚;
2、查看原子跑马灯例程并理解过程(还不会STM32,先看着学,因为心急,还没看视频);
3、关掉例程,复制自己的空工程模板,写跑马灯代码;
4、仿真调试,思考总结,记录发帖;


1、查看板子电路图,找到个LED分别连到MCU的IO口的哪个引脚;
    我的板子是精英板:LED0->B5;LED1->E5;IO连接到LED阴极(IO口输出0点亮LED);
2、查看原子跑马灯例程并理解过程(还不会STM32,先看着学,因为心急,还没看视频);
    跑马灯程序编写思路:①配置IO口时钟->②配置IO口->③重复“LED0亮,LED1灭” <--> “LED0灭,LED1亮”两种状态切换,并在中间加适当延时;
3、复制自己的空工程模板,写跑马灯代码;
    直接写在main.c里面,以前听别人说这样的习惯不好,我准备调通了再学例程那样单独建个文件;
    这是我仿照例程新建工程模板的写法打的程序,函数从各个库文件里找到复制出来的;(写的第一个程序就失败了
[mw_shl_code=applescript,true]#include "stm32f10x.h"
#include "delay.h"
#include "stm32f10x_rcc.h"

int main(void)
{       
   
   GPIO_InitTypeDef GPIO_InitStructure;
   
   delay_init();
   RCC_APB1PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOE , ENABLE);
   
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
   
   GPIO_Init(GPIOB,&GPIO_InitStructure);
   GPIO_SetBits(GPIOB, GPIO_Pin_5);
   
   GPIO_Init(GPIOE,&GPIO_InitStructure);
   GPIO_SetBits(GPIOE, GPIO_Pin_5);
   
   while(1)
   {
      GPIO_SetBits(GPIOB, GPIO_Pin_5);
      GPIO_ResetBits(GPIOE, GPIO_Pin_5);
      delay_ms(500);
      GPIO_ResetBits(GPIOB, GPIO_Pin_5);
      GPIO_SetBits(GPIOE, GPIO_Pin_5);
      delay_ms(500);
   }
}[/mw_shl_code]
4、仿真调试;

    下载程序到板子上,发现没反应,怕自己没选择复位,就按下板子的复位,还是没反应,然后就去DEBUG,发现程序执行完配置IO口PB5那里后,IO口的PB5模式并没有变化,不得已,又打开例程,DEBUG,观察到执行配置PB5后,PB5模式变成想要设定的那样,然后我就把例程里的配置全部复制到我自己的工程里,一句一句地对,看自己是不是哪个字符写错了(虽然keil5没报错,但是第一次写程序,还是怕打错字),没有观察到哪里不一样,注释掉自己的,DEBUG例程那一段,PB5能正常配置,注释掉例程,DEBUG自己那一段,PB5不能正常配置,纳闷了,后面终于观察到“RCC_APB1PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOE , ENABLE);”这一句有问题,我怎么就复制个APB1的函数出来了,改成APB2,之后一切正常,自己的LED终于闪烁起来了;(之后去翻了下时钟系统相关的资料,知道了IO口是由APB2提供,不能有APB1提供)
    接下来就把LED的代码仿照例程“跑马灯”的样式写在一个led.c文件里,也仿照着写一个led.h文件(其实算是复制的),以后的工程里,就可以直接加入这个文件,使用LED了。


忘月19920216
2楼-- · 2019-07-25 15:03
黑夜之狼 发表于 2016-3-5 17:12
LZ好样的!一起加油!

正在努力,一起加油!
忘月19920216
3楼-- · 2019-07-25 17:52
 精彩回答 2  元偷偷看……
ChanTselin5213
4楼-- · 2019-07-25 19:05
加油 帮顶
it8345
5楼-- · 2019-07-25 20:01
加油,帮顶,跟楼主差不多,我基本外设差不多都会用了,只是熟练度还差点,现在一边复习一边看UCOS,已经大三了 ,时间好少啊~
忘月19920216
6楼-- · 2019-07-26 00:44
【2016-03-06】按键
这个周末过把手瘾,编完这个按键程序之后,就去看视频看书补理论去了;
1、查看板子电路图,找到各个按键分别连到MCU的IO口的哪个引脚;
2、查看原子按键例程并理解过程;
3、关掉例程,复制自己之前写的蜂鸣器工程(里面有LED和BEEP功能),写按键代码;
4、仿真调试,思考总结,记录发帖;

1、查看板子电路图,找到各个按键分别连到MCU的IO口的哪个引脚;
    精英板:KEY0 -> PE4 ; KEY1 -> PE3;KEY_UP -> PA0 ;
2、查看原子按键例程并理解过程;
    程序还是关于IO口的使用,只不过用的是输入模式(原子的板子上,三个按键既有高电平有效,也有低电平有效的,对学习来说非常棒);
   按键程序编写思路:①配置IO口时钟->②配置IO口->③一直检测按键状态,若有键按下,则判断是哪一个键,并执行对应的动作;
3、关掉例程,复制自己之前写的蜂鸣器工程(里面有LED和BEEP功能),写按键代码;
   老样子,写一个初始化函数,配置按键相关的IO口,再仿照着例程写一个读取按键状态的函数,在main函数里一直检测按键状态,有键按下就点亮一下对应的LED,顺便响一下蜂鸣器;
    这是key.c的代码:
[mw_shl_code=applescript,true]#include "key.h"
#include "stm32f10x.h"  
#include "stm32f10x_rcc.h"
#include "delay.h"

// 3&#245;ê&#188;&#187;ˉ
void KEY_Init(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);  //ê1&#196;üPA,PEê±&#214;ó

   // KEY0 -> PE4 ; KEY1 -> PE3 ;
        GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_3|GPIO_Pin_4;
   // &#197;&#228;&#214;&#195;&#213;a&#184;&#246;&#214;&#174;&#199;°£&#172;&#187;1&#207;&#235;×&#197;ê&#199;·&#241;óD&#196;3&#214;&#214;D′·¨£&#172;&#196;üí&#172;ê±&#197;&#228;&#182;à&#184;&#246;IOòy&#189;&#197;£&#172;1&#251;è&#187;óD
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;   //&#196;£ê&#189;éè&#214;&#195;&#206;aé&#207;à-ê&#228;è&#235;
        GPIO_Init(GPIOE, &GPIO_InitStructure);

   // KEY_UP -> PA0 ;
        GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;   //&#196;£ê&#189;éè&#214;&#195;&#206;a&#207;&#194;à-ê&#228;è&#235;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

}

// °′&#188;ü′|àíoˉêy£o&#182;áè&#161;°′&#188;ü×′ì&#172;£&#172;2¢·μ&#187;&#216;&#188;ü&#214;μ
// 2&#206;êyo&#172;ò&#229;£o
// mode:SINGLE_TRIGGER,μ¥′&#206;′¥·¢£&#172;2&#187;&#214;§3&#214;á&#172;°′;CONTINUE_TRIGGER,&#214;§3&#214;á&#172;D&#248;°′;
// ·μ&#187;&#216;&#214;μo&#172;ò&#229;£o
//          0: &#195;&#187;óDè&#206;o&#206;°′&#188;ü°′&#207;&#194;
// KEY0_PRESS: KEY0°′&#207;&#194;
// KEY1_PRESS: KEY1°′&#207;&#194;
// WKUP_PRESS: WK_UP°′&#207;&#194;
// ±&#184;×¢£o&#207;ìó|ó&#197;&#207;è&#188;&#182;: KEY0>KEY1>WK_UP
u8 KEY_Scan(u8 mode)
{         
        static u8 key_up=1;  //°′&#188;ü°′&#203;é&#191;a±ê&#214;&#190;
       
        if(mode)
           key_up=1;   //&#214;§3&#214;á&#172;°′       
                     
        if(key_up&&(KEY0==0||KEY1==0||WK_UP==1))  // óD&#188;ü°′&#207;&#194;
        {
                delay_ms(10);//è¥&#182;&#182;&#182;ˉ
                key_up=0;
                if(KEY0==0)             // &#188;ü0°′&#207;&#194;
                   return KEY0_PRESS;
                else if(KEY1==0)        // &#188;ü1°′&#207;&#194;
                   return KEY1_PRESS;
                else if(WK_UP==1)       // &#188;üWK_UP°′&#207;&#194;
                   return WKUP_PRESS;
        }
        else if(KEY0==1&&KEY1==1&&WK_UP==0)       // &#206;T&#188;ü°′&#207;&#194;
           key_up=1;   // &#206;T&#188;ü°′&#207;&#194;£&#172;&#188;′°′&#188;ü&#203;é&#191;a       
               
   return 0;   // &#206;T°′&#188;ü°′&#207;&#194;
}
[/mw_shl_code]
再仿照例程写一个key.h:
[mw_shl_code=applescript,true]#ifndef __KEY_H
#define __KEY_H         
#include "sys.h"

//#define KEY0 PEin(4)           //PE4
//#define KEY1 PEin(3)        //PE3
//#define WK_UP PAin(0)        //PA0  WK_UP

#define KEY0  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)//&#182;áè&#161;KEY0
#define KEY1  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)//&#182;áè&#161;KEY1
#define WK_UP   GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//&#182;áè&#161;WK_UP

#define SINGLE_TRIGGER     0        //μ¥′&#206;′¥·¢
#define CONTINUE_TRIGGER   1        //á&#172;D&#248;′¥·¢

#define KEY0_PRESS   1        //KEY0°′&#207;&#194;
#define KEY1_PRESS   2        //KEY1°′&#207;&#194;
#define WKUP_PRESS   3        //KEY_UP°′&#207;&#194;

void KEY_Init(void);//IO3&#245;ê&#188;&#187;ˉ
u8 KEY_Scan(u8);          //°′&#188;üé¨&#195;èoˉêy               

#endif
[/mw_shl_code]
然后main.c这样写:
[mw_shl_code=applescript,true]#include "stm32f10x.h"
#include "led.h"
#include "beep.h"
#include "delay.h"
#include "key.h"

int main(void)
{       
   vu8 key_value;
  
   LED_Init();  
   BEEP_Init();
   delay_init();
   KEY_Init();
   
   while(1)
        {
      key_value = KEY_Scan(SINGLE_TRIGGER);
      
      if(key_value)  // óD&#188;ü°′&#207;&#194;
      {
         switch(key_value)
         {   
            case KEY0_PRESSED0 = 0;LED1 = 1;BEEP = 1;break;
            case KEY1_PRESSED0 = 1;LED1 = 0;BEEP = 1;break;
            case WKUP_PRESSED0 = 0;LED1 = 0;BEEP = 1;break;
            defaultED0 = 1;LED1 = 1;BEEP = 1;break;
         }
      }
      else           // &#206;T&#188;ü°′&#207;&#194;
      {
         LED0 = 1;LED1 = 1;BEEP = 0;
      }
      
      delay_ms(50);
        }
}
[/mw_shl_code]
4、仿真调试,思考总结,记录发帖;
    下载的时候,没注意,下载了例程的文件进去,吓得我以为自己一上午的努力又有哪里出错了,赶紧去翻代码,发现并不是自己的代码,还有机会,然后下了自己的代码进去,运行结果跟预想的一样;
    跑了LED,BEEP,KEY这几个程序,都是使用IO口的,对IO口的基本使用有了粗浅的了解,接下来就先不继续写程序跑了,看下视频,看下书,等理论学到了再实践,先打基础;

一周热门 更多>