🎉欢迎来到stm32专栏~stm32+oled最小系统板
- ☆* o(≧▽≦)o *☆嗨~我是小夏与酒🍹
- ✨博客主页:小夏与酒的博客
- 🎈该系列文章专栏:stm32专栏
- 文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏
- 📜 欢迎大家关注! ❤️
一、效果演示
🥝示例代码演示
特写:
🥝外观展示
正面:
背面:
加上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] != '\0'; i++)
{
OLED_ShowChar(Line, Column + i, String[i]);
}
}
/**
* @brief OLED次方函数
* @retval 返回值等于X的Y次方
*/
uint32_t OLED_Pow(uint32_t X, uint32_t Y)
{
uint32_t Result = 1;
while (Y--)
{
Result *= X;
}
return Result;
}
/**
* @brief OLED显示数字(十进制,正数)
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~4294967295
* @param Length 要显示数字的长度,范围:1~10
* @retval 无
*/
void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i++)
{
OLED_ShowChar(Line, Column + i, Number / OLED_Pow(10, Length - i - 1) % 10 + '0');
}
}
/**
* @brief OLED显示数字(十进制,带符号数)
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:-2147483648~2147483647
* @param Length 要显示数字的长度,范围:1~10
* @retval 无
*/
void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length)
{
uint8_t i;
uint32_t Number1;
if (Number >= 0)
{
OLED_ShowChar(Line, Column, '+');
Number1 = Number;
}
else
{
OLED_ShowChar(Line, Column, '-');
Number1 = -Number;
}
for (i = 0; i < Length; i++)
{
OLED_ShowChar(Line, Column + i + 1, Number1 / OLED_Pow(10, Length - i - 1) % 10 + '0');
}
}
/**
* @brief OLED显示数字(十六进制,正数)
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~0xFFFFFFFF
* @param Length 要显示数字的长度,范围:1~8
* @retval 无
*/
void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
uint8_t i, SingleNumber;
for (i = 0; i < Length; i++)
{
SingleNumber = Number / OLED_Pow(16, Length - i - 1) % 16;
if (SingleNumber < 10)
{
OLED_ShowChar(Line, Column + i, SingleNumber + '0');
}
else
{
OLED_ShowChar(Line, Column + i, SingleNumber - 10 + 'A');
}
}
}
/**
* @brief OLED显示数字(二进制,正数)
* @param Line 起始行位置,范围:1~4
* @param Column 起始列位置,范围:1~16
* @param Number 要显示的数字,范围:0~1111 1111 1111 1111
* @param Length 要显示数字的长度,范围:1~16
* @retval 无
*/
void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i++)
{
OLED_ShowChar(Line, Column + i, Number / OLED_Pow(2, Length - i - 1) % 2 + '0');
}
}
/**
* @brief OLED初始化
* @param 无
* @retval 无
*/
void OLED_Init(void)
{
uint32_t i, j;
for (i = 0; i < 1000; i++) //上电延时
{
for (j = 0; j < 1000; j++);
}
OLED_I2C_Init(); //端口初始化
OLED_WriteCommand(0xAE); //关闭显示
OLED_WriteCommand(0xD5); //设置显示时钟分频比/振荡器频率
OLED_WriteCommand(0x80);
OLED_WriteCommand(0xA8); //设置多路复用率
OLED_WriteCommand(0x3F);
OLED_WriteCommand(0xD3); //设置显示偏移
OLED_WriteCommand(0x00);
OLED_WriteCommand(0x40); //设置显示开始行
OLED_WriteCommand(0xA1); //设置左右方向,0xA1正常 0xA0左右反置
OLED_WriteCommand(0xC8); //设置上下方向,0xC8正常 0xC0上下反置
OLED_WriteCommand(0xDA); //设置COM引脚硬件配置
OLED_WriteCommand(0x12);
OLED_WriteCommand(0x81); //设置对比度控制
OLED_WriteCommand(0xCF);
OLED_WriteCommand(0xD9); //设置预充电周期
OLED_WriteCommand(0xF1);
OLED_WriteCommand(0xDB); //设置VCOMH取消选择级别
OLED_WriteCommand(0x30);
OLED_WriteCommand(0xA4); //设置整个显示打开/关闭
OLED_WriteCommand(0xA6); //设置正常/倒转显示
OLED_WriteCommand(0x8D); //设置充电泵
OLED_WriteCommand(0x14);
OLED_WriteCommand(0xAF); //开启显示
OLED_Clear(); //OLED清屏
}
void OLED_Init_Display(void)
{
OLED_ShowChar(1, 1, 'A');
OLED_ShowString(1, 3, "Hello World!");
OLED_ShowNum(2, 1, 12345, 5);
OLED_ShowSignedNum(2, 7, -66, 2);
OLED_ShowHexNum(3, 1, 0xAA55, 4);
OLED_ShowBinNum(4, 1, 0xAA55, 16);
}
OLED.h:
#ifndef __OLED_H
#define __OLED_H
void OLED_Init_Display(void);
void OLED_Init(void);
void OLED_Clear(void);
void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char);
void OLED_ShowString(uint8_t Line, uint8_t Column, char *String);
void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length);
void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length);
#endif
🔸按键控制: 用于实现按键控制和人机交互。
Key.c:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "LED.h"
void Key1_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void Key2_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void Key3_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void Key_Ctrl_OLED(void)
{
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_12) == 0)
{
LED_ON();
OLED_Init();
OLED_ShowString(1, 1, "Hello World!");
}
else
{
LED_OFF();
}
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13) == 0)
{
LED_ON();
OLED_Init();
OLED_ShowString(2, 1, "Stm32 + OLED!");
}
else
{
LED_OFF();
}
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0)
{
LED_ON();
OLED_Init();
OLED_ShowString(3, 1, "XiaoXia!");
}
else
{
LED_OFF();
}
}
Key.h:
#ifndef __KEY_H
#define __KEY_H
void Key1_Init(void);
void Key2_Init(void);
void Key3_Init(void);
void Key_Ctrl_OLED(void);
#endif
文章来源:https://www.toymoban.com/news/detail-484971.html
🧸结尾文章来源地址https://www.toymoban.com/news/detail-484971.html
- ❤️ 感谢您的支持和鼓励! 😊🙏
- 📜您可能感兴趣的内容:
- 【FPGA-Spirit_V2】基于FPGA的循迹小车-小精灵V2开发板
- 【Go黑帽子】使用Golang编写一个TCP扫描器(高级篇)
- 【Arduino TinyGo】【最新】使用Go语言编写Arduino-环境搭建和点亮LED灯
- 【全网首发开源教程】【Labview机器人仿真与控制】Labview与Solidworks多路支配关系-四足爬行机器人仿真与控制
到了这里,关于【stm32开发】stm32+oled最小系统板资料(原理图、PCB、示例代码)【六一】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!