本人以前学过51单片机,知道ARM这个东西后一直向往,最近终于入手一块“战舰V3 精英板”(买板子的时候,没注意看板子资源,看到“精英”二字,以为是STM32F103ZET6板子里面最牛的,而且看价格还不是最贵的,果断买了精英板),经过几天的C语言学习、keil安装及使用学习、Jlink使用学习、工程模板(基于固件库)建立……我的STM32学习终于走上正轨。之前听过别人分享如何学习STM32,其中强调了一点,就是加入一个论坛,在论坛中跟大家一起学习,共同进步,于是今天就开贴(以前水过,从来没发过贴),从零开始学习STM32(以前学过51,但是没了解过STM32,不知道算不算从零开始),记录我的学习历程,记录一个系统性地学习STM32的过程,以求跟坛友共同进步,同时以后传递给别人准备学STM32的人一些经验。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
由于刚入手板子,又是周末,虽然我视频还没看到跑马灯这里来,但是还是忍不住想自己写下程序到板子上跑一下;
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了。
正在努力,一起加油!
这个周末过把手瘾,编完这个按键程序之后,就去看视频看书补理论去了;
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õê¼»ˉ
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE); //ê1ÄüPA,PEê±Öó
// KEY0 -> PE4 ; KEY1 -> PE3 ;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4;
// ÅäÖÃÕa¸ö֮ǰ£¬»1Ïë×ÅêÇ·ñóDÄ3ÖÖD′·¨£¬Äüí¬ê±Åä¶à¸öIOòy½Å£¬1ûè»óD
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //Ä£ê½éèÖÃÎaéÏà-êäèë
GPIO_Init(GPIOE, &GPIO_InitStructure);
// KEY_UP -> PA0 ;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //Ä£ê½éèÖÃÎaÏÂà-êäèë
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
// °′¼ü′|àíoˉêy£o¶áè¡°′¼ü×′쬣¬2¢·μ»Ø¼üÖμ
// 2Îêyo¬òå£o
// mode:SINGLE_TRIGGER,μ¥′Î′¥·¢£¬2»Ö§3Öᬰ′;CONTINUE_TRIGGER,Ö§3Öá¬Dø°′;
// ·μ»ØÖμo¬òå£o
// 0: ûóDèÎoΰ′¼ü°′ÏÂ
// KEY0_PRESS: KEY0°′ÏÂ
// KEY1_PRESS: KEY1°′ÏÂ
// WKUP_PRESS: WK_UP°′ÏÂ
// ±¸×¢£oÏìó|óÅÏ輶: KEY0>KEY1>WK_UP
u8 KEY_Scan(u8 mode)
{
static u8 key_up=1; //°′¼ü°′Ëé¿a±êÖ¾
if(mode)
key_up=1; //Ö§3Öᬰ′
if(key_up&&(KEY0==0||KEY1==0||WK_UP==1)) // óD¼ü°′ÏÂ
{
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) // ÎT¼ü°′ÏÂ
key_up=1; // ÎT¼ü°′Ï£¬¼′°′¼üËé¿a
return 0; // ÎT°′¼ü°′ÏÂ
}
[/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 //á¬Dø′¥·¢
#define KEY0_PRESS 1 //KEY0°′ÏÂ
#define KEY1_PRESS 2 //KEY1°′ÏÂ
#define WKUP_PRESS 3 //KEY_UP°′ÏÂ
void KEY_Init(void);//IO3õê¼»ˉ
u8 KEY_Scan(u8); //°′¼üé¨Ãè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¼ü°′ÏÂ
{
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 // ÎT¼ü°′ÏÂ
{
LED0 = 1;LED1 = 1;BEEP = 0;
}
delay_ms(50);
}
}
[/mw_shl_code]
4、仿真调试,思考总结,记录发帖;
下载的时候,没注意,下载了例程的文件进去,吓得我以为自己一上午的努力又有哪里出错了,赶紧去翻代码,发现并不是自己的代码,还有机会,然后下了自己的代码进去,运行结果跟预想的一样;
跑了LED,BEEP,KEY这几个程序,都是使用IO口的,对IO口的基本使用有了粗浅的了解,接下来就先不继续写程序跑了,看下视频,看下书,等理论学到了再实践,先打基础;
一周热门 更多>