输入输出模式解析
输出模式
在输出模式下,通常不需要设置上下拉电阻.
输出电平由
LL_GPIO_SetOutputPin
和LL_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,结束值为 1270x75, 0x00, 0x7F, // 设置行地址范围,起始值为 0,结束值为 1270x81, 0x80, // 设置对比度控制,对比度值为 1280xA0, 0x51, // 段重映射,设置段重映射方式0xA1, 0x00, // 设置显示起始行,起始行地址为 00xA2, 0x00, // 设置显示偏移,偏移值为 00xA4, // 设置正常显示模式0xA8, 0x7F, // 设置多路复用比率,多路复用比率为 1270xB1, 0xF1, // 设置相位长度0xB3, 0x00, // 设置 DCLK,设置 DCLK 为 100 Hz0xAB, 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初始化结构体// MOSIGPIO_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);// MISOGPIO_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);// NSSGPIO_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);// 第三步设置SPIhspi1.Instance = SPI1; // SPI1hspi1.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; // 100MHzhspi1.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);
}