1.实现的功能及所需模块
驱动单色0.96英寸七针OLED 显示屏
串口调试等功能
2.板子和开发环境
本文如题采用STM32F411RET6(NUCLEO)开发板如图所示。
开发环境使用MDK(keil5)和STM32CubeMX,不了解的同学可以去百度一下。
3.STM32CubeMX配置
首先选择对应的开发板型号,然后进入图形化配置界面。
第一步是时钟配置,每个板子在不考虑功耗的情况下,初学者的配置都是使用最高频率,如图,使用外部高速晶振时钟(HSE)。
然后点上方的Clock Configuration,这里不需要太多改动,只需要按照如图所示修改,然后填写最高Mhz即可自动配置。
先驱动屏幕,这里可自己查询oled屏幕驱动原理,在STM32中可以使用SPI也可以使用IIC驱动,本文使用SPI协议方便移植屏幕驱动,配置如图。屏幕的驱动代码我直接移植了其他板子的,由于hal库特性移植很容易,自己写需要查数据手册很麻烦不便于新手使用,这里我根据屏幕的驱动代码也需要增加几个引脚并且有所修改。其中PB13~PB15为自己添加的一个GPIO_Output高速引脚
到此0.96寸oled7针屏幕在配置就完成了。
接下来是串口调试的配置,这个十分简单,只需要在左侧选择categories->USART1或者USART2(根据个人调整)然后选择Asynchronous其他不用修改。
下面放一张F411RET6的引脚图方便对照接线。
4.屏幕驱动代码
直接上驱动代码,整个工程代码我会放在文末。
oled.h
#ifndef __oled_H
#define __oled_H
#include "main.h"
#define SIZE 16
#define XLevelL 0x00
#define XLevelH 0x10
#define Max_Column 128
#define Max_Row 64
#define Brightness 0xFF
#define X_WIDTH 128
#define Y_WIDTH 64
//-----------------OLED端口定义----------------
#define OLED_RST_Pin GPIO_PIN_15
#define OLED_DC_Pin GPIO_PIN_14
#define OLED_CS_Pin GPIO_PIN_13
#define OLED_RST_GPIO_Port GPIOB
#define OLED_DC_GPIO_Port GPIOB
#define OLED_CS_GPIO_Port GPIOB
#define OLED_CS_Set() HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, GPIO_PIN_SET);
#define OLED_CS_Clr() HAL_GPIO_WritePin(OLED_CS_GPIO_Port, OLED_CS_Pin, GPIO_PIN_RESET);
#define OLED_DC_Set() HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, GPIO_PIN_SET);
#define OLED_DC_Clr() HAL_GPIO_WritePin(OLED_DC_GPIO_Port, OLED_DC_Pin, GPIO_PIN_RESET);
#define OLED_RST_Set() HAL_GPIO_WritePin(OLED_RST_GPIO_Port, OLED_RST_Pin, GPIO_PIN_SET);
#define OLED_RST_Clr() HAL_GPIO_WritePin(OLED_RST_GPIO_Port, OLED_RST_Pin, GPIO_PIN_RESET);
#define OLED_CMD 0 //写命令
#define OLED_DATA 1 //写数据
//OLED控制用函数
void OLED_WrCmd(uint8_t cmd);
void OLED_Display_On(void);
void OLED_Display_Off(void);
void OLED_Init(void);
void OLED_Clear(void);
void OLED_DrawPoint(uint8_t x,uint8_t y,uint8_t t);
void OLED_Fill(uint8_t x1,uint8_t y1,uint8_t x2,uint8_t y2,uint8_t dot);
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr);
void OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size);
void OLED_ShowString(uint8_t x,uint8_t y, uint8_t *p);
void OLED_Set_Pos(unsigned char x, unsigned char y);
void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no);
void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[]);
#endif
oled.c
#include "oled.h"
#include "oledfont.h"
#include "main.h"
#include "spi.h"
uint8_t OLED_GRAM [128][8];
//OLED的显存
//存放格式如下
//[0]0 1 2 3 ... 127
//[1]0 1 2 3 ... 127
//[2]0 1 2 3 ... 127
//[3]0 1 2 3 ... 127
//[4]0 1 2 3 ... 127
//[5]0 1 2 3 ... 127
//[6]0 1 2 3 ... 127
//[7]0 1 2 3 ... 127
//向SSD1306写入一个字节
//dat:要写入的数据/命令
//cmd:数据/命令标志 0,表示命令;1,表示数据
void OLED_WB(uint8_t data)
{
HAL_SPI_Transmit(&hspi1, &data, 1, 1000);
}
void OLED_WrDat(uint8_t dat)
{
OLED_DC_Set();
OLED_WB(dat);
}
void OLED_WrCmd(uint8_t cmd)
{
OLED_DC_Clr();
OLED_WB(cmd);
}
void OLED_DrawPoint(uint8_t x,uint8_t y,uint8_t t)
{
uint8_t pos,bx,temp=0;
if(x>127||y>63)return;
pos=7-y/8;
bx=y%8;
temp=1<<(7-bx);
if(t)OLED_GRAM[x][pos]|=temp;
else OLED_GRAM[x][pos]&=~temp;
}
void OLED_Refresh_Gram(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
OLED_WrCmd(0xb0+i);
OLED_WrCmd(0x00);
OLED_WrCmd(0x10);
for(n=0;n<128;n++)
OLED_WrDat(OLED_GRAM[n][i]);
}
}
void OLED_Fill(uint8_t x1,uint8_t y1,uint8_t x2,uint8_t y2,uint8_t dot)
{
uint8_t x,y;
for(x=x1;x<=x2;x++)
{
for(y=y1;y<=y2;y++)OLED_DrawPoint(x,y,dot);
}
OLED_Refresh_Gram();
}
void OLED_Set_Pos(unsigned char x, unsigned char y)
{
OLED_WrCmd(0xb0+y);
OLED_WrCmd((((x+2)&0xf0)>>4)|0x10);
OLED_WrCmd(((x+2)&0x0f));
}
//开启OLED显示
void OLED_Display_On(void)
{
OLED_WrCmd(0X8D); //设置电荷泵命令字
OLED_WrCmd(0X14); //开启电荷泵
OLED_WrCmd(0XAF); //DISPLAY ON
}
//关闭OLED显示
void OLED_Display_Off(void)
{
OLED_WrCmd(0X8D); //设置电荷泵命令字
OLED_WrCmd(0X10); //关闭电荷泵
OLED_WrCmd(0XAE); //DISPLAY OFF
}
//清屏函数,清完后整个屏幕都是黑色的,没有一点光亮
void OLED_Clear(void)
{
OLED_Fill(0,0,127,63, 0x00);
HAL_Delay(20);
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~6
//mode:0,反白显示;1,正常显示
//size:选择字体大小 16/12
void OLED_ShowChar(uint8_t x,uint8_t y,uint8_t chr)
{
unsigned char c=0,i=0;
c=chr-' ';//得到偏移后的值
if(x>Max_Column-1){x=0;y=y+2;}
if(SIZE ==16)
{
OLED_Set_Pos(x,y);
for(i=0;i<8;i++)
OLED_WrDat(F8X16[c*16+i]);
OLED_Set_Pos(x,y+1);
for(i=0;i<8;i++)
OLED_WrDat(F8X16[c*16+i+8]);
}
else {
OLED_Set_Pos(x,y+1);
for(i=0;i<6;i++)
OLED_WrDat(F6x8[c][i]);
}
}
//m^n函数
uint32_t oled_pow(uint8_t m,uint8_t n)
{
uint32_t result=1;
while(n--)result*=m;
return result;
}
//显示两个数字
//x,y :起点坐标
//len :数字的位数
//size:字体大小
//mode:0:填充模式;1:叠加模式
//num:数值(0~4294967295);
void OLED_ShowNum(uint8_t x,uint8_t y,uint32_t num,uint8_t len,uint8_t size)
{
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+(size/2)*t,y,' ');
continue;
}else enshow=1;
}
OLED_ShowChar(x+(size/2)*t,y,temp+'0');
}
}
//显示一个字符串
void OLED_ShowString(uint8_t x,uint8_t y,uint8_t *chr)
{
unsigned char j=0;
while (chr[j]!='\0')
{ OLED_ShowChar(x,y,chr[j]);
x+=8;
if(x>120){x=0;y+=2;}
j++;
}
}
//显示汉字
void OLED_ShowCHinese(uint8_t x,uint8_t y,uint8_t no)
{
uint8_t t,adder=0;
OLED_Set_Pos(x,y);
for(t=0;t<16;t++)
{
OLED_WrDat(Hzk[2*no][t]);
adder+=1;
}
OLED_Set_Pos(x,y+1);
for(t=0;t<16;t++)
{
OLED_WrDat(Hzk[2*no+1][t]);
adder+=1;
}
}
/*显示BMP图片。x的范围为0~127,y的页得的范围0~7*/
void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[])
{
unsigned int j=0;
unsigned char x,y;
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++)
{
OLED_WrDat(BMP[j++]);
}
}
}
//初始化SSD1306
void OLED_Init(void)
{
OLED_RST_Clr();
HAL_Delay(200);
OLED_RST_Set();
OLED_WrCmd(0xAE); //display off
OLED_WrCmd(0x20); //Set Memory Addressing Mode
OLED_WrCmd(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
OLED_WrCmd(0xb0); //Set Page Start Address for Page Addressing Mode,0-7
OLED_WrCmd(0xc8); //Set COM Output Scan Direction
OLED_WrCmd(0x00); //---set low column address
OLED_WrCmd(0x10); //---set high column address
OLED_WrCmd(0x40); //--set start line address
OLED_WrCmd(0x81); //--set contrast control register
OLED_WrCmd(0xff); //light 0x00~0xff
OLED_WrCmd(0xa1); //--set segment re-map 0 to 127
OLED_WrCmd(0xa6); //--set normal display
OLED_WrCmd(0xa8); //--set multiplex ratio(1 to 64)
OLED_WrCmd(0x3F); //
OLED_WrCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
OLED_WrCmd(0xd3); //-set display offset
OLED_WrCmd(0x00); //-not offset
OLED_WrCmd(0xd5); //--set display clock divide ratio/oscillator frequency
OLED_WrCmd(0xf0); //--set divide ratio
OLED_WrCmd(0xd9); //--set pre-charge period
OLED_WrCmd(0x22); //
OLED_WrCmd(0xda); //--set com pins hardware configuration
OLED_WrCmd(0x12);
OLED_WrCmd(0xdb); //--set vcomh
OLED_WrCmd(0x20); //0x20,0.77xVcc
OLED_WrCmd(0x8d); //--set DC-DC enable
OLED_WrCmd(0x14); //
OLED_WrCmd(0xaf); //--turn on oled panel
OLED_WrCmd(0xAF);
OLED_Set_Pos(0,0);
}
整个工程打包在此,包括串口调试,屏幕驱动,DHT11温湿度模块,4*4矩阵键盘模块的驱动,可自行修改。文章来源:https://www.toymoban.com/news/detail-490207.html
工程源码下载链接文章来源地址https://www.toymoban.com/news/detail-490207.html
到了这里,关于【STM32】STM32F411RET6(NUCLEO)开发板基于HAL库创建工程模板及屏幕驱动的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!