您现在的位置是:首页 >技术教程 >【stm32开发】stm32+oled最小系统板资料(原理图、PCB、示例代码)【六一】网站首页技术教程
【stm32开发】stm32+oled最小系统板资料(原理图、PCB、示例代码)【六一】
?欢迎来到stm32专栏~stm32+oled最小系统板
一、效果演示
?示例代码演示
特写:
?外观展示
正面:
背面:
加上oled屏:
如果需要板子的原理图、PCB和示例代码工程文件,请从我上传的资源中下载:stm32+oled最小系统板资料(原理图、PCB、示例代码)。或者三连本文章后联系我免费获取!
二、原理图与PCB
我使用了最最最可爱的嘉立创EDA完成了stm32+oled最小系统板的绘制。
2.1 原理图
先介绍原理图部分:
?整体原理图:
?电源接口部分:最简单的,通过排针接入5V
电源。
?电源降压部分:使用AMS1117
完成5V转3.3V
的任务。
?滤波电路部分:该部分也可以称为电源滤波退耦电路。
?按键部分:加入该部分是为了便于实现控制操作和交互操作,设计三个用户按键,满足多数设计开发需求。
?MCU部分:在此我只使用了8M
的晶振,如果需要使用32.768KHz
的晶振,加入即可。
?复位电路部分:就是正常的复位电路。
?程序下载部分:SWD程序下载接口。
?oled接口部分:为了方便直接使用oled显示屏,在画板子的时候直接引出对应的接口。
?电源指示部分:用于显示电压是否正常。
?板载led部分:板载led接了PC13
,使用时注意配置引脚。
?其余引脚部分:将剩余的引脚引出。
2.2 PCB
顶层:
底层:
3D:
2.3 PCB布局
对于PCB的布局,我从一些参考资料中进行了整理。
STM32F103C8T6相关布线知识点:
1、布局中应参考原理图,根据电路的主信号流向规律安排主要元器件。
2、Boot0和Boot1都接到地,就是正常工作模式:Boot0和Boot1都加一个10K的电阻,然后接到地。
3、晶振电路:
晶振与两个电容并联使用,电容的大小由晶振决定,一般使用22pF。
- 画板时晶振尽量离芯片近一点;
- 晶振底部尽量不要穿过其他支路,防止信号串扰;
- 晶振、芯片、电容(与晶振相连的电容要紧邻晶振)之间的走线要尽量直且短;
- 不同型号的晶振可能需要不同的电路设计,根据自己使用的晶振型号设计。
4、AMS1117降压电路,5V转3.3V:
- 输入滤波电容的作用:
输入电压,当接入电源,其幅值是从零起始的,波动非常大,加入足够容量的电容进行滤波后,因电容的充放电效应,该脉动直流变成纹波不大的直流电,这是输入滤波的作用。 - 输出滤波电容的作用:
稳压电路的工作过程需要从输出采样,然后根据其反馈值调节输出以达稳压的目的。如果此时没有输出滤波电容,只要因负载变化带来的电压波动频率恰好与稳压电路的调节速率差不多就会产生振荡效应,导致输出失控,所以稳压输出也必须加滤波电容,而且增加滤波电容也可以进一步增加稳压输出的稳定性。 - 大电容和小电容并联的作用:
至于与大容量电解电容并联的小电容,其作用在于旁路频率较高的波动电压,因为铝电解电容的制造工艺导致其具有较大的ESL(等效电感),无法滤除高频成份,故需加个小电容。
5、去耦电容:
- 主要用来滤除杂波,保持引脚电压的稳定。
- 这些电容也尽量离芯片相关引脚近一点。
- 分布在芯片四周即可。
- 去耦电容应尽量放置在相应的VCC和GND引脚之间,且距离IC尽可能近,使之与VCC和GND之间形成的回路最短。
6、导线线宽最小为10mil。
7、同一功能模块集中原则。即实现同一功能的相关电路模块中的元器件就近集中布局。
8、遵守“先大后小,先难后易”的原则,即重要的单元电路、核心元器件应优先布局。
9、元器件的排列要便于调试和维修,即小元器件周围不能放置大元器件,需调试的元器件周围要有足够的空间。
10、布局时,位于电路板边缘的元器件离电路板边缘一般不小于2mm,如果空间允许,建议距离保持在5mm。
11、电源主干线原则上要加粗(尤其是电路板的电源输入/输出线)。
12、高频信号线,如STM32核心板上的晶振电路的布线,不要加粗,建议也按照线宽为10mil进行设计,而且尽可能布线在同一层。
13、100mil = 2.54mm(39.37mil = 1mm)。
14、过孔的放置:
- 普通的电阻、电容、电感、磁珠焊盘周围的过孔边缘与焊盘边缘至少保持在0.15mm(5.91mil)以上。
- IC、SOT、大型电感、电解电容、二极管、连接器等焊盘周围的过孔与焊盘边缘至少保持在0.5mm(19.69mil)以上。
- 防止元件回流时,锡膏从过孔流失。
15、添加泪滴:使信号传输时平滑阻抗,减少阻抗的急剧跳变。
大家在画PCB时,可以参考上述布线规则,如果有误或者更好的建议,希望能在评论区中指出。
三、示例代码
示例代码使用江协科技的教学代码:STM32入门教程-2023持续更新中。
?项目一览:
?main.c:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Key.h"
#include "LED.h"
#include "GPIOPC13.h"
int main(void)
{
OLED_Init();
OLED_Init_Display();
Key1_Init();
Key2_Init();
Key3_Init();
DIO_GPIO_OUT_Init();//PC13
while (1)
{
Key_Ctrl_OLED();
}
}
?PC13: 由于板载led接了PC13,所以需要对PC13进行相应的配置。
GPIOPC13.c:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#define TM1668_APBxClock_FUN RCC_APB2PeriphClockCmd
#define TM1668_RCC_DIO RCC_APB2Periph_GPIOC
#define TM1668_DIO_PORT GPIOC
#define TM1668_DIO_PIN GPIO_Pin_13
void DIO_GPIO_OUT_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TM1668_APBxClock_FUN(TM1668_RCC_DIO|RCC_APB2Periph_AFIO,ENABLE);
BKP_TamperPinCmd(DISABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin =TM1668_DIO_PIN;
GPIO_Init(TM1668_DIO_PORT, &GPIO_InitStructure);
}
void DIO_GPIO_IN_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
TM1668_APBxClock_FUN(TM1668_RCC_DIO|RCC_APB2Periph_AFIO,ENABLE);
BKP_TamperPinCmd(DISABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = TM1668_DIO_PIN;
GPIO_Init(TM1668_DIO_PORT, &GPIO_InitStructure);
}
GPIOPC13.h:
#ifndef __GPIO_PC13
#define __GPIO_PC13
void DIO_GPIO_OUT_Init(void);
void DIO_GPIO_IN_Init(void);
#endif
?OLED: 用于显示屏输出。
OLED.c:
#include "stm32f10x.h"
#include "OLED_Font.h"
/*引脚配置*/
#define OLED_W_SCL(x) GPIO_WriteBit(GPIOB, GPIO_Pin_6, (BitAction)(x))
#define OLED_W_SDA(x) GPIO_WriteBit(GPIOB, GPIO_Pin_7, (BitAction)(x))
/*引脚初始化*/
void OLED_I2C_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOB, &GPIO_InitStructure);
OLED_W_SCL(1);
OLED_W_SDA(1);
}
/**
* @brief I2C开始
* @param 无
* @retval 无
*/
void OLED_I2C_Start(void)
{
OLED_W_SDA(1);
OLED_W_SCL(1);
OLED_W_SDA(0);
OLED_W_SCL(0);
}
/**
* @brief I2C停止
* @param 无
* @retval 无
*/
void OLED_I2C_Stop(void)
{
OLED_W_SDA(0);
OLED_W_SCL(1);
OLED_W_SDA(1);
}
/**
* @brief I2C发送一个字节
* @param Byte 要发送的一个字节
* @retval 无
*/
void OLED_I2C_SendByte(uint8_t Byte)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
OLED_W_SDA(Byte & (0x80 >> i));
OLED_W_SCL(1);
OLED_W_SCL(0);
}
OLED_W_SCL(1); //额外的一个时钟,不处理应答信号
OLED_W_SCL(0);
}
/**
* @brief OLED写命令
* @param Command 要写入的命令
* @retval 无
*/
void OLED_WriteCommand(uint8_t Command)
{
OLED_I2C_Start();
OLED_I2C_SendByte(0x78); //从机地址
OLED_I2C_SendByte(0x00); //写命令
OLED_I2C_SendByte(Command);
OLED_I2C_Stop();
}
/**
* @brief OLED写数据
* @param Data 要写入的数据
* @retval 无
*/
void OLED_WriteData(uint8_t Data)
{
OLED_I2C_Start();
OLED_I2C_SendByte(0x78); //从机地址
OLED_I2C_SendByte(0x40); //写数据
OLED_I2C_SendByte(Data);
OLED_I2C_Stop();
}
/**
* @brief OLED设置光标位置
* @param Y 以左上角为原点,向下方向的坐标,范围:0~7
* @param X 以左上角为原点,向右方向的坐标,范围:0~127
* @retval 无
*/
void OLED_SetCursor(uint8_t Y, uint8_t X)
{
OLED_WriteCommand(0xB0 | Y); //设置Y位置
OLED_WriteCommand(0x10 | ((X & 0xF0) >> 4)); //设置X位置高4位
OLED_WriteCommand(0x00 | (X & 0x0F)); //设置X位置低4位
}
/**
* @brief OLED清屏
* @param 无
* @retval 无
*/
void OLED_Clear(void)
{
uint8_t i, j;
for (j = 0; j < 8; j++)
{
OLED_SetCursor(j, 0);
for(i = 0; i < 128; i++)
{
OLED_WriteData(0x00);
}
}
}
/**
* @brief OLED显示一个字符
* @param Line 行位置,范围:1~4
* @param Column 列位置,范围:1~16
* @param Char 要显示的一个字符,范围:ASCII可见字符
* @retval 无
*/
void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char)
{
uint8_t i;
OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8); //设置光标位置在上半部分
for (i = 0; i < 8; i++)
{
OLED_WriteData(OLED_F8x16[Char - ' '][i]); //显示上半部分内容
}
OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8); //设置光标位置在下半部分
for (i = 0; i < 8; i++)
{
OLED_WriteData(OLED_F8x16[Char - ' '][i + 8]); //显示下半部分内容
}
}
/**
* @brief OLED显示字符串
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param String 要显示的字符串,范围:ASCII可见字符
* @retval 无
*/
void OLED_ShowString(uint8_t Line, uint8_t Column, char *String)
{
uint8_t i;
for (i = 0; String[i] != '