1、外设库的结构介绍
(1)标准外设库的下载和解压 en.stsw-stm32054.zip
(2)建立SourceInsight工程
(3)文件夹结构和主要文件的作用
2.标准库对硬件信息的封装方式
(1)寄存器地址的封装-----以TIM2为例:
- 先定义外设TIM2的基地址
- 再用结构体封装该外设的所有寄存器
- 通过指向各个外设的指针访问各外设的控制寄存器。这些指针所指向的数据结构与各个外设的控
制寄存器布局一一对应把外设的基地址转换成该结构体类型的指针
(2)寄存器位定义的封装-----以RCC模块为例:
(3)外设操作的封装-----以RCC模块为例:
对RCC的各种操作都被封装成若干函数
3.使用结构体方式访问寄存器的原理
(1)C语言访问寄存器的本质是C语言访问内存,本质思路是:定义一个指针(临时变量)指向这块内存,然后*p = xx这种方式去解引用指针从而向目标内存中写入内容。
(2)缺陷:当寄存器多了之后每一个寄存器都要定义一套套路,很麻烦。
(3)解决思路:就是打包,批发式的定义,用结构体(想一下为什么不用数组?)的方式进行打包。具体做法是:把整个一个模块的所有寄存器(地址是连接的)打包在一个结构体中,每个寄存器对应结构体中的一个元素,然后结构体基地址对应寄存器组的基地址,将来就可以通过结构体的各个元素来访问各个寄存器了。
(4)结构体方式来访问寄存器和指针式访问寄存器,本质上其实是一样的,区别是C语言的封装不同。
(5)实现代码-----实现LED闪烁
使用结构体方式访问寄存器---------以GPIO模块为例
gpio.h
#ifndef __GPIO_H__
#define __GPIO_H__
#define GPIOB_BASE 0x40010C00 //LED接的是GPIOB端口
#define GPIOB_CRH (GPIOB_BASE + 0x04)
#define GPIOB_ODR (GPIOB_BASE + 0x0C)
#define GPIOB_BSRR (GPIOB_BASE + 0x10)
#define GPIOB_BRR (GPIOB_BASE + 0x14)
#define RCC_APB2ENR 0x40021018
//-------------------------------------------------
#define rGPIOB_CRH (*((unsigned int *)GPIOB_CRH))
#define rGPIOB_ODR (*((unsigned int *)GPIOB_ODR))
#define rGPIOB_BSRR (*((unsigned int *)GPIOB_BSRR))
#define rGPIOB_BRR (*((unsigned int *)GPIOB_BRR))
#define rRCC_APB2ENR (*((unsigned int *)RCC_APB2ENR))
// 用结构体的方式对寄存器访问
typedef struct
{
volatile unsigned int CRL;
volatile unsigned int CRH;
volatile unsigned int IDR; // 定义为32位
volatile unsigned int ODR;
volatile unsigned int BSRR; // 10
volatile unsigned int BRR;
volatile unsigned int LCKR;
}GPIO_Typedef;
GPIO_Typedef *pGPIOB = (GPIO_Typedef *)GPIOB_BASE;
gpio.c
#include "gpio.h"
void main(void)
{
led_init();
led_flash();
while (1);
}
void led_init(void)
{
// 因为RCC部分还没有定义结构体,所以还按照原来的方式去操作
rRCC_APB2ENR = 0x00000008; //要打开GPIOB的外设时钟才能驱动GPIO端口
pGPIOB->CRH = 0x33333333;
pGPIOB->ODR = 0x0000AA00;
}
void led_flash(void) //LED闪烁3下
{
unsigned int i = 0;
for (i=0; i<3; i++)
{
pGPIOB->ODR = 0x0000ff00; // 全亮
delay();
pGPIOB->ODR = 0x00000000; // 全灭
delay();
}
}
void delay(void) //延时函数
{
unsigned int i, j;
for (i=0; i<1000; i++)
for (j=0; j<2000; j++);
}