stm32TestTempl/Src/ztOLED.hpp
2025-04-12 11:16:45 +08:00

366 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "OLED_Font.h"
#include <cstdint>
#include <list>
#include <vector>
namespace zt{
class Oled{
private:
const u32 _RCC_APB2Periph;
GPIO_TypeDef *const _GPIOx;
const u16 _GPIO_PIN_SCL;
const u16 _GPIO_PIN_SDA;
Oled&W_SCL(const u8 &bit){
GPIO_WriteBit(_GPIOx, _GPIO_PIN_SCL, (BitAction)(bit));
return *this;
}
Oled&W_SDA(const u8 &bit){
GPIO_WriteBit(_GPIOx, _GPIO_PIN_SDA, (BitAction)(bit));
return *this;
}
/**
* @brief I2C开始
* @param 无
* @retval 无
*/
void I2C_Start()
{
W_SDA(1);
W_SCL(1);
W_SDA(0);
W_SCL(0);
}
/**
* @brief I2C停止
* @param 无
* @retval 无
*/
void I2C_Stop()
{
W_SDA(0);
W_SCL(1);
W_SDA(1);
}
/**
* @brief I2C发送一个字节
* @param Byte 要发送的一个字节
* @retval 无
*/
void I2C_SendByte(const uint8_t &Byte)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
W_SDA(!!(Byte & (0x80 >> i)));
W_SCL(1);
W_SCL(0);
}
W_SCL(1); //额外的一个时钟,不处理应答信号
W_SCL(0);
}
/**
* @brief OLED写命令
* @param Command 要写入的命令
* @retval 无
*/
void WriteCommand(uint8_t Command)
{
I2C_Start();
I2C_SendByte(0x78); //从机地址
I2C_SendByte(0x00); //写命令
I2C_SendByte(Command);
I2C_Stop();
}
/**
* @brief OLED写数据
* @param Data 要写入的数据
* @retval 无
*/
void WriteData(uint8_t Data)
{
I2C_Start();
I2C_SendByte(0x78); //从机地址
I2C_SendByte(0x40); //写数据
I2C_SendByte(Data);
I2C_Stop();
}
/**
* @brief OLED设置光标位置
* @param Y 以左上角为原点向下方向的坐标范围0~7
* @param X 以左上角为原点向右方向的坐标范围0~127
* @retval 无
*/
void SetCursor(uint8_t Y, uint8_t X)
{
WriteCommand(0xB0 | Y); //设置Y位置
WriteCommand(0x10 | ((X & 0xF0) >> 4)); //设置X位置高4位
WriteCommand(0x00 | (X & 0x0F)); //设置X位置低4位
}
/**
* @brief OLED次方函数
* @retval 返回值等于X的Y次方
*/
uint32_t Pow(uint32_t X, uint32_t Y)
{
uint32_t Result = 1;
while (Y--)
{
Result *= X;
}
return Result;
}
/**
* @brief OLED初始化
* @param 无
* @retval 无
*/
void Init()
{
uint32_t i, j;
for (i = 0; i < 1000; i++) //上电延时
{
for (j = 0; j < 1000; j++);
}
// I2C_Init(); //端口初始化
WriteCommand(0xAE); //关闭显示
WriteCommand(0xD5); //设置显示时钟分频比/振荡器频率
WriteCommand(0x80);
WriteCommand(0xA8); //设置多路复用率
WriteCommand(0x3F);
WriteCommand(0xD3); //设置显示偏移
WriteCommand(0x00);
WriteCommand(0x40); //设置显示开始行
WriteCommand(0xA1); //设置左右方向0xA1正常 0xA0左右反置
WriteCommand(0xC8); //设置上下方向0xC8正常 0xC0上下反置
WriteCommand(0xDA); //设置COM引脚硬件配置
WriteCommand(0x12);
WriteCommand(0x81); //设置对比度控制
WriteCommand(0xCF);
WriteCommand(0xD9); //设置预充电周期
WriteCommand(0xF1);
WriteCommand(0xDB); //设置VCOMH取消选择级别
WriteCommand(0x30);
WriteCommand(0xA4); //设置整个显示打开/关闭
WriteCommand(0xA6); //设置正常/倒转显示
WriteCommand(0x8D); //设置充电泵
WriteCommand(0x14);
WriteCommand(0xAF); //开启显示
Clear(); //OLED清屏
}
public:
/**
* @brief OLED清屏
* @param 无
* @retval 无
*/
Oled& Clear(void)
{
uint8_t i, j;
for (j = 0; j < 8; j++)
{
SetCursor(j, 0);
for(i = 0; i < 128; i++)
{
WriteData(0x00);
}
}
return *this;
}
/**
* @brief OLED显示一个字符
* @param Line 行位置范围1~4
* @param Column 列位置范围1~16
* @param Char 要显示的一个字符范围ASCII可见字符
* @retval 无
*/
Oled& ShowChar(uint8_t Line, uint8_t Column, char Char)
{
uint8_t i;
SetCursor((Line - 1) * 2, (Column - 1) * 8); //设置光标位置在上半部分
for (i = 0; i < 8; i++)
{
WriteData(OLED_F8x16[Char - ' '][i]); //显示上半部分内容
}
SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8); //设置光标位置在下半部分
for (i = 0; i < 8; i++)
{
WriteData(OLED_F8x16[Char - ' '][i + 8]); //显示下半部分内容
}
return *this;
}
/**
* @brief OLED显示字符串
* @param Line 起始行位置范围1~4
* @param Column 起始列位置范围1~16
* @param String 要显示的字符串范围ASCII可见字符
* @retval 无
*/
Oled& ShowString(uint8_t Line, uint8_t Column, const char *const String)
{
uint8_t i;
for (i = 0; String[i] != '\0'; i++)
{
ShowChar(Line, Column + i, String[i]);
}
return *this;
}
/**
* @brief OLED显示数字十进制正数
* @param Line 起始行位置范围1~4
* @param Column 起始列位置范围1~16
* @param Number 要显示的数字范围0~4294967295
* @param Length 要显示数字的长度范围1~10
* @retval 无
*/
Oled& ShowUNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i++)
{
ShowChar(Line, Column + i, Number / Pow(10, Length - i - 1) % 10 + '0');
}
return *this;
}
Oled&ShowUNum(const uint8_t line, const uint8_t column, uint8_t number){
std::list<char> chars;
while(number>0){
chars.push_front(number%10);
number/=10;
}
std::list<char>::iterator it = chars.begin();
for(uint8_t i=0;i<chars.size();i++){
ShowChar(line, column+i, *(it++));
}
return *this;
}
/**
* @brief OLED显示数字十进制带符号数
* @param Line 起始行位置范围1~4
* @param Column 起始列位置范围1~16
* @param Number 要显示的数字,范围:-2147483648~2147483647
* @param Length 要显示数字的长度范围1~10
* @retval 无
*/
Oled& ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length)
{
uint8_t i;
uint32_t Number1;
if (Number >= 0)
{
ShowChar(Line, Column, '+');
Number1 = Number;
}
else
{
ShowChar(Line, Column, '-');
Number1 = -Number;
}
for (i = 0; i < Length; i++)
{
ShowChar(Line, Column + i + 1, Number1 / Pow(10, Length - i - 1) % 10 + '0');
}
return *this;
}
/**
* @brief OLED显示数字十六进制正数
* @param Line 起始行位置范围1~4
* @param Column 起始列位置范围1~16
* @param Number 要显示的数字范围0~0xFFFFFFFF
* @param Length 要显示数字的长度范围1~8
* @retval 无
*/
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 / Pow(16, Length - i - 1) % 16;
if (SingleNumber < 10)
{
ShowChar(Line, Column + i, SingleNumber + '0');
}
else
{
ShowChar(Line, Column + i, SingleNumber - 10 + 'A');
}
}
return *this;
}
/**
* @brief OLED显示数字二进制正数
* @param Line 起始行位置范围1~4
* @param Column 起始列位置范围1~16
* @param Number 要显示的数字范围0~1111 1111 1111 1111
* @param Length 要显示数字的长度范围1~16
* @retval 无
*/
Oled& ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length)
{
uint8_t i;
for (i = 0; i < Length; i++)
{
ShowChar(Line, Column + i, Number / Pow(2, Length - i - 1) % 2 + '0');
}
return *this;
}
Oled(const u32 &RCC_APB2Periph,GPIO_TypeDef *const& GPIOx,const u16 &GPIO_PIN_SCL,const u16 &GPIO_PIN_SDA)
:_RCC_APB2Periph(RCC_APB2Periph),_GPIOx(GPIOx),_GPIO_PIN_SCL(GPIO_PIN_SCL),_GPIO_PIN_SDA(GPIO_PIN_SDA){
RCC_APB2PeriphClockCmd(_RCC_APB2Periph, 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_SCL;
GPIO_Init(_GPIOx, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = _GPIO_PIN_SDA;
GPIO_Init(_GPIOx, &GPIO_InitStructure);
W_SCL(1);
W_SDA(1);
Init();
}
virtual ~Oled(){
GPIO_DeInit(_GPIOx);
RCC_APB2PeriphClockCmd(_RCC_APB2Periph, DISABLE);
}
};
}