从零开始学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-26 05:17
不知道怎么回事,可能是我复制了格式粘贴了,导致文字看不清楚……还是重发一下吧顺便把注释的乱码矫正
【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"

// 初始化
void KEY_Init(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);  //使能PA,PE时钟

   // KEY0 -> PE4 ; KEY1 -> PE3 ;
        GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_3|GPIO_Pin_4;
   // 配置这个之前,还想着是否有某种写法,能同时配多个IO引脚,果然有
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;   //模式设置为上拉输入
        GPIO_Init(GPIOE, &GPIO_InitStructure);

   // KEY_UP -> PA0 ;
        GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;   //模式设置为下拉输入
        GPIO_Init(GPIOA, &GPIO_InitStructure);

}

// 按键处理函数:读取按键状态,并返回键值
// 参数含义:
// mode:SINGLE_TRIGGER,单次触发,不支持连按;CONTINUE_TRIGGER,支持连续按;
// 返回值含义:
//          0: 没有任何按键按下
// KEY0_PRESS: KEY0按下
// KEY1_PRESS: KEY1按下
// WKUP_PRESS: WK_UP按下
// 备注:响应优先级: KEY0>KEY1>WK_UP
u8 KEY_Scan(u8 mode)
{         
        static u8 key_up=1;  //按键按松开标志
       
        if(mode)
           key_up=1;   //支持连按       
                     
        if(key_up&&(KEY0==0||KEY1==0||WK_UP==1))  // 有键按下
        {
                delay_ms(10);//去抖动
                key_up=0;
                if(KEY0==0)             // 键0按下
                   return KEY0_PRESS;
                else if(KEY1==0)        // 键1按下
                   return KEY1_PRESS;
                else if(WK_UP==1)       // 键WK_UP按下
                   return WKUP_PRESS;
        }
        else if(KEY0==1&&KEY1==1&&WK_UP==0)       // 无键按下
           key_up=1;   // 无键按下,即按键松开       
               
   return 0;   // 无按键按下
}
[/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)//读取KEY0
#define KEY1  GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)//读取KEY1
#define WK_UP   GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)//读取WK_UP

#define SINGLE_TRIGGER     0        //单次触发
#define CONTINUE_TRIGGER   1        //连续触发

#define KEY0_PRESS   1        //KEY0按下
#define KEY1_PRESS   2        //KEY1按下
#define WKUP_PRESS   3        //KEY_UP按下

void KEY_Init(void);//IO初始化
u8 KEY_Scan(u8);          //按键扫描函数               

#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)  // 有键按下
      {
         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           // 无键按下
      {
         LED0 = 1;LED1 = 1;BEEP = 0;
      }
      
      delay_ms(50);
        }
}
[/mw_shl_code]
4、仿真调试,思考总结,记录发帖;
    下载的时候,没注意,下载了例程的文件进去,吓得我以为自己一上午的努力又有哪里出错了,赶紧去翻代码,发现并不是自己的代码,还有机会,然后下了自己的代码进去,运行结果跟预想的一样;
    跑了LED,BEEP,KEY这几个程序,都是使用IO口的,对IO口的基本使用有了粗浅的了解,接下来就先不继续写程序跑了,看下视频,看下书,等理论学到了再实践,先打基础;

忘月19920216
2楼-- · 2019-07-26 05:24
 精彩回答 2  元偷偷看……
忘月19920216
3楼-- · 2019-07-26 05:32
it8345 发表于 2016-3-6 15:29
加油,帮顶,跟楼主差不多,我基本外设差不多都会用了,只是熟练度还差点,现在一边复习一边看UCOS,已经大 ...

哇哇,谢谢,你比我厉害多了我刚开始学,很多东西以前没接触过,要一步一步来;
蜗蜗猴
4楼-- · 2019-07-26 09:50
我个人觉得Key_up=0这句放在if(KEY0==0) 的下面会合理一点,不然感觉去抖无意义了
xug
5楼-- · 2019-07-26 11:39
加油,加油
忘月19920216
6楼-- · 2019-07-26 15:57
蜗蜗猴 发表于 2016-3-7 00:20
我个人觉得Key_up=0这句放在if(KEY0==0) 的下面会合理一点,不然感觉去抖无意义了

这里的逻辑是这样的:1、有键按下(不管是抖动还是真按);2、延时10ms;3、10ms后再检测是键是否按下,如果没有按下了,就认为是抖动,如果还是按下的,就认为是真按;
如果有键按下之后,没有延时,马上判断是否是键0按下,两次检测之间只隔了一个判断语句的时间,就可能没有达到去抖的效果;
当然,先判断是不是键0按下,再延时,也同样能够去抖的,因为这个键0的输出不会平白无故就为0,如果为0,就必被按下,然后再加一个延时,防止后续抖动造成误判,也到达了去抖的效果,这个在连续触发按键的时候起作用;

一周热门 更多>