项目简介
由于家里的路由器有点烂,只要长时间工作发烫后就和我说再见,本人也被这个断网折磨得苦不堪言。为此就想能不能设计一款带屏幕显示温度,风扇速度的,可以按键控制风扇速度同时还可以温度闭环控制的小装置。基于以上想法就有了本文的由来,这篇文章的目的是我希望你看完之后能明白怎么设计,各个模块是怎么工作的需要微控制器怎么配合它,我将以通俗一点的话语去讲述,毕竟这是博客不是论文。感谢嘉立创的支持,文中大量的图片来自于嘉立创,购买的电子元件大量来自于立创商城,3d打印的外壳也是三维猴出品。如有侵权立马删稿。
B站效果视频
路由器风扇PID控制
项目框架
首先设计之前,我得考虑到一些问题。
1.微控制器选择啥?
微控制器本人选择的是STM32F401RCT6单片机,因为小,便宜,功能够用。
2.怎么温控,用啥传感器?用啥执行器?
温控可以用PID进行控制,至于用位置式还是增量式无所谓。传感器选择DHT11温度传感器,因为家里还有不能浪费。执行器也就是谁扇风,买个电机即可但是得可以控制风速的。
3.怎么人工调速
人工调速就得考虑到有个上位机也就是显示屏显示相关数据,选择OLED因为家里有。调速就可以通过按键中断来进行调速。
4.电机调速怎么实现?
最常见的方法就是PWM控制电压从而控制速度,这就得用到TB6612电机驱动芯片,它就是用来控电压的,15V电源的话就得用升压电路啥的进行升压。
以上就是遇到的几个关键问题,以及大致的解决思路。
详细总结就是本设计是基于STM32F401RCT6单片机(便宜)设计的风扇PID温度自动调节装置,三个轻触开关分别可以加风速、减风速、风速归零。DHT11负责采集温湿度数据,OLED屏幕上显示温湿度以及风扇速度相关数据。通过TYPE_C口引入电源。15V升压部分采用boost升压电路。
硬件系统选型及原理图设计
元件及材料选型
STM32F401RCT6
STM32F401RCT6 是意法半导体(STMicroelectronics)推出的 STM32 F4 系列微控制器(MCU) 中的一款型号。STM32 F4 系列是基于 ARM Cortex-M4 内核的高性能 32 位微控制器。
ARM Cortex-M4 内核,主频最高可达 84 MHz
Flash 存储:512 KB 的 Flash 存储,用于程序存储。
SRAM:96 KB 的 SRAM,用于数据存储。
I2C:2 个 I2C(串行外设接口),支持与外部传感器或其他设备进行通信。
UART:多达 3 个 UART(异步串行通信),用于与其他设备通信。
定时器:多达 6 个定时器,支持 PWM(脉冲宽度调制)、输入捕获、输出比较等功能。
以上是本人比较关注的几个点。
STM32F401RCT6 原理图设计
从图中也可以很清晰的看出,按键使用了3个,分别连接PC0、PC1、PC2。两路PWM,PB5、PB6。使用了一个串口PA9,PA10等等。
电机驱动TB6612
电机驱动选用的是TB6612电机驱动芯片,该驱动模块具有强劲的驱动能力,它的优势在于发热量低能量转换效率高,抗干扰能力强。TB6612FNG是一款采用带输出晶体管的直流电机驱动IC低导通电阻的LD MOS结构的驱动芯片。两个输入信号,IN1和IN2,可以选择四种模式之一,如连续、快速连续、短制动和停止模式。要求PWM工作频率不得大于100KHZ,输入电压VM不可大于15V。平衡车主要使用其快速连续、停止模式两功能从而实现对电机的快速控制。如图4-5所示为TB6612电机驱动实物。
关于它的详细讲解请参考这篇文章:
(四)STM32F407 cubemx定时器PWM驱动tb6612具体不做细致讲解了。
TB6612原理图设计
芯片主要部分是U7,从STM32处引出的引脚AIN1,AIN2,BIN1,BIN2用于控制两个电机的正反转方向。STBY是通过PB9进行控制的。定时器的两路PWM分别给了PWMA,PWMB引脚。VM也就是接地GND。控制两个电机的引脚分别是AO1,AO1,BO1,BO2。下面的U6,U5是我打的几个过孔,方便我测试用的,可去掉。
如图所示它的孔比较密、小。
如图所示P1,P2就是连接电机的引脚,本人用的贴片排针,有电热台不想焊。
风扇直流电机
本人测试过,可以通过改变电压控制风速。
OLED屏
数据显示主要使用的是OLED屏,其对比度高、厚度薄、视角广、反应速度快、功耗低,更加适合小系统。STM32通过IIC协议访问寄存器地址0X78传输显示交互数据,以及显示相应数据方便调试工作。
关于它的详细讲解请参考这几篇文章:
(五)STM32F407 cubemx IIC驱动OLED(1)IIC协议篇
(五)STM32F407 cubemx IIC驱动OLED(2)硬件篇
(五)STM32F407 cubemx IIC驱动OLED(3)软件篇
OLED原理图设计
没啥好讲的就是使用的IIC1,连接的引脚是PB6,PB7。
DHT11
DHT11 是一种常用的温湿度传感器,广泛应用于温湿度监测系统中。它能够测量环境中的温度和相对湿度,并通过数字信号输出这些测量值。DHT11 是一种低成本的传感器,常用于嵌入式系统、Arduino 项目、家庭自动化以及气象站等应用。
关于它的详细讲解请参考这篇文章:stm32F103C8T6控制DHT11这篇文章是我很久之前学习标准库写的,后续开发是基于hal库,可以参考一下其中的理论基础。
DHT11 原理图设计
本人用的PC9传输信号,上拉电阻是按照数据手册的要求接的。
原数据手册截图,建议连接线长度短于20米时用5K上拉电阻,大于20米时根据实际情况使用合适的上拉电阻。接了个上拉电阻即可,我是家里只有4.7K,不想买了,最好还是用5K。
按键
按键使用的是常见的轻触开关。
接法很简单,模式设置为上拉。
TYPC接口
TYPC接口原理图设计
USB Type-C 接口是可以正反插的,也就是说,无论插头正面还是背面插入,连接的设备都应该能够正常工作。为了解决这个问题,Type-C 接口设计了两个 CC (Configuration Channel) 引脚:CC1 和 CC2,分别用于检测插头的两种不同方向。当你插入 Type-C 连接器时,两个 CC 引脚 中的一个会接收到电阻,而另一个引脚则会被浮空(未连接)。设备通过检测到这两个引脚的状态,来判断插头的插入方向。
每个 CC 引脚 连接一个下拉电阻。通常情况下,这两个下拉电阻的阻值为 5.1kΩ。这两个电阻分别连接在 CC1 和 CC2 引脚上,以确保设备能够根据引脚状态正确识别 USB 的连接方向。
升压电路设计器件选型TLV61048DBVR
选择它因为便宜、有手册、德州的芯片值得信赖。
这张图上写的是14V最高输出。
但是芯片手册上写的却是15V,一切遵行芯片手册。以上是本人比较关注的几个点,首先我的输入电压为5v符合输入电源的要求,其次工作电流可以达到4.7A,本人估计最终0.5A可能都不到,绰绰有余。工作频率接下来按照手册要求进行设计。
1.FB引脚也就是设置输出电压大小的引脚。
2.EN引脚用于启动芯片,所以设计时一直给他5V输入是最好的。
3.本人想着FREQ连接GND引脚,将其设置成1MHZ。
想具体了解芯片电路设计可以参考这篇文章学会如何根据芯片手册设计参数
锂电池充电板电路设计具体设计本人就不细讲了,德州仪器的芯片手册写的很全的,很值得学习。
15V升压电路原理图
以上原理图来自于官方的芯片手册。本人只是在它的基础上加了几个滤波电容。具体可以看我的嘉立创开源项目链接。
软件部分
CUBEMX配置
1.首先基于原理图配置相应的功能引脚,将引脚的名字重定义,方便我使用和理解。KEY_PA15是核心板板子上板载的按键,本人定义了它,方便随时使用。
KEY1,KEY2,KEY3我设置的是上拉模式,不用外接电阻。这是通过软件实现了芯片内部的功能设置。如果你偏要外接一个电阻上拉,那你就将其设置成输入模式。功能一样的,如果你设置成了上拉模式,理论上也没问题,就相当于你拉了两个电阻也就等效成了一个原电阻0.5倍的电阻了。
2.KEY1,KEY2,KEY3配置的是外部中断模式。
3.IIC使用的是IIC1,配置的引脚是PB6,PB7。
4.定时器配置的是定时器3,PB4,PB5提供PWM。
5.串口使用的是串口1,PA9,PA10引脚。
软件代码部分
以上很多内容本人都写过和hal库相关的代码。重点讲一下DHT11温度检测代码的撰写吧。
DHT11代码
/**********************************************
步骤一DHT11上电后(DHT11上电后要等待 1S 以越过不稳定状态在此期间不能发送任何指令),测试环境
温湿度数据,并记录数据,同时 DHT11的DATA数据线由上拉电阻拉高一直保持高电平;此时 DHT11的
DATA 引脚处于输入状态,时刻检测外部信号
函数名:u8 DHT11_Init(void)
参数说明:无
返回值:u8 ,返回1代表初始化成功,0则失败
函数作用:配置IO口,并发送开始信号
***********************************************/
uint8_t DHT11_Init(void)
{
DHT11_Rst();//发送开始信号
return DHT11_Check();//检测DHT11的响应
}
/**********************************************
步骤二: 微处理器的I/O设置为输出同时输出低电平,且低电平保持时间不能小于18ms(最大不得超过30ms),
然后微处理器的I/O设置为输入状态,由于上拉电阻,微处理器的I/O即DHT11的DATA数据线也随之变
高,等待DHT11作出回答信号,
函数名:static void DHT11_Rst(void)
参数说明:无
返回值:无
函数作用:主机发送开始信号
***********************************************/
//这是它的物理工作原理,根据原理拉高或拉低它的引脚来唤醒dht11
static void DHT11_Rst(void)
{
GPIO_SETOUT(); //配置成输出模式
HAL_GPIO_WritePin(DHT11_IO,DHT11_PIN,GPIO_PIN_RESET); //拉低数据线
HAL_Delay(20); //拉低至少18ms
HAL_GPIO_WritePin(DHT11_IO,DHT11_PIN,GPIO_PIN_SET); ; //拉高数据线
delay_us(13);
}
/**********************************************
步骤三: 设置为输入模式,DHT11的DATA引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后DHT11的DATA
引脚处于输出状态,输出 83微秒的低电平作为应答信号,紧接着输出 87 微秒的高电平通知外设准备接
收数据,微处理器的 I/O 此时处于输入状态,检测到 I/O 有低电平(DHT11回应信号)后,等待87微秒
的高电平后的数据接收
程序思路:先是83us的低电平然后是87us的高电平,整个周期在170us,若检测低电平小于83us时证明其有响应由低变高
函数名:static u8 DHT11_Check(void)
参数说明:无
返回值:检测到回应-->返回1,否则0
函数作用:检测DHT11的响应信号
***********************************************/
uint8_t DHT11_Check(void)
{
uint8_t retry=0;
GPIO_SETIN(); //设置为输入模式
while (HAL_GPIO_ReadPin(DHT11_IO,DHT11_PIN)==0 && retry<83)//DHT11会拉低40~50us
{
retry++;
delay_us(1);
}
if(retry >= 83) //超时未响应/未收到开始信号,退出检测
return 0;
else
retry = 0;
while (HAL_GPIO_ReadPin(DHT11_IO,DHT11_PIN)==1 && retry<87)//DHT11拉低后会再次拉高40~50us
{
retry++;
delay_us(1);
}
if(retry>=87) //超时,DHT11工作出错,退出检测
return 0;
return 1; //设备正常响应,可以正常工作
}
/**********************************************
步骤四: 由DHT11的DATA引脚输出40位数据,微处理器根据I/O电平的变化接收40位数据,
位数据“0”的格式为: 54 微秒的低电平和 23-27 微秒的高电平,
位数据“1”的格式为: 54 微秒的低电平加 68-74
微秒的高电平
函数名:static u8 DHT11_Read_Bit(void)
参数说明:无
返回值:返回从DHT11上读取的一个Bit数据
函数作用:从DHT11上读取一个Bit数据
***********************************************/
uint8_t DHT11_Read_Bit(void)
{
uint8_t retry = 0;
//DHT11的Bit开始信号为12-14us低电平
while(HAL_GPIO_ReadPin(DHT11_IO,DHT11_PIN)==1 && retry<100)//等待变为低电平(等待Bit开始信号)
{
retry++;
delay_us(1);
}
retry = 0;
while(HAL_GPIO_ReadPin(DHT11_IO,DHT11_PIN)==0 && retry<100)//等待变高电平(代表数据开始传输)
{
retry++;
delay_us(1);
}
delay_us(30);//等待30us
//0信号为23-27us,30us延时过后进入低电平就是0,1信号则为68-74us,30us延时过后仍然是高电平就是1
if(HAL_GPIO_ReadPin(DHT11_IO,DHT11_PIN)) return 1;
else return 0;
}
/***********************************************************************
函数名:static u8 DHT11_Read_Byte(void)
参数说明:无
返回值:返回从DHT11上读取的一个byte数据
函数作用:从DHT11上读取一个byte数据
************************************************************************/
uint8_t DHT11_Read_Byte(void)
{
uint8_t i,dat;
dat=0;
for (i=0;i<8;i++)
{
dat<<=1;
dat|=DHT11_Read_Bit();
}
return dat;
}
/**************************************************************************
函数名:u8 DHT11_Read_Data(u8 *temp,u8 *humi)
参数说明:temp:用于存放温度值(范围:0~50°),humi:用于存放湿度值(范围:20%~90%)
返回值:1:成功读取数据,0:读取数据出错
函数作用:从DHT11上读取温湿度数据(这里省略小数值)
***************************************************************************/
uint8_t DHT11_Read_Data(uint8_t *temp,uint8_t *humi)
{
uint8_t buf[5];
uint8_t i;
DHT11_Rst();
if(DHT11_Check()==1) //设备响应正常
{
for(i=0;i<5;i++)//读取40位数据
{
buf[i]=DHT11_Read_Byte();
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])//进行校验
{
*humi=buf[0];
*temp=buf[2];
}
}else return 0; //设备未成功响应,返回0
return 1; //读取数据成功返回1
}
以上代码本人是从以前的标准库中移植过来的,每一块代码为什么这么写,注释写的很详细了。
TB6612代码
//L298N的周期为20KHz,72MHZ/36(分频)/周期(100)=20KHz,pwm值介于0-100之间
#include "tb6612.h"
uint8_t velocity = 50;
void Motor_1_PRun(uint8_t velocity) //电机1正转左轮
{
__HAL_TIM_SET_COMPARE(&TB6612_TIMX, TIM_CHANNEL_3,50);
IN1_1;IN2_0;
}
void Motor_2_PRun(uint8_t velocity) //电机2正转右轮
{
__HAL_TIM_SET_COMPARE(&TB6612_TIMX, TIM_CHANNEL_4,50);
IN3_1;IN4_0;
}
/*************************************************
Function: // Speed_Left(short Speed)
Description: // 左轮速度设置
Input: // short Speed
Return: // void
Others: //
*************************************************/
void Speed_Left(short Speed)
{
if(Speed < SPEED_MINI) Speed = SPEED_MINI;
else if(Speed > SPEED_MAX) Speed = SPEED_MAX;
else Speed = Speed;
__HAL_TIM_SET_COMPARE(&TB6612_TIMX,TIM_CHANNEL_1,Speed);//左轮
}
/*************************************************
Function: // Speed_Right(short Speed)
Description: // 右轮速度设置
Input: // short Speed
Return: // void
Others: //
*************************************************/
void Speed_Right(short Speed)
{
if(Speed < SPEED_MINI) Speed = SPEED_MINI; //速度限幅
else if(Speed > SPEED_MAX) Speed = SPEED_MAX;
else Speed = Speed;
__HAL_TIM_SET_COMPARE(&TB6612_TIMX,TIM_CHANNEL_2,Speed);//右轮
}
float KP=100;
float KI=100;
float KD=1;
float err,err1,err2, temperture_last,PID_value;
short target_temp=32;
short Fan_PID(uint8_t temperture)
{
float err_D;
err2=err1;
err1=err;
err_D =temperture - temperture_last;
err= temperture -target_temp;
temperture_last=temperture;
PID_value = KP*err+KI*(err1+err2+err)+KD*err_D;
if(PID_value>1500) PID_value=1500;
else if(PID_value<0) PID_value=0;
else {}
return PID_value;
}
OLED代码1
/*
* oled.c
*
* Created on: 2022年7月24日
* Author: Unicorn_Li
*/
#include "oled.h"
/**********************************************************
* 初始化命令,根据芯片手册书写,详细步骤见上图以及注意事项
***********************************************************/
uint8_t CMD_Data[]={
0xAE, 0xD5, 0x80, 0xA8, 0x3F, 0xD3, 0x00, 0x40,0xA1, 0xC8, 0xDA,
0x12, 0x81, 0xCF, 0xD9, 0xF1, 0xDB, 0x40, 0xA4, 0xA6,0x8D, 0x14,
0xAF};
/**
* @function: void OLED_Init(void)
* @description: OLED初始化
* @return {*}
*/
void OLED_Init(void)
{
HAL_Delay(200);
WriteCmd();
}
void WriteCmd(void)
{
uint8_t i = 0;
for(i=0; i<23; i++)
{
HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x00,I2C_MEMADD_SIZE_8BIT,&CMD_Data[i],1,0x100);
}
}
/**
* @function: void OLED_WR_CMD(uint8_t cmd)
* @description: 向设备写控制命令
* @param {uint8_t} cmd 芯片手册规定的命令
* @return {*}
*/
void OLED_WR_CMD(uint8_t cmd)
{
HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x00,I2C_MEMADD_SIZE_8BIT,&cmd,1,0x100);
}
/**
* @function: void OLED_WR_DATA(uint8_t data)
* @description: 向设备写控制数据
* @param {uint8_t} data 数据
* @return {*}
*/
void OLED_WR_DATA(uint8_t data)
{
HAL_I2C_Mem_Write(&hi2c1 ,0x78,0x40,I2C_MEMADD_SIZE_8BIT,&data,1,0x100);
}
void OLED_On(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_WR_CMD(0xb0+i); //设置页地址(0~7)
OLED_WR_CMD(0x00); //设置显示位置—列低地址
//OLED_WR_CMD(0x10); //设置显示位置—列高地址
for(n=0;n<12;n++)
OLED_WR_DATA(0xff);
}
}
/**
* @function: OLED_Clear(void)
* @description: 清屏,整个屏幕是黑色的!和没点亮一样!!!
* @return {*}
*/
void OLED_Clear(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_WR_CMD(0xb0+i); //设置页地址(0~7)
OLED_WR_CMD(0x00); //设置显示位置—列低地址
OLED_WR_CMD(0x10); //设置显示位置—列高地址
for(n=0;n<128;n++)
OLED_WR_DATA(0x0);
}
}
/**
* @function: void OLED_Display_On(void)
* @description: 开启OLED显示
* @return {*}
*/
void OLED_Display_On(void)
{
OLED_WR_CMD(0X8D); //SET DCDC命令
OLED_WR_CMD(0X14); //DCDC ON
OLED_WR_CMD(0XAF); //DISPLAY ON,打开显示
}
/**
* @function: void OLED_Display_Off(void)
* @description: 关闭OLED显示
* @return {*}
*/
void OLED_Display_Off(void)
{
OLED_WR_CMD(0X8D); //SET DCDC命令
OLED_WR_CMD(0X10); //DCDC OFF
OLED_WR_CMD(0XAE); //DISPLAY OFF,关闭显示
}
/**
* @function: void OLED_Set_Pos(uint8_t x, uint8_t y)
* @description: 坐标设置
* @param {uint8_t} x,y注意x是0-128,y是0-7
* @return {*}
*/
void OLED_Set_Pos(uint8_t x, uint8_t y)
{
OLED_WR_CMD(0xb0+y); //设置页地址(0~7)
OLED_WR_CMD(((x&0xf0)>>4)|0x10); //设置显示位置—列低地址
OLED_WR_CMD(x&0x0f); //设置显示位置—列高地址
OLED_WR_DATA(0X18);
}
/**
* @function: unsigned int oled_pow(uint8_t m,uint8_t n)
* @description: m^n函数
* @param {uint8_t} m,n
* @return {unsigned int} result
*/
unsigned int oled_pow(uint8_t m,uint8_t n)
{
unsigned int result=1;
while(n--)result*=m;
return result;
}
/**
* @function: void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr, uint8_t Char_Size,uint8_t Color_Turn)
* @description: 在OLED12864特定位置开始显示一个字符
* @param {uint8_t} x字符开始显示的横坐标
* @param {uint8_t} y字符开始显示的纵坐标
* @param {uint8_t} chr待显示的字符
* @param {uint8_t} Char_Size待显示字符的字体大小,选择字体 16/12
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr,uint8_t Char_Size,uint8_t Color_Turn)
{
unsigned char c=0,i=0;
c=chr-' ';//得到偏移后的值
if(x>128-1){x=0;y=y+2;}
if(Char_Size ==16)
{
OLED_Set_Pos(x,y);
for(i=0;i<8;i++)
{
if(Color_Turn)
OLED_WR_DATA(~F8X16[c*16+i]);
else
OLED_WR_DATA(F8X16[c*16+i]);
}
OLED_Set_Pos(x,y+1);
for(i=0;i<8;i++)
{
if(Color_Turn)
OLED_WR_DATA(~F8X16[c*16+i+8]);
else
OLED_WR_DATA(F8X16[c*16+i+8]);
}
}
else
{
OLED_Set_Pos(x,y);
for(i=0;i<6;i++)
{
if(Color_Turn)
OLED_WR_DATA(~F6x8[c][i]);
else
OLED_WR_DATA(F6x8[c][i]);
}
}
}
/**
* @function: void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *chr, uint8_tChar_Size, uint8_t Color_Turn)
* @description: 在OLED12864特定位置开始显示字符串
* @param {uint8_t} x待显示字符串的开始横坐标x:0~127
* @param {uint8_t} y待显示字符串的开始纵坐标 y:0~7,若选择字体大小为16,则两行数字之间需要间隔2,若选择字体大小为12,间隔1
* @param {uint8_t} *chr待显示的字符串
* @param {uint8_t} Char_Size待显示字符串的字体大小,选择字体 16/12,16为8X16,12为6x8
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_ShowString(uint8_t x,uint8_t y,char*chr,uint8_t Char_Size, uint8_t Color_Turn)
{
uint8_t j=0;
while (chr[j]!='\0')
{ OLED_ShowChar(x,y,chr[j],Char_Size, Color_Turn);
if (Char_Size == 12) //6X8的字体列加6,显示下一个字符
x += 6;
else //8X16的字体列加8,显示下一个字符
x += 8;
if (x > 122 && Char_Size==12) //TextSize6x8如果一行不够显示了,从下一行继续显示
{
x = 0;
y++;
}
if (x > 120 && Char_Size== 16) //TextSize8x16如果一行不够显示了,从下一行继续显示
{
x = 0;
y++;
}
j++;
}
}
/**
* @function: void OLED_ShowNum(uint8_t x,uint8_t y,unsigned int num,uint8_t len,uint8_t size2, Color_Turn)
* @description: 显示数字
* @param {uint8_t} x待显示的数字起始横坐标,x:0~126
* @param {uint8_t} y待显示的数字起始纵坐标, y:0~7,若选择字体大小为16,则两行数字之间需要间隔2,若选择字体大小为12,间隔1
* @param {unsigned int} num:输入的数据
* @param {uint8_t } len:输入的数据位数
* @param {uint8_t} size2:输入的数据大小,选择 16/12,16为8X16,12为6x8
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_ShowNum(uint8_t x,uint8_t y,unsigned int num,uint8_t len,uint8_t size2, uint8_t Color_Turn)
{
uint8_t t,temp;
uint8_t enshow=0;
for(t=0;t<len;t++)
{
temp=(num/oled_pow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
OLED_ShowChar(x+(size2/2)*t,y,' ',size2, Color_Turn);
continue;
}else enshow=1;
}
OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2, Color_Turn);
}
}
/**
* @function: void OLED_Showdecimal(uint8_t x,uint8_t y,float num,uint8_t z_len,uint8_t f_len,uint8_t size2, uint8_t Color_Turn)
* @description: 显示正负浮点数
* @param {uint8_t} x待显示的数字起始横坐标,x:0~126
* @param {uint8_t} y待显示的数字起始纵坐标, y:0~7,若选择字体大小为16,则两行数字之间需要间隔2,若选择字体大小为12,间隔1
* @param {float} num:输入的浮点型数据
* @param {uint8_t } z_ len:整数部分的位数
* @param {uint8_t } f_len: 小数部分的位数
* @param {uint8_t} size2:输入的数据大小,选择 16/12,16为8X16,12为6x8
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_Showdecimal(uint8_t x,uint8_t y,float num,uint8_t z_len,uint8_t f_len,uint8_t size2, uint8_t Color_Turn)
{
uint8_t t,temp,i=0;//i为负数标志位
uint8_t enshow;
int z_temp,f_temp;
if(num<0)
{
z_len+=1;
i=1;
num=-num;
}
z_temp=(int)num;
//整数部分
for(t=0;t<z_len;t++)
{
temp=(z_temp/oled_pow(10,z_len-t-1))%10;
if(enshow==0 && t<(z_len-1))
{
if(temp==0)
{
OLED_ShowChar(x+(size2/2)*t,y,' ',size2, Color_Turn);
continue;
}
else
enshow=1;
}
OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2, Color_Turn);
}
//小数点
OLED_ShowChar(x+(size2/2)*(z_len),y,'.',size2, Color_Turn);
f_temp=(int)((num-z_temp)*(oled_pow(10,f_len)));
//小数部分
for(t=0;t<f_len;t++)
{
temp=(f_temp/oled_pow(10,f_len-t-1))%10;
OLED_ShowChar(x+(size2/2)*(t+z_len)+5,y,temp+'0',size2, Color_Turn);
}
if(i==1)//如果为负,就将最前的一位赋值‘-’
{
OLED_ShowChar(x,y,'-',size2, Color_Turn);
i=0;
}
}
/**
* @function: void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no, uint8_t Color_Turn)
* @description: 在OLED特定位置开始显示16X16汉字
* @param {uint8_t} x待显示的汉字起始横坐标x: 0~112,两列汉字之间需要间隔16
* @param {uint8_t} y待显示的汉字起始纵坐标 y: 0~6 , 两行汉字之间需要间隔2
* @param {uint8_t} no待显示的汉字编号
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no, uint8_t Color_Turn)
{
uint8_t t=0;
OLED_Set_Pos(x,y);
for(t=0;t<16;t++)
{
if (Color_Turn)
OLED_WR_DATA(~Hzk[2*no][t]); //显示汉字的上半部分
else
OLED_WR_DATA(Hzk[2*no][t]); //显示汉字的上半部分
}
OLED_Set_Pos(x,y+1);
for(t=0;t<16;t++)
{
if (Color_Turn)
OLED_WR_DATA(~Hzk[2*no+1][t]); //显示汉字的上半部分
else
OLED_WR_DATA(Hzk[2*no+1][t]);//显示汉字的上半部分
}
}
/**
* @function: void OLED_DrawBMP(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t * BMP,uint8_t Color_Turn)
* @description: 在OLED特定区域显示BMP图片
* @param {uint8_t} x0图像开始显示横坐标 x0:0~127
* @param {uint8_t} y0图像开始显示纵坐标 y0:0~7
* @param {uint8_t} x1图像结束显示横坐标 x1:1~128
* @param {uint8_t} y1图像结束显示纵坐标 y1:1~8
* @param {uint8_t} *BMP待显示的图像数据
* @param {uint8_t} Color_Turn是否反相显示(1反相、0不反相)
* @return {*}
*/
void OLED_DrawBMP(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t * BMP,uint8_t Color_Turn)
{
uint32_t j = 0;
uint8_t x = 0, y = 0;
if(y1%8==0)
y = y1/8;
else
y = y1/8 + 1;
for(y=y0;y<y1;y++)
{
OLED_Set_Pos(x0,y);
for(x=x0;x<x1;x++)
{
if (Color_Turn)
OLED_WR_DATA(~BMP[j++]);//显示反相图片
else
OLED_WR_DATA(BMP[j++]);//显示图片
}
}
}
/**
* @function: void OLED_HorizontalShift(uint8_t direction)
* @description: 屏幕内容水平全屏滚动播放
* @param {uint8_t} direction LEFT 0x27 RIGHT 0x26
* @return {*}
*/
void OLED_HorizontalShift(uint8_t direction)
{
OLED_WR_CMD(0x2e);//停止滚动
OLED_WR_CMD(direction);//设置滚动方向
OLED_WR_CMD(0x00);//虚拟字节设置,默认为0x00
OLED_WR_CMD(0x00);//设置开始页地址
OLED_WR_CMD(0x07);//设置每个滚动步骤之间的时间间隔的帧频
// 0x00-5帧, 0x01-64帧, 0x02-128帧, 0x03-256帧, 0x04-3帧, 0x05-4帧, 0x06-25帧, 0x07-2帧,
OLED_WR_CMD(0x07);//设置结束页地址
OLED_WR_CMD(0x00);//虚拟字节设置,默认为0x00
OLED_WR_CMD(0xff);//虚拟字节设置,默认为0xff
OLED_WR_CMD(0x2f);//开启滚动-0x2f,禁用滚动-0x2e,禁用需要重写数据
}
/**
* @function: void OLED_Some_HorizontalShift(uint8_t direction,uint8_t start,uint8_t end)
* @description: 屏幕部分内容水平滚动播放
* @param {uint8_t} direction LEFT 0x27 RIGHT 0x26
* @param {uint8_t} start 开始页地址 0x00~0x07
* @param {uint8_t} end 结束页地址 0x01~0x07
* @return {*}
*/
void OLED_Some_HorizontalShift(uint8_t direction,uint8_t start,uint8_t end)
{
OLED_WR_CMD(0x2e);//停止滚动
OLED_WR_CMD(direction);//设置滚动方向
OLED_WR_CMD(0x00);//虚拟字节设置,默认为0x00
OLED_WR_CMD(start);//设置开始页地址
OLED_WR_CMD(0x07);//设置每个滚动步骤之间的时间间隔的帧频,0x07即滚动速度2帧
OLED_WR_CMD(end);//设置结束页地址
OLED_WR_CMD(0x00);//虚拟字节设置,默认为0x00
OLED_WR_CMD(0xff);//虚拟字节设置,默认为0xff
OLED_WR_CMD(0x2f);//开启滚动-0x2f,禁用滚动-0x2e,禁用需要重写数据
}
/**
* @function: void OLED_VerticalAndHorizontalShift(uint8_t direction)
* @description: 屏幕内容垂直水平全屏滚动播放
* @param {uint8_t} direction 右上滚动 0x29
* 左上滚动 0x2A
* @return {*}
*/
void OLED_VerticalAndHorizontalShift(uint8_t direction)
{
OLED_WR_CMD(0x2e);//停止滚动
OLED_WR_CMD(direction);//设置滚动方向
OLED_WR_CMD(0x01);//虚拟字节设置
OLED_WR_CMD(0x00);//设置开始页地址
OLED_WR_CMD(0x07);//设置每个滚动步骤之间的时间间隔的帧频,即滚动速度
OLED_WR_CMD(0x07);//设置结束页地址
OLED_WR_CMD(0x01);//垂直滚动偏移量
OLED_WR_CMD(0x00);//虚拟字节设置,默认为0x00
OLED_WR_CMD(0xff);//虚拟字节设置,默认为0xff
OLED_WR_CMD(0x2f);//开启滚动-0x2f,禁用滚动-0x2e,禁用需要重写数据
}
/**
* @function: void OLED_DisplayMode(uint8_t mode)
* @description: 屏幕内容取反显示
* @param {uint8_t} direction ON 0xA7 ,
* OFF 0xA6 默认此模式,设置像素点亮
* @return {*}
*/
void OLED_DisplayMode(uint8_t mode)
{
OLED_WR_CMD(mode);
}
/**
* @function: void OLED_IntensityControl(uint8_t intensity)
* @description: 屏幕亮度调节
* @param {uint8_t} intensity 0x00~0xFF,RESET=0x7F
* @return {*}
*/
void OLED_IntensityControl(uint8_t intensity)
{
OLED_WR_CMD(0x81);
OLED_WR_CMD(intensity);
}
OLED代码2
/*
* oledfont.c
*
* Created on: Jul 24, 2022
* Author: Unicorn_Li
*/
#include "oledfont.h"
//8*6 ASCII字符集点阵
const unsigned char F6x8[][6] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// sp
0x00, 0x00, 0x00, 0x2f, 0x00, 0x00,// !
0x00, 0x00, 0x07, 0x00, 0x07, 0x00,// "
0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14,// #
0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12,// $
0x00, 0x62, 0x64, 0x08, 0x13, 0x23,// %
0x00, 0x36, 0x49, 0x55, 0x22, 0x50,// &
0x00, 0x00, 0x05, 0x03, 0x00, 0x00,// '
0x00, 0x00, 0x1c, 0x22, 0x41, 0x00,// (
0x00, 0x00, 0x41, 0x22, 0x1c, 0x00,// )
0x00, 0x14, 0x08, 0x3E, 0x08, 0x14,// *
0x00, 0x08, 0x08, 0x3E, 0x08, 0x08,// +
0x00, 0x00, 0x00, 0xA0, 0x60, 0x00,// ,
0x00, 0x08, 0x08, 0x08, 0x08, 0x08,// -
0x00, 0x00, 0x60, 0x60, 0x00, 0x00,// .
0x00, 0x20, 0x10, 0x08, 0x04, 0x02,// /
0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E,// 0
0x00, 0x00, 0x42, 0x7F, 0x40, 0x00,// 1
0x00, 0x42, 0x61, 0x51, 0x49, 0x46,// 2
0x00, 0x21, 0x41, 0x45, 0x4B, 0x31,// 3
0x00, 0x18, 0x14, 0x12, 0x7F, 0x10,// 4
0x00, 0x27, 0x45, 0x45, 0x45, 0x39,// 5
0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30,// 6
0x00, 0x01, 0x71, 0x09, 0x05, 0x03,// 7
0x00, 0x36, 0x49, 0x49, 0x49, 0x36,// 8
0x00, 0x06, 0x49, 0x49, 0x29, 0x1E,// 9
0x00, 0x00, 0x36, 0x36, 0x00, 0x00,// :
0x00, 0x00, 0x56, 0x36, 0x00, 0x00,// ;
0x00, 0x08, 0x14, 0x22, 0x41, 0x00,// <
0x00, 0x14, 0x14, 0x14, 0x14, 0x14,// =
0x00, 0x00, 0x41, 0x22, 0x14, 0x08,// >
0x00, 0x02, 0x01, 0x51, 0x09, 0x06,// ?
0x00, 0x32, 0x49, 0x59, 0x51, 0x3E,// @
0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C,// A
0x00, 0x7F, 0x49, 0x49, 0x49, 0x36,// B
0x00, 0x3E, 0x41, 0x41, 0x41, 0x22,// C
0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C,// D
0x00, 0x7F, 0x49, 0x49, 0x49, 0x41,// E
0x00, 0x7F, 0x09, 0x09, 0x09, 0x01,// F
0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A,// G
0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F,// H
0x00, 0x00, 0x41, 0x7F, 0x41, 0x00,// I
0x00, 0x20, 0x40, 0x41, 0x3F, 0x01,// J
0x00, 0x7F, 0x08, 0x14, 0x22, 0x41,// K
0x00, 0x7F, 0x40, 0x40, 0x40, 0x40,// L
0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F,// M
0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F,// N
0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E,// O
0x00, 0x7F, 0x09, 0x09, 0x09, 0x06,// P
0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E,// Q
0x00, 0x7F, 0x09, 0x19, 0x29, 0x46,// R
0x00, 0x46, 0x49, 0x49, 0x49, 0x31,// S
0x00, 0x01, 0x01, 0x7F, 0x01, 0x01,// T
0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F,// U
0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F,// V
0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F,// W
0x00, 0x63, 0x14, 0x08, 0x14, 0x63,// X
0x00, 0x07, 0x08, 0x70, 0x08, 0x07,// Y
0x00, 0x61, 0x51, 0x49, 0x45, 0x43,// Z
0x00, 0x00, 0x7F, 0x41, 0x41, 0x00,// [
0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55,// 55
0x00, 0x00, 0x41, 0x41, 0x7F, 0x00,// ]
0x00, 0x04, 0x02, 0x01, 0x02, 0x04,// ^
0x00, 0x40, 0x40, 0x40, 0x40, 0x40,// _
0x00, 0x00, 0x01, 0x02, 0x04, 0x00,// '
0x00, 0x20, 0x54, 0x54, 0x54, 0x78,// a
0x00, 0x7F, 0x48, 0x44, 0x44, 0x38,// b
0x00, 0x38, 0x44, 0x44, 0x44, 0x20,// c
0x00, 0x38, 0x44, 0x44, 0x48, 0x7F,// d
0x00, 0x38, 0x54, 0x54, 0x54, 0x18,// e
0x00, 0x08, 0x7E, 0x09, 0x01, 0x02,// f
0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C,// g
0x00, 0x7F, 0x08, 0x04, 0x04, 0x78,// h
0x00, 0x00, 0x44, 0x7D, 0x40, 0x00,// i
0x00, 0x40, 0x80, 0x84, 0x7D, 0x00,// j
0x00, 0x7F, 0x10, 0x28, 0x44, 0x00,// k
0x00, 0x00, 0x41, 0x7F, 0x40, 0x00,// l
0x00, 0x7C, 0x04, 0x18, 0x04, 0x78,// m
0x00, 0x7C, 0x08, 0x04, 0x04, 0x78,// n
0x00, 0x38, 0x44, 0x44, 0x44, 0x38,// o
0x00, 0xFC, 0x24, 0x24, 0x24, 0x18,// p
0x00, 0x18, 0x24, 0x24, 0x18, 0xFC,// q
0x00, 0x7C, 0x08, 0x04, 0x04, 0x08,// r
0x00, 0x48, 0x54, 0x54, 0x54, 0x20,// s
0x00, 0x04, 0x3F, 0x44, 0x40, 0x20,// t
0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C,// u
0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C,// v
0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C,// w
0x00, 0x44, 0x28, 0x10, 0x28, 0x44,// x
0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C,// y
0x00, 0x44, 0x64, 0x54, 0x4C, 0x44,// z
0x14, 0x14, 0x14, 0x14, 0x14, 0x14,// horiz lines
};
//16*8 ASCII字符集点阵
const unsigned char F8X16[]=
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//sp /0
0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! /1
0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" /2
0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# /3
0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ /4
0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% /5
0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& /6
0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' /7
0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( /8
0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) /9
0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* /10
0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ /11
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, /12
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- /13
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. /14
0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// /15
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 /16
0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 /17
0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 /18
0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 /19
0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 /20
0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 /21
0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 /22
0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 /23
0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 /24
0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 /25
0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: /26
0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; /27
0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< /28
0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= /29
0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> /30
0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? /31
0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ /32
0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A /33
0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B /34
0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C /35
0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D /36
0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E /37
0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F /38
0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G /39
0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H /40
0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I /41
0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J /42
0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K /43
0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L /44
0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M /45
0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N /46
0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O /47
0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P /48
0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q /49
0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R /50
0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S /51
0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T /52
0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U /53
0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V /54
0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W /55
0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X /56
0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y /57
0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z /58
0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ /59
0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ /60
0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] /61
0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ /62
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ /63
0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` /64
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a /65
0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b /66
0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c /67
0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d /68
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e /69
0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f /70
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g /71
0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h /72
0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i /73
0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j /74
0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k /75
0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l /76
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m /77
0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n /78
0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o /79
0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p /80
0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q /81
0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r /82
0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s /83
0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t /84
0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u /85
0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v /86
0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w /87
0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x /88
0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y /89
0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z /90
0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ /91
0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} /92
0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00};//| /93
//部分汉字 阴码,列行式,逆向
const unsigned char Hzk[][32]=
{
{0x10,0x60,0x02,0x8c,0x00,0x00,0xfe,0x92,0x92,0x92,0x92,0x92,0xfe,0x00,0x00,0x00},/* 0 温 */
{0x04,0x04,0x7e,0x01,0x40,0x7e,0x42,0x42,0x7e,0x42,0x7e,0x42,0x42,0x7e,0x40,0x00},
{0x00,0x00,0xfc,0x24,0x24,0x24,0xfc,0x25,0x26,0x24,0xfc,0x24,0x24,0x24,0x04,0x00},/* 1 度 */
{0x40,0x30,0x8f,0x80,0x84,0x4c,0x55,0x25,0x25,0x25,0x55,0x4c,0x80,0x80,0x80,0x00},
{0x00,0x18,0x24,0x24,0x18,0xc0,0x20,0x10,0x08,0x08,0x08,0x10,0x38,0x00,0x00,0x00},/* 2 ℃ */
{0x00,0x00,0x00,0x00,0x00,0x0f,0x10,0x20,0x40,0x40,0x40,0x40,0x20,0x10,0x00,0x00},
{0x10,0x60,0x02,0x8c,0x00,0xfe,0x92,0x92,0x92,0x92,0x92,0x92,0xfe,0x00,0x00,0x00},/* 3 湿 */
{0x04,0x04,0x7e,0x01,0x44,0x48,0x50,0x7f,0x40,0x40,0x7f,0x50,0x48,0x44,0x40,0x00},
{0x00,0x00,0xfc,0x24,0x24,0x24,0xfc,0x25,0x26,0x24,0xfc,0x24,0x24,0x24,0x04,0x00},/* 4 度 */
{0x40,0x30,0x8f,0x80,0x84,0x4c,0x55,0x25,0x25,0x25,0x55,0x4c,0x80,0x80,0x80,0x00},
{0x38,0x44,0x44,0x38,0xc0,0x30,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/* 5 % */
{0x40,0x30,0x0c,0x03,0x38,0x44,0x44,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0xfe,0x02,0x12,0x22,0xc2,0x02,0xc2,0x32,0x02,0xfe,0x00,0x00,0x00,0x00},/* 6 风 */
{0x80,0x60,0x1f,0x00,0x20,0x10,0x0c,0x03,0x0c,0x30,0x00,0x0f,0x30,0x40,0xf8,0x00},
{0x00,0x00,0xfc,0x24,0x24,0x24,0x25,0x26,0x24,0x24,0x24,0x24,0x24,0x3c,0x00,0x00},/* 7 扇 */
{0x40,0x30,0x0f,0x21,0x15,0x49,0x81,0x7f,0x00,0x21,0x15,0x49,0x81,0x7f,0x00,0x00},
{0x40,0x40,0x42,0xcc,0x00,0x04,0xf4,0x94,0x94,0xff,0x94,0x94,0xf4,0x04,0x00,0x00},/* 8 速 */
{0x00,0x40,0x20,0x1f,0x20,0x48,0x44,0x42,0x41,0x5f,0x41,0x42,0x44,0x48,0x40,0x00},
{0x00,0x00,0xfc,0x24,0x24,0x24,0xfc,0x25,0x26,0x24,0xfc,0x24,0x24,0x24,0x04,0x00},/* 9 度 */
{0x40,0x30,0x8f,0x80,0x84,0x4c,0x55,0x25,0x25,0x25,0x55,0x4c,0x80,0x80,0x80,0x00,}
};
//128*64图片
unsigned char BMP1[]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x40,0xE0,0xE0,0x60,
0x00,0x40,0x80,0x00,0x00,0x00,0x80,0x80,0x60,0x60,0x10,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x90,0xB2,0x66,0x6E,0xEC,0xC9,0x83,0x02,0x00,0x40,0x80,
0x00,0x0C,0x0C,0x01,0x03,0x07,0x0F,0x11,0x20,0x40,0x80,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x08,0x18,0x3B,0x37,0x66,0xEE,0xEE,0xCC,0x88,0x80,0x00,0x00,
0x01,0x02,0x04,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x0F,0x00,0x00,0x00,0x00,0x00,
0x00,0x3E,0x40,0x40,0x40,0x3E,0x00,0x7E,0x04,0x08,0x10,0x7E,0x00,0x7E,0x00,0x3C,
0x42,0x42,0x42,0x42,0x00,0x7E,0x42,0x42,0x42,0x7E,0x00,0x7E,0x04,0x08,0x10,0x7E,/*"C:\Users\HP\Desktop\UNICORN.BMP",0*/
};
unsigned char bearData[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x5f, 0x9f, 0xdf, 0xef, 0xef, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0x17,
0xd7, 0xe7, 0x07, 0x0f, 0x9f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00, 0xfe, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xbf, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xf8, 0xe3,
0x8f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x07, 0xf3, 0xfd, 0xec, 0xe7, 0x91, 0x2f, 0x5d,
0x7c, 0xfc, 0xdc, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7c, 0x01, 0x1f, 0xff, 0xff, 0xff, 0xff,
0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x07, 0x03, 0x01, 0x00, 0x01, 0x03, 0x07, 0x07, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x14, 0x0e, 0x1f, 0x1f, 0x1f, 0x0f, 0x07, 0x03, 0x00, 0x00, 0x00, 0x80, 0xc1, 0xe1, 0xff, 0xff, 0xfe, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0xf8,
0xf8, 0xf8, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0xc0, 0xe0, 0xf0, 0xf8,
0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
//const uint8_t zh16x16[][36] = {
///* 0 温 */ {0xe6,0xb8,0xa9,0x00,0xef,0x9f,0xfd,0x73,0xff,0xff,0x01,0x6d,0x6d,0x6d,0x6d,0x6d,0x01,0xff,0xff,0xff,0xfb,0xfb,0x81,0xfe,0xbf,0x81,0xbd,0xbd,0x81,0xbd,0x81,0xbd,0xbd,0x81,0xbf,0xff,},
///* 1 度 */ {0xe5,0xba,0xa6,0x00,0xff,0xff,0x03,0xdb,0xdb,0xdb,0x03,0xda,0xd9,0xdb,0x03,0xdb,0xdb,0xdb,0xfb,0xff,0xbf,0xcf,0x70,0x7f,0x7b,0xb3,0xaa,0xda,0xda,0xda,0xaa,0xb3,0x7f,0x7f,0x7f,0xff,}
//};
//const Font font16x16 = {.w =16, .h = 16, .chars = (const uint8_t *)zh16x16,.len = sizeof(zh16x16)/36, .ascii = &afont16x8};
外部按键中断代码
short fan_speed=0;
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == KEY1_Pin)
{
fan_speed+=100;
if(fan_speed>=1000) fan_speed=1000;
OLED_ShowNum(80,6,fan_speed,2,16,0);
}
if(GPIO_Pin == KEY2_Pin)
{
fan_speed-=100;
if(fan_speed<=0) fan_speed=0;
OLED_ShowNum(80,6,fan_speed,4,16,0);
}
if(GPIO_Pin == KEY3_Pin)
{
fan_speed=0;
OLED_ShowNum(80,6,fan_speed,4,16,0);
}
}
实验结果
失败的第一次
可以正常烧录程序但是IIC输出后程序烧录不了并且死机,到现在本人还不知道为什么。如果有大佬的话希望指点一下。本人详细描述一下这个问题:首先本人设计的核心板可以正常工作只要不用IIC就行,但是一旦将IIC引脚连接了,直接死机,代码也无法烧录。
调试会出现这个界面,他是自动跳入run的不是人工点的,stop都stop不了。
最终成果
本人还是放弃了自己设计核心板的思路,使用了现成的核心板。
上盖的数值算错了,里面的风扇太厚了,把它垫高了。本人改了上盖的文件大小,后续也没打印了,太贵了,太久了。
代码也有点小瑕疵,不知道为什么会有两个点,还有待改进。
本人将所有用到的资料说明书,代码放到此处:
通过网盘分享的文件:F401RCT6_FAN
链接: https://pan.baidu.com/s/1PBlDLgIsgpRCi4GpYqPiXQ?pwd=crhw 提取码: crhw
3D模型链接:https://makerworld.com.cn/zh/models/727124
PCB文件开源地址(嘉立创支持):https://oshwhub.com/roudragon/san-re-feng-shan-2-0