本帖最后由 zzq宁静致远 于 2013-10-12 09:47 编辑
第二节 STM32小试牛刀——LED
这是基本上所有的学习者第一步学习的程序,因为简单。但是我看过的程序都是千篇一律,其实再简单的一个程序都要注重模块化编程,这是朱兆祺要告诉大家的第一个经验,因为只有这样,你的代码才能复用。
我们看下最底层我们的配置,这一层是直接和底层硬件打交道:
/********************************************************************
** 函数名称:LED_Configuration
** 函数功能:对LED1-LED5的配置
** 入口参数:None
** 出口参数:None
********************************************************************/
void LED_Configuration (void)
{
/*
LED_InitStructure structure
typedef struct
{
u16 GPIO_Pin;
GPIOSpeed_TypeDef GPIO_Speed;
GPIOMode_TypeDef GPIO_Mode;
} GPIO_InitTypeDef ;
*/
GPIO_InitTypeDef GPIO_InitStructure;
/* Configure all unused GPIO port pins in Analog Input mode (floating input
trigger OFF), this will reduce the power consumption and increase the device
immunity against EMI/EMC *************************************************/
/* 将GPIOA、GPIOB、GPIOC、GPIOD、GPIOE使能 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD |
RCC_APB2Periph_GPIOE, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
/*
void GPIO_Init(GPIO_TypeDef* GPIOx,
GPIO_InitTypeDef* GPIO_InitStruct)
根据GPIO_InitStruct中指定的参数初始化外设GPIOx寄存器
*/
#if 0
GPIO_Init(GPIOA | GPIOB | GPIOC | GPIOD | GPIOE ,
&GPIO_InitStructure) ;
#endif
#if 1
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_Init(GPIOE, &GPIO_InitStructure);
#endif
/* 将GPIOA、GPIOB、GPIOC、GPIOD、GPIOE禁能 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD |
RCC_APB2Periph_GPIOE, DISABLE);
#ifdef USE_STM3210E_EVAL
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG, ENABLE);
GPIO_Init(GPIOF, &GPIO_InitStructure);
GPIO_Init(GPIOG, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG, DISABLE);
#endif /* USE_STM3210E_EVAL */
/* Configure IO connected to LD1, LD2, LD3 and LD4 leds *********************/
/* Enable GPIO_LED clock */
/*
#define GPIO_LED GPIOF
#define RCC_APB2Periph_GPIO_LED RCC_APB2Periph_GPIOF
使能GPIOF
*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIO_LED, ENABLE);
/*
GPIOF的678910四个引脚控制五个LED
0000 0000 0000 0000
*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIO_LED, &GPIO_InitStructure);
/*
void GPIO_Write(GPIO_TypeDef* GPIOx, u16 PortVal)
向指定GPIO数据端口写入数据
GPIOx:x可以是A,B,C,D或者E,来选择GPIO外设
PortVal: 待写入端口数据寄存器的值
*/
GPIO_Write(GPIOF, 0xffff);
}
底层文件配置完成之后,中间层是作为底层硬件和上层应用之间的枢纽:
#ifndef _LEDCONFIG_H_
#define _LEDCONFIG_H_
/* 包含配置文件 */
#include "stm32f10x_lib.h"
#include "platform_config.h"
/* 连接LED1引脚输出高电平,即LED1熄灭 */
#define LED1OFF() GPIO_SetBits(GPIO_LED , GPIO_Pin_6)
/* 连接LED1引脚输出低电平,即LED1点亮 */
#define LED1ON() GPIO_ResetBits(GPIO_LED , GPIO_Pin_6)
/* 连接LED2引脚输出高电平,即LED2熄灭 */
#define LED2OFF() GPIO_SetBits(GPIO_LED , GPIO_Pin_7)
/* 连接LED2引脚输出低电平,即LED2点亮 */
#define LED2ON() GPIO_ResetBits(GPIO_LED , GPIO_Pin_7)
/* 连接LED3引脚输出高电平,即LED3熄灭 */
#define LED3OFF() GPIO_SetBits(GPIO_LED , GPIO_Pin_8)
/* 连接LED3引脚输出低电平,即LED3点亮 */
#define LED3ON() GPIO_ResetBits(GPIO_LED , GPIO_Pin_8)
/* 连接LED4引脚输出高电平,即LED4熄灭 */
#define LED4OFF() GPIO_SetBits(GPIO_LED , GPIO_Pin_9)
/* 连接LED4引脚输出低电平,即LED4点亮 */
#define LED4ON() GPIO_ResetBits(GPIO_LED , GPIO_Pin_9)
/* 连接LED5引脚输出高电平,即LED5熄灭 */
#define LED5OFF() GPIO_SetBits(GPIO_LED , GPIO_Pin_10)
/* 连接LED5引脚输出低电平,即LED5点亮 */
#define LED5ON() GPIO_ResetBits(GPIO_LED , GPIO_Pin_10)
#endif
作为顶层文件,是单独的一个文件,这一层所要具备的是不管放在什么平台、什么系统下面都可以运行。
int main(void)
{
#ifdef DEBUG
debug();
#endif
/* 系统时钟配置 */
RCC_Configuration();
/* 中断向量配置 */
NVIC_Configuration();
/* LED配置 */
LED_Configuration();
while (1)
{
LED1ON();
}
}
通过这个程序,你看到了是哪个引脚在控制LED灯吗?不知道,那么,我换一个平台是不是照样可以运行。其实还可以进一步进行包装,但是要注意,是不是模块化怎么样就怎么样,非也,技术含量就在于此。