STM32单片机(四)第二节:OLED显示屏

news2024/11/26 12:41:37

❤️ 专栏简介:本专栏记录了从零学习单片机的过程,其中包括51单片机和STM32单片机两部分;建议先学习51单片机,其是STM32等高级单片机的基础;这样再学习STM32时才能融会贯通。
☀️ 专栏适用人群 :适用于想要从零基础开始学习入门单片机,且有一定C语言基础的的童鞋。
🌙专栏目标:实现从零基础入门51单片机和STM32单片机,力求在玩好单片机的同时,能够了解一些计算机的基本概念,了解电路及其元器件的基本理论等。

⭐️ 专栏主要内容: 主要学习STM32单片机的功能、各个模块、单片机的外设、驱动等,最终玩好单片机和单片机的外设,全程手敲代码,实现我们所要实现的功能。
🌴 专栏说明 :如果文章知识点有错误的地方,欢迎大家随时在文章下面评论,我会第一时间改正。让我们一起学习,一起进步。
💑专栏主页:http://t.csdn.cn/HCD8v

本学习过程参考:https://space.bilibili.com/383400717

STM3单片机安装软件、各种资料以及源码的路径:
链接:https://pan.baidu.com/s/1snD0uuTfMhchFqOMWvAiHA?pwd=asdf#list/path=%2F
提取码:asdf

链接里压缩包的解压密码:32

本大节主要学习OLED调试工具,包含两部分,第一小节主要学习OLED的基础知识,第二小节是写一个简单的程序进行练习,即OLED显示屏,最终提供一个OLED显示屏的驱动函数模块,可以在OLED上显示我们需要的调试信息;
本小节主要是学习如何使用驱动函数,使OLED显示屏上显示我们所需要的内容以及调试信息。

文章目录

  • 一、本节目标
  • 二、OLED显示屏
    • 2.1 接线图
    • 2.2 代码实现

一、本节目标

在OLED屏幕上显示一些我们需要输出端的信息,包含字符和数字等:

在这里插入图片描述

二、OLED显示屏

2.1 接线图

在这里插入图片描述
从上图可以看到,把OLED插在了面包板的右下角,以后就一直把这个屏幕插在这里,方便调试;

可以看出我们使用的是4引脚的OLED屏幕,GND和VCC需要接电源的负极和正极;

将OLED插到PB6到PB9这四个口,SCL接到PB8,SDA接到PB9;

硬件电路如下图所示

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2.2 代码实现

准备好的OLED驱动函数模块都放在了STM32入门教程资料\程序源码\STM32Project\1-4 OLED驱动函数模块\4针脚I2C版本这个路径下:

在这里插入图片描述
以上文件可以直接复制的我们对应的工程中直接使用,
例如本节,将以上文件复制到:STM32入门教程资料\程序源码\STM32Project\4-1 OLED显示屏\Hardware

源码路径:
STM32入门教程资料\程序源码\STM32Project\4-1 OLED显示屏\User里存放的是main函数

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"

int main(void)
{
	OLED_Init();
	
	OLED_ShowChar(1, 1, 'A');
	OLED_ShowString(1, 3, "HelloWorld!");
	OLED_ShowNum(2, 1, 12345, 5);
	OLED_ShowSignedNum(2, 7, -66, 2);
	OLED_ShowHexNum(3, 1, 0xAA55, 4);
	OLED_ShowBinNum(4, 1, 0xAA55, 16);
	
	while (1)
	{
		
	}
}

OLED.c://OLED相关驱动函数

#include "stm32f10x.h"
#include "OLED_Font.h"

/*引脚配置*/
#define OLED_W_SCL(x)		GPIO_WriteBit(GPIOB, GPIO_Pin_8, (BitAction)(x))
#define OLED_W_SDA(x)		GPIO_WriteBit(GPIOB, GPIO_Pin_9, (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_8;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
 	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清屏
}

代码解释:

如果你硬件接口的SCL和SDA不是接在PB8和PB9,那么则需要做以下两点修改适配:

1、引脚配置

/*引脚配置*/
#define OLED_W_SCL(x)		GPIO_WriteBit(GPIOB, GPIO_Pin_8, (BitAction)(x))
#define OLED_W_SDA(x)		GPIO_WriteBit(GPIOB, GPIO_Pin_9, (BitAction)(x))

引脚配置,这里选择的是你硬件电路上把SCL和SDA这两个引脚接在了哪两个端口上,如上代码表示SCL接在了PB8上,SDA接在了PB9上;

例如:如果你硬件电路上把SCL接在了PA6上,那么对应的DLED_W_SCL(x)宏就要改为:

#define OLED_W_SCL(x)		GPIO_WriteBit(GPIOA, GPIO_Pin_6, (BitAction)(x))

SDA,OLED_W_SDA(x)宏也是同样的道理;

2、引脚初始化

如果像1中修改了硬件的引脚,那么OLED_I2C_Init函数也要更改;此函数就是把SCL和SDA两个引脚都初始化为开漏输出模式,

在这里插入图片描述
可以看到以上代码里写的是SCL接PB8,SDA接PB9;如果硬件引脚换成了其他的引脚,除了1中宏定义要修改,这里也是要做相应修改的;

其他剩下驱动函数的就不需要更改了,可以直接拿来使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/629651.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java下载sun包下的源码

为什么要重下sun包&#xff1f; sun包下的类&#xff0c;都是.class文件。例如&#xff1a;sun.net.www.protocol.http.HttpURLConnection的源码&#xff0c;竟然是.class。原因是JDK自带的src.zip里面&#xff0c;压根没有放对应的源码文件。 如何下载sun包源码&#xff1f; …

chatgpt赋能python:Python编程与SEO:如何用Python写出最优化自己的姓名?

Python编程与SEO&#xff1a;如何用Python写出最优化自己的姓名&#xff1f; 作为一名有10年Python编程经验的工程师&#xff0c;我深知Python编程在SEO优化方面所起的重要作用。Python语言简洁、灵活以及强大的功能&#xff0c;可以使我们更好地优化自己的网页排名。 在本篇…

Unreal5 实现武器切换功能

首先回忆一下之前在制作武器时&#xff0c;如何实现从后背拿武器的。我们创建了一个切换事件&#xff0c;判断当前是否持有武器&#xff0c;然后根据是否持有武器&#xff0c;去修改动画蓝图的变量&#xff0c;来触发从后面拿枪或者是否把枪放了回去。 然后在播放切枪动画时&am…

【MySql】数据库的增删改查

本篇的主要目的&#xff1a;对于数据库如何去增加删除查询修改 文章目录 创建数据库create查看数据库show删除数据库drop修改数据库alter 创建数据库create 主要细节在于选项问题&#xff0c;编码选项 CREATE DATABASE [IF NOT EXISTS] db_name [create_specification [, cre…

让chatGPT使用Tensor flow Keras组装Bert,GPT,Transformer

让chatGPT使用Tensor flow Keras组装Bert,GPT,Transformer implement Transformer Model by Tensor flow Kerasimplement Bert model by Tensor flow Kerasimplement GPT model by Tensor flow Keras 本文主要展示Transfomer, Bert, GPT的神经网络结构之间的关系和差异。网络上…

空间权重矩阵总结

前言 建立空间计量模型的前提&#xff0c;一般要引入空间权重矩阵 W W W来表达 n n n个位置的空间区域邻近关系。 但空间权重矩阵的构造一直是备受争议的&#xff0c;理论是不存在最优的空间矩阵&#xff0c;那么在实证分析中&#xff0c;通常用一个词总结试一试。下文总结了目…

chatgpt赋能python:Python怎么全加井号

Python怎么全加井号 在SEO优化中&#xff0c;适当的标记和排版对文章排名起到重要作用。在这篇文章中&#xff0c;我们将介绍如何使用井号&#xff08;#&#xff09;在Python中全加井号&#xff0c;以帮助优化文章搜索引擎排名。 什么是井号&#xff1f; 在Python中&#xf…

chatgpt赋能python:Python怎么再添一格的SEO

Python怎么再添一格的SEO Python作为一门高效、多用途、自由、易于学习的编程语言&#xff0c;已经被广泛地应用在各个领域&#xff0c;包括Web开发、数据分析、机器学习、人工智能等。在这篇文章中&#xff0c;我们将探讨如何使用Python来提高网站的SEO排名。 1. 了解SEO 在…

chatgpt赋能python:Python怎么写表格:介绍与结论

Python怎么写表格&#xff1a;介绍与结论 在数据分析或者开发领域&#xff0c;表格是非常常见的数据展示形式。Python作为一门流行的编程语言&#xff0c;在表格的处理上也有很好的支持。今天我们来介绍一下Python怎么写表格。 1. Pandas库的使用 Pandas是Python中非常流行的…

chatgpt赋能python:Python怎么入侵手机

Python怎么入侵手机 现在移动设备已经成为人们生活中必不可少的一部分&#xff0c;因此&#xff0c;攻击者越来越多地将目光转向移动设备。 进入移动设备的主要方式之一是通过应用程序漏洞进行攻击。而Python编程语言的出现可以让攻击者更容易地发掘和利用这些漏洞&#xff0c…

chatgpt赋能python:Python创建SEO文章的指南

#Python创建SEO文章的指南 在当今数字化世界中&#xff0c;SEO&#xff08;搜索引擎优化&#xff09;对于拥有一个成功的在线业务至关重要。SEO文章不仅可以帮助提高网站的排名&#xff0c;还可以吸引更多的访问者并提高转化率。在本文中&#xff0c;我们将介绍如何使用Python…

基于统计检验的空间计量经济模型选择方法

前言 当前空间计量模型的实证研究中&#xff0c;国内的文献均是基于LM检验的空间自相关和空间误差模型进行选择与分析&#xff0c;但是LM检验确实存在局限性。故此&#xff0c;需要对空间计量模型选择进行一个阐述。下列出现在空间计量模型选择方法。 原理方法基于统计检验方…

chatgpt赋能python:Python怎么做选择题?

Python怎么做选择题&#xff1f; 作为一种最广泛使用的编程语言之一&#xff0c;Python被广泛应用于数据科学、机器学习、人工智能、Web开发等领域&#xff0c;而我们今天要聚焦的是Python如何实现选择题的功能。 选择题是什么&#xff1f; 选择题是一种常见的考试题型&…

ICMP协议详解

目录 1.ICMP协议简介 2.ICMP报文格式 2.1 ICMP报文以太网数据帧格式 2.2 ICMP首部格式 2.3 ICMP报文类型列表 3.ICMP故障排查工具 3.1 ping工具 3.2 traceroute工具 4.常见ICMP报文 4.1 ICMP请求和应答 4.2 ICMP差错报告报文 4.3 目标主机不可达 5.ICMP校验和计算 …

ROS学习——通信机制(话题通信④—自定义msg)

052话题通信_自定义msg_实现_Chapter2-ROS通信机制_哔哩哔哩_bilibili 2.1.4 话题通信自定义msg Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 一、自定义msg实现 需求:创建自定义消息&#xff0c;该消息包含人的信息:姓名、身高、年龄等。 1.定义msg文件 &am…

python基础语法学习--字面量

1、字面量的定义 在代码中&#xff0c;被写下来的固定的值。 2、常见值类型 数字&#xff1a;Number&#xff0c;包含整数int、浮点数float、复数complex、布尔bool四类。 整数int&#xff1a;如10、-10等 浮点数float&#xff1a;如13.14、-13.14等 复数complex&#xff1a;如…

Cracking C++(6): 准确打印浮点数

文章目录 1. 目的2. 准确打印浮点数&#xff1a; 使用 fmt 库3. 准确算出被表示的值3.1 直观感受IEEE-754: float-toy3.2 获取浮点数二进制表示3.3 float 类型3.4 double 类型3.5 fp16 类型3.6 验证 4. 结论和讨论5. References 1. 目的 给 float 或 double 类型的变量赋值后&…

chatgpt赋能python:Python教程:如何倒序输出字典?

Python教程&#xff1a;如何倒序输出字典&#xff1f; Python是一种强大的编程语言&#xff0c;广泛用于各种类型的应用程序开发。在开发应用程序时&#xff0c;访问和操作数据是至关重要的一步&#xff0c;而字典是Python中最有用的数据结构之一。字典允许开发人员使用键值对…

Linux安装myql8.0操作步骤

1. 创建software目录&#xff0c;目录可以自定义 mkdir /usr/local/softwar 2. 进入目录software&#xff0c;获取安装包文件 wget https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.32-linux-glibc2.12-x86_64.tar.xz 3. 解压文件 tar -vxf mysql-8.0.32-…

【MySQL数据库 | 第十六篇】存储引擎

目录 前言&#xff1a; MySQL体系结构图&#xff1a; 存储引擎简介&#xff1a; 1. InnoDB存储引擎&#xff1a; 2. MyISAM存储引擎&#xff1a; 3. MEMORY存储引擎&#xff1a; 4. NDB Cluster存储引擎&#xff1a; 5. ARCHIVE存储引擎&#xff1a; 存储引擎语法&#…