笔记(STM32篇)day3——寄存器结构体、端口置位函数

目录

一些C知识点

1、#define和typedef的区别

2、结构体struct

3、结构体中.和->的区别

4、.c文件和.h文件的关系

5、防止重复引用

一、寄存器结构体定义

1、定义结构体变量指针

 2、寄存器赋值

二、端口置位函数

1、端口置位.c文件

2、端口置位.h文件

3、调用

遇到的问题

参考


一些C知识点

1、#define和typedef的区别

        #define为一宏定义语句,通常用它来定义常量(包括无参量与带参量)或者公式,在预处理之后的.i文件中就完成替换。定义在前,原文本在后。

        typedef为关键字,可以使用它为变量取别名,但仅限为类型定义名称,由编译器执行解释。类型在前,别名在后。与define不同,typedef后需要加引号。此外如本文,typedef也可定义结构变量。

#define     Max            255
#define     Add(a,b)       ((a)+(b))
typedef    unsigned int   uint32_t;

2、结构体struct

        结构体声明格式:Book为结构体名称,book为结构体变量名。

struct Book
{
    char title[128];
    char author[40];
}book;

3、结构体中.和->的区别

        ->:用在结构体指针的后面;
        . :用在结构体后面(".“这个运算符可以理解为中文里"的”);

        (*a).b 等价于a->b

4、.c文件和.h文件的关系

        一般来说二者没有本质区别,.h文件是头文件,内含函数声明、宏定义、结构体定义等内容;.c文件是程序文件,内含函数实现,变量定义等内容。

        func.h里声明函数,在func.h同一目录下建立func.c ,func.c里定义了这个函数的内容。如果在main函数所在.c文件里#include这个func.h 后,main函数运行时就会直接找到func.c的函数并运行。

5、防止重复引用

        为防止重复引用,习惯在每个头文件里用条件指示符#ifndef。

#ifndef _STM32F10X_H
#define _STM32F10X_H
    //text
#endif

一、寄存器结构体定义

1、定义结构体变量指针

        如图1所示,GPIO的七个寄存器从每个GPIO的基地址开始,按每32位即每4个字节一个寄存器排列,因此可以使用结构体为GPIO的寄存器分配一块连续内存,结构体内有七个成员对应七个寄存器,以此方便对各个寄存器的配置操作。

图1 GPIO寄存器地址映像和复位值

         如下代码所示,结构体变量为GPIO_TypeDef,所有GPIO内部的寄存器都是这种结构,都可以使用这种结构体去操作内部成员寄存器。因此,如果使用GPIOB,则需要将GPIOB_BASE基地址转化为这种结构体类型的指针,并宏定义为GPIOB。

typedef unsigned int		uint32_t;
typedef unsigned short		uint16_t;

typedef struct
{
	uint32_t CRL;
	uint32_t CRH;
	uint32_t IDR;
	uint32_t ODR;
	uint32_t BSRR;
	uint32_t BRR;
	uint32_t LCKR;
}GPIO_TypeDef;

#define    GPIOB	((GPIO_TypeDef*)GPIOB_BASE)		//GPIOB定义为GPIO_TypeDef类型的指针

 2、寄存器赋值

       通过以上定义,要操作GPIOB的CRL寄存器,代码对比如下:

GPIOB_CRL |= ((1)<<(4*0));
GPIOB->CRL |= ((1)<<(4*0));	
//二者作用相同

二、端口置位函数

       在对端口置位、复位时,与使用移位等位操作相比,写好端口操作函数直接调用来的更方便。

1、端口置位.c文件

        形参为结构变量类型的指针,和端口位。

/**********    stm32f10x_gpio.c    **********/
#include "stm32f10x_gpio.h"

void GPIO_SetBits(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin)
{
	GPIOx ->BSRR |= GPIO_Pin;
}

2、端口置位.h文件

        对于置位函数,要设置端口的某一位为1,在BSRR寄存器中,低16位为置位功能,即0不影响,1则置位1。因此,可以使用宏定义,若要将寄存器首位置位,则定义GPIO_Pin_0为0x0001,GPIO_Pin_1为0x0002,GPIO_Pin_2为0x0004,以此类推。同时别忘了在头文件中声明函数。

/**********    stm32f10x_gpio.h    **********/
#ifndef _STM32F10X_GPIO_H
#define _STM32F10X_GPIO_H

#include "stm32f10x.h"

#define GPIO_Pin_0    ((uint16_t)0x0001)  /*!< 选择Pin0 */    //(00000000 00000001)b
#define GPIO_Pin_1    ((uint16_t)0x0002)  /*!< 选择Pin1 */    //(00000000 00000010)b
#define GPIO_Pin_2    ((uint16_t)0x0004)  /*!< 选择Pin2 */    //(00000000 00000100)b
#define GPIO_Pin_3    ((uint16_t)0x0008)  /*!< 选择Pin3 */    //(00000000 00001000)b
#define GPIO_Pin_4    ((uint16_t)0x0010)  /*!< 选择Pin4 */    //(00000000 00010000)b
#define GPIO_Pin_5    ((uint16_t)0x0020)  /*!< 选择Pin5 */    //(00000000 00100000)b
#define GPIO_Pin_6    ((uint16_t)0x0040)  /*!< 选择Pin6 */    //(00000000 01000000)b
#define GPIO_Pin_7    ((uint16_t)0x0080)  /*!< 选择Pin7 */    //(00000000 10000000)b

#define GPIO_Pin_8    ((uint16_t)0x0100)  /*!< 选择Pin8 */    //(00000001 00000000)b
#define GPIO_Pin_9    ((uint16_t)0x0200)  /*!< 选择Pin9 */    //(00000010 00000000)b
#define GPIO_Pin_10   ((uint16_t)0x0400)  /*!< 选择Pin10 */   //(00000100 00000000)b
#define GPIO_Pin_11   ((uint16_t)0x0800)  /*!< 选择Pin11 */   //(00001000 00000000)b
#define GPIO_Pin_12   ((uint16_t)0x1000)  /*!< 选择Pin12 */   //(00010000 00000000)b
#define GPIO_Pin_13   ((uint16_t)0x2000)  /*!< 选择Pin13 */   //(00100000 00000000)b
#define GPIO_Pin_14   ((uint16_t)0x4000)  /*!< 选择Pin14 */   //(01000000 00000000)b
#define GPIO_Pin_15   ((uint16_t)0x8000)  /*!< 选择Pin15 */   //(10000000 00000000)b
#define GPIO_Pin_All  ((uint16_t)0xFFFF)  /*!< 选择全部引脚*/ //(11111111 11111111)b

void GPIO_SetBits(GPIO_TypeDef *GPIOx,uint16_t GPIO_Pin);

#endif	/*_STM32F10X_GPIO_H*/

3、调用

        使用时,在主程序中调用即可。GBIOB已经被定义为GPIO_TypeDef类型的指针,GPIO_Pin_0已经被定义为0x0001。

GPIO_SetBits(GPIOB,GPIO_Pin_0);

遇到的问题

        让LED闪烁,程序看不出问题,但只要是在while里的程序就不会执行,led只会常亮或者常灭,百度这个问题,有优化等级的原因,原来是O1,改成O0不优化就没有问题了,具体为什么不优化就可以运行,暂时不清楚。

int main(void)
{ 
	RCC_APB2ENR |= (1<<3);		
    //控制RCC寄存器打开时钟,RCC偏移0x18为APB2时钟,寄存器第三位为PB使能

	GPIOB_CRL &= ~((0x0F)<<(4*0));
	//初始化,低4位为一组,全部置0
	GPIOB->CRL |= ((1)<<(4*0));		
    //控制GPIOB_CRL低位配置寄存器,GPIOB偏移0x00,PB0通用推挽输出00,模式为输出01
	
	while(1)
	{	
		GPIOB->ODR &= ~(1<<0);		
		Delay_ms(500);
		GPIOB->ODR |= (1<<0);	
		Delay_ms(500);
	}

}

参考

https://doc.embedfire.com/mcu/stm32/f103zhinanzhe/std/zh/latest/index.html

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值