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 XLevelL0x00#define XLevelH0x10#define Max_Column128#define Max_Row64#defineBrightness0xFF #define X_WIDTH 128#define Y_WIDTH 64//-----------------OLED端口定义---------------- #defineOLED_RST_Pin GPIO_PIN_15#defineOLED_DC_Pin GPIO_PIN_14#defineOLED_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_CMD0//写命令#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>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&&t120){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++]);}}} //初始化SSD1306void OLED_Init(void){ OLED_RST_Clr();HAL_Delay(200);OLED_RST_Set(); OLED_WrCmd(0xAE); //display offOLED_WrCmd(0x20);//Set Memory Addressing ModeOLED_WrCmd(0x10);//00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,InvalidOLED_WrCmd(0xb0);//Set Page Start Address for Page Addressing Mode,0-7OLED_WrCmd(0xc8);//Set COM Output Scan DirectionOLED_WrCmd(0x00); //---set low column addressOLED_WrCmd(0x10); //---set high column addressOLED_WrCmd(0x40); //--set start line addressOLED_WrCmd(0x81); //--set contrast control registerOLED_WrCmd(0xff); //light 0x00~0xffOLED_WrCmd(0xa1); //--set segment re-map 0 to 127OLED_WrCmd(0xa6); //--set normal displayOLED_WrCmd(0xa8); //--set multiplex ratio(1 to 64)OLED_WrCmd(0x3F); //OLED_WrCmd(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM contentOLED_WrCmd(0xd3); //-set display offsetOLED_WrCmd(0x00); //-not offsetOLED_WrCmd(0xd5); //--set display clock divide ratio/oscillator frequencyOLED_WrCmd(0xf0); //--set divide ratioOLED_WrCmd(0xd9); //--set pre-charge periodOLED_WrCmd(0x22); //OLED_WrCmd(0xda); //--set com pins hardware configurationOLED_WrCmd(0x12);OLED_WrCmd(0xdb); //--set vcomhOLED_WrCmd(0x20); //0x20,0.77xVccOLED_WrCmd(0x8d); //--set DC-DC enableOLED_WrCmd(0x14); //OLED_WrCmd(0xaf); //--turn on oled panelOLED_WrCmd(0xAF);OLED_Set_Pos(0,0); }
整个工程打包在此,包括串口调试,屏幕驱动,DHT11温湿度模块,4*4矩阵键盘模块的驱动,可自行修改。
工程源码下载链接