以STM32F103为例,记录一下自己对STM32中GPIO初始化的理解:
1 void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
功能描述: 根据GPIO_InitStruct中指定的参数初始化外设GPIOx寄存器
输入参数1:GPIOx //GPIOx:x 可以是 A,B,C,D 或者 E,来选择 GPIO 外设
输入参数2:GPIO_InitStruct //GPIO_InitStruct:指向结构 GPIO_InitTypeDef 的指针,包含了外设 GPIO 的配置信息
如:管脚号,速度,模式等(GPIO_Pin,GPIO_Speed,GPIO_Mode)
参阅 Section:GPIO_InitTypeDef 查阅更多该参数允许取值范围
GPIO_Init:有二个参数,均为结构体指针,右键Go To definition :可以查看函数的定义
/** * @brief General Purpose I/O */ typedef struct { __IO uint32_t CRL; //端口配置低寄存器 __IO uint32_t CRH; //端口配置高寄存器 __IO uint32_t IDR; //端口输入数据寄存器 __IO uint32_t ODR; //端口输出数据寄存器 __IO uint32_t BSRR; //端口位设置/复位寄存器 __IO uint32_t BRR; //端口位复位寄存器 __IO uint32_t LCKR; //端口配置锁定寄存器 } GPIO_TypeDef;
/** * @brief GPIO Init structure definition */ typedef struct { uint16_t GPIO_Pin; /*!< Specifies the GPIO pins to be configured. This parameter can be any value of @ref GPIO_pins_define */ GPIOSpeed_TypeDef GPIO_Speed; /*!< Specifies the speed for the selected pins. This parameter can be a value of @ref GPIOSpeed_TypeDef */ GPIOMode_TypeDef GPIO_Mode; /*!< Specifies the operating mode for the selected pins. This parameter can be a value of @ref GPIOMode_TypeDef */ }GPIO_InitTypeDef;
函数原型如下:
1 /** 2 * @brief Initializes the GPIOx peripheral according to the specified 3 * parameters in the GPIO_InitStruct. 4 * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. 5 * @param GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure that 6 * contains the configuration information for the specified GPIO peripheral. 7 * @retval None 8 */
9 void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) 10 { 11 uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00; 12 uint32_t tmpreg = 0x00, pinmask = 0x00; 13 /* Check the parameters */
14 assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); 15 assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode)); 16 assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin)); 17
18 /*---------------------------- GPIO Mode Configuration -----------------------*/
19 currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F); 20 if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00) 21 { 22 /* Check the parameters */
23 assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed)); 24 /* Output mode */
25 currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed; 26 } 27 /*---------------------------- GPIO CRL Configuration ------------------------*/
28 /* Configure the eight low port pins */
29 if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00) 30 { 31 tmpreg = GPIOx->CRL; 32 for (pinpos = 0x00; pinpos < 0x08; pinpos++) 33 { 34 pos = ((uint32_t)0x01) << pinpos; 35 /* Get the port pins position */
36 currentpin = (GPIO_InitStruct->GPIO_Pin) & pos; 37 if (currentpin == pos) 38 { 39 pos = pinpos << 2; 40 /* Clear the corresponding low control register bits */
41 pinmask = ((uint32_t)0x0F) << pos; 42 tmpreg &= ~pinmask; 43 /* Write the mode configuration in the corresponding bits */
44 tmpreg |= (currentmode << pos); 45 /* Reset the corresponding ODR bit */
46 if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD) 47 { 48 GPIOx->BRR = (((uint32_t)0x01) << pinpos); 49 } 50 else
51 { 52 /* Set the corresponding ODR bit */
53 if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU) 54 { 55 GPIOx->BSRR = (((uint32_t)0x01) << pinpos); 56 } 57 } 58 } 59 } 60 GPIOx->CRL = tmpreg; 61 }
下面我门以初始化
#define LED_G_GPIO_PIN GPIO_Pin_0
#define LED_G_GPIO_PORT GPIOB
#define LED_G_GPIO_CLK RCC_APB2Periph_GPIOB
void LED_GPIO_Config(void) {
/*定义一个 GPIO_InitTypeDef 类型的结构体*/ GPIO_InitTypeDef GPIO_InitStruct;
/*开启 LED 相关的 GPIO 外设时钟*/ RCC_APB2PeriphClockCmd(LED_G_GPIO_CLK, ENABLE);
/*选择要控制的 GPIO 引脚*/
GPIO_InitStruct.GPIO_Pin = LED_G_GPIO_PIN;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
/*设置引脚速率为 50MHz*/ GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; /*调用库函数,初始化 GPIO*/ GPIO_Init(LED_G_GPIO_PORT, &GPIO_InitStruct);
/*设置初始状态为 SetBits 关闭LED灯(低电平点亮)*/
GPIO_SetBits(LED1_GPIO_PORT, LED1_GPIO_PIN);
}
难点就是函数种运用了结构体指针:
下面我们来学习一下C语言中的结构体
1. 什么是结构体?
结构体是一种工具,用这个工具可以定义自己的数据类型
2. 结构体与数组的比较
(1) 都由多个元素组成
(2) 各个元素在内存中的存储空间是连续的
(3) 数组中各个元素的数据类型相同,而结构体中的各个元素的数据类型可以不相同
3. 结构体的定义和使用
1>:一般形式
struct 结构体名 { 类型名1 成员名1; 类型名2 成员名2; 类型名n 成员名n; }; struct student { char name[10]; char sex; int age; float score; };
//student 为结构体类型名
2>:定义结构体类型的变量,指针变量和数组
方法一:定义结构体类型时,同时定义该类型的变量
struct [student] /* [ ]表示结构体名是可选的 */ { char name[10]; char sex; int age; float score; }stu1, *ps, stu[5]; /* 定义结构体类型的普通变量、指针变量和数组 */
方法二:先定义结构体类型,再定义该类型的变量
struct student { char name[10]; char sex; int age; float score; }; struct student stu1, *ps, stu[5]; /* 定义结构体类型的普通变量、指针变量和数组 */
方法三:用类型定义符typedef先给结构体类型命别名,再用别名定义变量
typedef struct [student] { char name[10]; char sex; int age; float score; }STU; STU stu1, *ps, stu[5]; /* 用别名定义结构体类型的普通变量、指针变量和数组 */
//注释:typedef
3:> 给结构体变量赋初值
struct [student] { char name[10]; char sex; int age; float score; }stu[2]={{"Li", 'F', 22, 90.5}, {"Su", 'M', 20, 88.5}};
4:>引用结构体变量中的成员
1) 结构体变量名. 成员名: stu1.name 2) 结构体指针变量->成员名: ps->name 3) (*结构体指针变量). 成员名: (*ps).name 4) 结构体变量数组名. 成员名: stu[0].name
先写到这里 下次再补充