STM32 极速入门第一天基础拓展 驱动i2c屏幕 ( 使用PlatformIO开发STM32单片机 )

输入输出模式解析

输出模式

在输出模式下,通常不需要设置上下拉电阻.

输出电平由 LL_GPIO_SetOutputPinLL_GPIO_ResetOutputPin 函数直

接控制。

输入模式

在输入模式下,设置上下拉电阻是非常重要的.

输入引脚悬空时可能会导致不确定的电平,从而引起误触发或噪声。

初始设置相关资料

  • 引脚模式:输入、输出、复用功能等。

LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_13, LL_GPIO_MODE_INPUT); //输入

LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_13, LL_GPIO_MODE_OUTPUT);//输出

LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_13, LL_GPIO_MODE_ALTERNATE);//复用

1. 复用功能(Alternate Function)

复用功能允许GPIO引脚用于外设的功能,例如USART、SPI、I2C等。每个GPIO引脚可以配置为多种复用功能之一。

假设我们要将GPIOA第9引脚配置为USART1的TX引脚:
// 使能GPIOA时钟
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA);

// 配置GPIOA第9引脚为复用功能模式
LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_9, LL_GPIO_MODE_ALTERNATE);

// 设置引脚速度为高速
LL_GPIO_SetPinSpeed(GPIOA, LL_GPIO_PIN_9, LL_GPIO_SPEED_FREQ_HIGH);

// 设置引脚输出类型为推挽输出
LL_GPIO_SetPinOutputType(GPIOA, LL_GPIO_PIN_9, LL_GPIO_OUTPUT_PUSHPULL);

// 设置引脚上拉/下拉电阻为无
LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_9, LL_GPIO_PULL_NO);

  • 输出类型:推挽、开漏等。

LL_GPIO_SetPinOutputType(GPIOC, LL_GPIO_PIN_13, LL_GPIO_OUTPUT_PUSHPULL); //推挽

LL_GPIO_SetPinOutputType(GPIOC, LL_GPIO_PIN_13, LL_GPIO_OUTPUT_OPENDRAIN);//开漏

推挽输出(Push-Pull)
  • 特点:引脚可以输出高电平和低电平。
  • 用途:适用于大多数通用输出场景。
开漏输出(Open-Drain)
  • 特点:引脚只能输出低电平,高电平需要外部上拉电阻。
  • 用途:适用于需要外部上拉电阻的场景,如I2C通信。

  • 速度:低速、中速、高速、非常高速等。

LL_GPIO_SetPinSpeed(GPIOC, LL_GPIO_PIN_13, LL_GPIO_SPEED_FREQ_LOW);//低

LL_GPIO_SetPinSpeed(GPIOC, LL_GPIO_PIN_13, LL_GPIO_SPEED_FREQ_MEDIUM);//中

LL_GPIO_SetPinSpeed(GPIOC, LL_GPIO_PIN_13, LL_GPIO_SPEED_FREQ_HIGH);//高

LL_GPIO_SetPinSpeed(GPIOC, LL_GPIO_PIN_13, LL_GPIO_SPEED_FREQ_VERY_HIGH);//非常高

速度解析

低速(Low Speed)
  • 特点:最低的输出速度,适用于低频信号。
  • 用途:适用于对速度要求不高的场景。
中速(Medium Speed)
  • 特点:中等的输出速度。
  • 用途:适用于一般的输出场景。
高速(High Speed)
  • 特点:较高的输出速度。
  • 用途:适用于对速度有一定要求的场景。
非常高速(Very High Speed)
  • 特点:最高的输出速度。
  • 用途:适用于对速度要求很高的场景。

  • 上下拉电阻:上拉、下拉、无等。

LL_GPIO_SetPinPull(GPIOC, LL_GPIO_PIN_13, LL_GPIO_PULL_UP);//上拉

LL_GPIO_SetPinPull(GPIOC, LL_GPIO_PIN_13, LL_GPIO_PULL_DOWN);//下拉

LL_GPIO_SetPinPull(GPIOC, LL_GPIO_PIN_13, LL_GPIO_PULL_NO);//无上下拉 可忽略


  • 中断和事件:配置中断和事件触发条件

    // 使能GPIOC时钟
    LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOC);

    // 配置GPIOC第13引脚为输入模式
    LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_13, LL_GPIO_MODE_INPUT);

    // 设置上拉电阻
    LL_GPIO_SetPinPull(GPIOC, LL_GPIO_PIN_13, LL_GPIO_PULL_UP);

    // 使能外部中断线
    LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_13);

    // 选择GPIOC第13引脚作为外部中断源
    LL_SYSCFG_SetEXTISource(LL_SYSCFG_EXTI_PORTC, LL_SYSCFG_EXTI_LINE13);

    // 使能NVIC中断
    NVIC_EnableIRQ(EXTI15_10_IRQn);

    // 设置中断优先级
    NVIC_SetPriority(EXTI15_10_IRQn, 1);

    // 中断服务例程
    void EXTI15_10_IRQHandler(void) {
    if (LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_13) != RESET) {
    // 清除中断标志
    LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_13);

          // 处理中断
          // ...
      }
    

    }


驱动i2c屏幕

可能是有什么问题没有调试通代码放在这里坐等有人解答!

#include <stm32f1xx_hal.h>
#include <stm32f1xx_hal_gpio.h>
#include <stm32f1xx_hal_spi.h>
#include <stm32f1xx_hal_rcc.h>

SPI_HandleTypeDef hspi1; // SPI句柄
const char *s;

// 初始化序列
// 初始化序列
uint8_t init_sequence[] = {
    0xAE,             // 关闭 OLED 显示面板
    0x15, 0x00, 0x7F, // 设置列地址范围,起始值为 0,结束值为 127
    0x75, 0x00, 0x7F, // 设置行地址范围,起始值为 0,结束值为 127
    0x81, 0x80,       // 设置对比度控制,对比度值为 128
    0xA0, 0x51,       // 段重映射,设置段重映射方式
    0xA1, 0x00,       // 设置显示起始行,起始行地址为 0
    0xA2, 0x00,       // 设置显示偏移,偏移值为 0
    0xA4,             // 设置正常显示模式
    0xA8, 0x7F,       // 设置多路复用比率,多路复用比率为 127
    0xB1, 0xF1,       // 设置相位长度
    0xB3, 0x00,       // 设置 DCLK,设置 DCLK 为 100 Hz
    0xAB, 0x01,       // 启动内部振荡器
    0xB6, 0x0F,       // 设置相位长度
    0xBE, 0x0F,       // 设置 VCOMH 电压
    0xBC, 0x08,       // 设置预充电周期
    0xD5, 0x62,       // 设置显示时钟分频
    0xFD, 0x12,       // 设置命令锁存
    0xA0, 0x51,       // 再次设置扫描方式,设置扫描方式从左往右,从上到下
    0xAF,             // 打开 OLED 显示面板
};

void spiinit()
{
    // 第一步开启时钟
    __HAL_RCC_SPI1_CLK_ENABLE();  // SPI1
    __HAL_RCC_GPIOA_CLK_ENABLE(); // PA

    // 第二步设置引脚
    GPIO_InitTypeDef GPIO_InitStructure; // GPIO初始化结构体

    // MOSI
    GPIO_InitStructure.Pin = GPIO_PIN_5;
    GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStructure.Pull = GPIO_NOPULL;
    GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);

    // MISO
    GPIO_InitStructure.Pin = GPIO_PIN_6;
    GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
    GPIO_InitStructure.Pull = GPIO_NOPULL;
    GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);

    // NSS
    GPIO_InitStructure.Pin = GPIO_PIN_4;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.Pull = GPIO_PULLDOWN;
    GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 第三步设置SPI
    hspi1.Instance = SPI1;                                  // SPI1
    hspi1.Init.Direction = SPI_DIRECTION_2LINES;            // 双线模式
    hspi1.Init.Mode = SPI_MODE_MASTER;                      // 主机模式
    hspi1.Init.DataSize = SPI_DATASIZE_8BIT;                // 8位
    hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;              // 低电平
    hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;                  // 上升沿
    hspi1.Init.NSS = SPI_NSS_SOFT;                          // 软件片选
    hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; // 100MHz
    hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;                 // 高位在前
    hspi1.Init.TIMode = SPI_TIMODE_DISABLE;                 // 硬件模式
    hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; // CRC校验
    hspi1.Init.CRCPolynomial = 7;                           // CRC校验
    if (HAL_SPI_Init(&hspi1) != HAL_OK)
    {
        // 初始化失败处理
        while (1)
            ;
    }
    __HAL_SPI_ENABLE(&hspi1); // 使能SPI
}

void spi_select()
{
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // 选择从设备
}

void spi_deselect()
{
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // 取消选择从设备
}

uint8_t spi_write(uint8_t data)
{
    uint8_t rdata;
    HAL_SPI_Transmit(&hspi1, &data, 1, 1000);
    return rdata;
}

int main()
{
    spiinit(); // 初始化
    s = "hello world";

    // 发送初始化序列

    for (int i = 0; i < sizeof(init_sequence) / sizeof(init_sequence[0]); i++)
    {
        spi_select();
        spi_write(init_sequence[i]);
       HAL_Delay(10);
        spi_deselect();
       HAL_Delay(10);
    }

    while (*s)
    {
        spi_deselect();
       HAL_Delay(10);
        spi_write(*s);
        s++;
        spi_select();
       HAL_Delay(10);
    }

    while (1)
        ;
}
相关推荐
嵌入式科普7 分钟前
十一、从0开始卷出一个新项目之瑞萨RA6M5串口DTC接收不定长
c语言·stm32·cubeide·e2studio·ra6m5·dma接收不定长
嵌入式大圣9 分钟前
单片机UDP数据透传
单片机·嵌入式硬件·udp
云山工作室37 分钟前
基于单片机的视力保护及身姿矫正器设计(论文+源码)
stm32·单片机·嵌入式硬件·毕业设计·毕设
嵌入式-老费40 分钟前
基于海思soc的智能产品开发(mcu读保护的设置)
单片机·嵌入式硬件
qq_397562312 小时前
MPU6050 , 设置内部低通滤波器,对于输出数据的影响。(简单实验)
单片机
liyinuo20173 小时前
嵌入式(单片机方向)面试题总结
嵌入式硬件·设计模式·面试·设计规范
艺术家天选3 小时前
STM32点亮LED灯
stm32·单片机·嵌入式硬件
向阳逐梦3 小时前
基于STM32F4单片机实现ROS机器人主板
stm32·单片机·机器人
委员4 小时前
基于NodeMCU的物联网空调控制系统设计
单片机·mcu·物联网·智能家居
小猪写代码4 小时前
STM32 水质水位检测项目 (调试模块)和(延时模块)
stm32·单片机·嵌入式硬件