STM32学习了有一阵子了,现做一个简单的总结。
先上一个跑马灯的小程序,本人学习过程中先学习了一些STM32F103的一些基本知识,但是直到接触到真实的程序后开始思索看代码后一些模糊的概念才发现原先学习的基础感念都提到过,不过当时在学习的时候仅仅过了遍脑子没有理解了,故在此我先贴出跑马灯的程序,然后通过程序拓展出STM32编程必知的基础。
1、跑马灯
什么是跑马灯,本篇的程序实现的功能是板子上的两个小灯来回的闪烁。
下面将贴出寄存器版和库函数版两版源码。
1)寄存器版
main.c
#include "sys.h"
#include "delay.h"
#include "led.h"
int main(void)
{
delay_init();
LED_Init();
while(1)
{
LED0=0;
LED1=1;
delay_ms(300);
LED0=1;
LED1=0;
delay_ms(300);
}
}
sys.h
#ifndef __SYS_H
#define __SYS_H
#include "stm32f10x.h"
#define SYSTEM_SUPPORT_OS 0
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
#define GPIOA_ODR_Addr (GPIOA_BASE+12)
#define GPIOB_ODR_Addr (GPIOB_BASE+12)
#define GPIOC_ODR_Addr (GPIOC_BASE+12)
#define GPIOD_ODR_Addr (GPIOD_BASE+12)
#define GPIOE_ODR_Addr (GPIOE_BASE+12)
#define GPIOF_ODR_Addr (GPIOF_BASE+12)
#define GPIOG_ODR_Addr (GPIOG_BASE+12)
#define GPIOA_IDR_Addr (GPIOA_BASE+8)
#define GPIOB_IDR_Addr (GPIOB_BASE+8)
#define GPIOC_IDR_Addr (GPIOC_BASE+8)
#define GPIOD_IDR_Addr (GPIOD_BASE+8)
#define GPIOE_IDR_Addr (GPIOE_BASE+8)
#define GPIOF_IDR_Addr (GPIOF_BASE+8)
#define GPIOG_IDR_Addr (GPIOG_BASE+8)
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n)
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n)
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n)
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n)
#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n)
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n)
#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n)
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n)
#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n)
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n)
#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n)
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n)
#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n)
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n)
#endif
led.h
#ifndef __LED_H
#define __LED_H
#include "sys.h"
#define LED0 PBout(5)
#define LED1 PEout(5)
void LED_Init(void);
#endif
led.c
#include "led.h"
void LED_Init(void)
{
RCC->APB2ENR|=1<<3;
RCC->APB2ENR|=1<<6;
GPIOB->CRL&=0XFF0FFFFF;
GPIOB->CRL|=0X00300000;
GPIOB->ODR|=1<<5;
GPIOE->CRL&=0XFF0FFFFF;
GPIOE->CRL|=0X00300000;
GPIOE->ODR|=1<<5;
}
delay.h
#ifndef __DELAY_H
#define __DELAY_H
#include "sys.h"
void delay_init(void);
void delay_ms(u16 nms);
void delay_us(u32 nus);
#endif
delay.c
#include "delay.h"
static u8 fac_us=0;
static u16 fac_ms=0;
void delay_init()
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
fac_us=SystemCoreClock/8000000;
fac_ms=(u16)fac_us*1000;
}
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD=nus*fac_us;
SysTick->VAL=0x00;
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16)));
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;
SysTick->VAL =0X00;
}
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms;
SysTick->VAL =0x00;
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;
do
{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16)));
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;
SysTick->VAL =0X00;
}
#endif
2、库函数版
main.c
#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
int main(void)
{
delay_init();
LED_Init();
while(1)
{
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
GPIO_SetBits(GPIOE,GPIO_Pin_5);
delay_ms(300);
GPIO_SetBits(GPIOB,GPIO_Pin_5);
GPIO_ResetBits(GPIOE,GPIO_Pin_5);
delay_ms(300);
}
}
led.h
#ifndef __LED_H
#define __LED_H
void LED_Init(void);
#endif
led.c
#include "led.h"
void LED_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_5);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_SetBits(GPIOE,GPIO_Pin_5);
}
上面的代码即是一个跑马灯程序的源码了,其中sys.h为正点原子为我们可以实现51类似的GPIO控制功能,定义的一些宏定义。
2、罗列问题
看了上述的单片机入门学习代码(类似语言学习入门代码helloword),想必会有很多疑问提出来,下面会罗列一些学习方面的问题,然后在一个一个的给予解释。
1)开发工具使用MDK5,工程项目如何建立
2)GPIO是什么,程序中用到的GPIOB、GPIOE这些宏定义代表什么
3)stm32f103是什么
4)为何要使能PB、PE端口时钟
5)库函数编程函数都表示的是什么
3、解释问题
1)开发工具使用MDK5,工程项目如何建立
1-1)使用MDK5新建工程,工程建好后,通过右键工程项目菜单“Manage project items…”将相应的基本开发库函数源码填入进来,下图是本程序用到的基础库的介绍,请看图
要使程序编译成功,还需在 “Options for target ‘marquee’”弹出框中设置 “C/C++”相应配置项
①设置“Preprocessor Symbols”,如下图
②设置 “Include Paths”,即设置相应库函数的目录,如下图
USE_STDPERIPH_DRIVER :表示是否在应用中启用外设驱动。我们使用标准外设库是为了方便控制外设,添加这个定义,以启用外设驱动。( to use or not the peripheral’s drivers in application code (i.e. code will be based on direct access to peripheral’s registers rather than drivers API) , this option is controlled by the
#define USE_STDPERIPH_DRIVER)
STM32F10X_HD:STM32F10X系列每种系列都有所区别,例如sram或者flash或者外设数量不一样,所以stm32标准外设库必须根据你使用的处理器来做相应的预处理。
在stm32f10x.h可以看到相应的宏定义,如下:
#if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL) && !defined (STM32F10X_MD) && !defined (STM32F10X_MD_VL) && !defined (STM32F10X_HD) && !defined (STM32F10X_HD_VL) && !defined (STM32F10X_XL) && !defined (STM32F10X_CL)
#endif
#if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL) && !defined (STM32F10X_MD) && !defined (STM32F10X_MD_VL) && !defined (STM32F10X_HD) && !defined (STM32F10X_HD_VL) && !defined (STM32F10X_XL) && !defined (STM32F10X_CL)
#error "Please select first the target STM32F10x device used in your application (in stm32f10x.h file)"
#endif
1-2)采用ST-Link下载程序
使用ST-Link方式下载程序我们可以使用debug功能在线调试代码,建议开发阶段使用这种方式。
ST-Link方式下载程序设置方式如下图:
在debug页签中选中“ST-Link debugger”,点击“Setting”修改 Debug Adpater为“ST-Link/V2”,
安照图设置”CPU DLL”为SARMCM3.DLL、“Parameter”为 -REMAP;设置“Debug DLL”为DARMSTM.DLL、“Parameter”为-pSTM32F103ZE;设置“Driver DLL”为SARMCM3.DLL;设置“Dialog DLL”为TARMSTM.DLL、Parameter”为-pSTM32F103ZE;
除了上图设置还需要设置“Cortex-M Target Driver Setup”中的“Flash Download”选中 Reset and Run,如下图
ST-Link实物连接如下图:
1-3)修改程序编译结果为hex文件
mdk5默认输出是不选中Create Hex File选项的,我们需要选中,如下图:

按照上面步骤设置好环境后,编译下载到板子上,跑马灯程序即可运行,运行效果如下图:

碍于篇幅长度,问题中的2~5后续文章会一一解释记录。