carry
发布于 2024-05-06 / 18 阅读
0
0

使用stm32f103c8t6完成《嵌入式技术与基础 第六版》相关内容博客作业4 GPIO

使用stm32f103c8t6完成《嵌入式技术与基础 第六版》相关内容博客作业4 GPIO

零、 创新点

《嵌入式技术与基础 第六版》原书教材随书附赠了一块stm32L431的开发板,配套内容都是以此为基础打造的,甚至作者还专门为此开发了一套ide,但是:

  • 现在stm32主流的教程生态用的都是stm32f103c8t6这款芯片,原书的教程虽然能很好的为你解释嵌入式开发的原理,但是要进一步学习,你还是不得不寻找其他教程,购买主流的开发板
  • 作者的ide完全是出于本书学习设计的,对于实际开发毫无意义,若将来想做点嵌入式,还需要重新学习一套开发栈
  • 全新套书卖100。作为抠门带血生,肯定要考虑二手的,但是二手书通常不会带有原书的附件。单买开发板,某宝60,某鱼甚至没有。起码截至我使用该书学习的时间(2024年3月)是这样的,后期使用此书的前辈多了,估计二手市场会变好。
  • 最重要的是,我已经有一个stm32f103c8t6的开发板了

综上,无论是从学习角度还是省钱角度,使用stm32f103c8t6完成《嵌入式技术与基础 第六版》相关内容都是非常合适的

这套博客是广州大学计算机学院嵌入式系统课程的作业,我用stm32f103c8t6开荒,也是为了后来的同学做贡献

一、 底层原理

在程序上来说,arm内核通过对寄存器个别位的读写实现GPIO,每一位都有特殊的定义

GPIOx->CRL

image

示例

GPIOA->CRL&=0XFFFFFFF0;//其他位置为11,不启用其他引脚
GPIOA->CRL|=0X00000003;//0-3位为0011,意为启用输出且最大速度为50Mhz,且为推挽输出模式

GPIOx->CRH

这个寄存器和GPIOx->CRL大同小异,不同的是这个寄存器是设置高8位(8~15)端口的配置,不再赘述

GPIOx->IDR

image

示例

unsigned char a;
a=GPIOA->IDR&1<<0;//读取PA0的数值

GPIOx->ODR

image

示例

GPIOA->ODR|=1<<0;//设置PA0为1
GPIOA->ODR|=0<<0;//设置PA0为0

GPIOx_BSRR

image

示例

GPIOA->BSRR|=1<<0;//设置PA0为1
GPIOA->BSRR|=1<<16;//设置PA0为0

二、 寄存器编程初体验

写一个跑马灯的程序

/* USER CODE BEGIN WHILE */
RCC->APB2ENR |= (1 << 2); // 使能GPIOA端口的时钟
GPIOB->CRL &= 0X000FFFFF; // 清除GPIOB端口配置低寄存器(CRL)的高5位,为配置这些引脚做准备
GPIOB->CRL |= 0X33300000; // 配置为通用推挽输出模式

while (1)
{
    // 绿灯
    GPIOA->BSRR = 5;
    HAL_Delay(500);
    GPIOA->BRR = 5;
    HAL_Delay(500);
    // 黄灯
    GPIOA->BSRR = 6;
    HAL_Delay(500);
    GPIOA->BRR = 6;
    HAL_Delay(500);
    // 红灯
    GPIOA->BSRR = 7;
    HAL_Delay(500);
    GPIOA->BRR = 7;
    HAL_Delay(500);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */

三、 层层封装后的GPIO

通过读写寄存器进行操作的方式,不仅反人类,还缺乏可移植性,所以主流的stm32开发都是用标准库或hal库完成

标准库

GPIO_InitTypeDef GPIO_InitStructure;                  //定义一个GPIO_InitTypeDef类型的结构体变量
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);  //开启GPIOB的时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;             //选择要使用的I/O引脚,此处选择PB5引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //设置引脚输出模式为推挽输出模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //设置引脚的输出速度为50MHz
GPIO_Init(GPIOB,&GPIO_InitStructure);                 //调用初始化库函数初始化GPIOB端口

GPIO_WriteBit(GPIOB, GPIO_Pin_6, Bit_SET);
GPIO_WriteBit(GPIOB, GPIO_Pin_6, Bit_RESET);

HAL库

通过ide配置引脚初始化

image

HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET); // 设置引脚为高电平
HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET); // 设置引脚为低电平

关于作者:

欢迎联系!


评论