零、所需文件及环境:
1、第一章建立好的LED灯闪烁程序
2、编译环境MDK5(KEIL5)
3、一个STM32F103C8T6硬件
4、一个下载器j-link 或 st-link等
5.代码编辑器 Notepad++ (可以不要 用记事本也能编译 都是习惯的问题)
壹、复制LED灯闪烁程序
1.1 复制led灯闪烁程序并进行重命名
贰、修改BSP_LED.h代码
2.1 仔细阅读参考手册找到GPIO寄存器地址,将一堆GPIO寄存器一层一层封装出来 方便控制 直接操作的是寄存器 可以自己写但没有必要,挨个核对寄存器地址时特别费时,所以我这里复制的 原子的sys.h里面的 将其添加进之前的BSP_LED.h里面 修改后的文件如图所示
#ifndef __BSP_LED_H
#define __BSP_LED_H
#include "stm32f10x.h"
//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).
//IO口操作宏定义
#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))
//IO口地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C
#define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C
#define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C
#define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C
#define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C
#define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C
#define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C
#define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808
#define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08
#define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008
#define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408
#define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808
#define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08
#define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#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) //输入
#define CPU_LED PBout(9)
//定义一个宏 以后改起来方便只需要修改宏就可以
#define LED_PIN GPIO_Pin_9
#define LED_GPIO_PORT GPIOB
#define LED_GPIO_CLK RCC_APB2Periph_GPIOB
//根据自己实际硬件定义 有的是输出高亮 有的是输出低亮
//GPIO_SetBits(LED_GPIO_PORT,LED_PIN); //输出高
//GPIO_ResetBits(LED_GPIO_PORT,LED_PIN); //输出低
#define CPU_LED_ON GPIO_ResetBits(LED_GPIO_PORT,LED_PIN)
#define CPU_LED_OFF GPIO_SetBits(LED_GPIO_PORT,LED_PIN)
extern void BSP_LED_Init(void);
#endif
叁、编写BSP_TIMER.c与BSP_TIMER.h代码
3.1 进入USER/BSP文件夹下 复制LED文件夹改为TIMER
3.2 进入USER/BSP/TIMER文件夹,修改文件名
3.3 打开BSP_TIMER.h修改为
#ifndef __BSP_TIMER_H
#define __BSP_TIMER_H
#include "stm32f10x.h"
extern void BSP_TIMER_Init(void);
#endif
3.4 打开BSP_TIMER.c修改为
#include "BSP_TIMER.h"
#include "BSP_LED.h"
#define BSP_TIMERx TIM2
#define BSP_TIMERx_IRQn TIM2_IRQn
#define BSP_TIMERx_Priority 5 //中断函数接口(见stm32f10x_it.c)
#define BSP_TIMERx_IRQHandler TIM2_IRQHandler
#define BSP_TIMERx_CLK RCC_APB1Periph_TIM2
//F1定时器中断时间 = (Period +1)*(Prescaler+1)/72M
//(7200 - 1+1)*(1000 - 1+1)/72M = 0.1S
//100ms定时器
void BSP_TIMER_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(BSP_TIMERx_CLK, ENABLE); //时钟使能
//定时器TIMx初始化
TIM_TimeBaseStructure.TIM_Period = 7200 - 1; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler = 1000 - 1; //设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
TIM_TimeBaseInit(BSP_TIMERx, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
TIM_ITConfig(BSP_TIMERx,TIM_IT_Update,ENABLE ); //使能指定的TIMx中断,允许更新中断
NVIC_InitStructure.NVIC_IRQChannel = BSP_TIMERx_IRQn; /* 选择TIMx的中断通道 */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = BSP_TIMERx_Priority; /* 抢占式中断优先级*/
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /* 响应式中断优先级设置为0 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; /* 使能中断 */
NVIC_Init(&NVIC_InitStructure); /* 中断初始化 */
TIM_Cmd(BSP_TIMERx, ENABLE); //使能TIMx
}
/* 定时器中断向量 */
void BSP_TIMERx_IRQHandler(void)
{
if(TIM_GetITStatus(BSP_TIMERx, TIM_IT_Update) != RESET) /* 定时器2溢出标志位 */
{
TIM_ClearITPendingBit(BSP_TIMERx , TIM_FLAG_Update); /* 定时器清除溢出标志位 */
CPU_LED = ~CPU_LED;
}
}
肆、打开工程,将BSP_TIMER.c添加入工程并添加头文件路径
伍、修改main函数
#include "stm32f10x.h"
#include "BSP_LED.h"
#include "BSP_DELAY.h"
#include "BSP_TIMER.h"
int main(void)
{
BSP_LED_Init();
// BSP_DELAY_Init();
BSP_TIMER_Init();
while(1)
{
// CPU_LED_ON;
// BSP_DELAY_ms(500);
// CPU_LED_OFF;
// BSP_DELAY_ms(500);
}
}