打印
[STM32F1]

(分享)基于STM32F103系列控制的OLED经验分享

[复制链接]
443|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
elephant00|  楼主 | 2023-5-9 10:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
最近在研究四针的OLED 先上个效果图
总工程文件评论区留下邮箱我会发送





硬件部分
有开发板的直接用开发板就好 没有的去某宝买一块STM32F103C8T6(10元左右)
类似这种





接线部分
OLED一共有四个接口 本别是SCL(时钟),SDA(数据),GND(电源负),VCC3.3(注意是接3.3V, 5V会烧坏)
电源正负随便接是3.3V就OK SCL,SDA接单片机IO口 具体配置看原理图 我这个芯片的对应的是PB6,7用排线连接就好


硬件部分结束。

使用特权

评论回复
沙发
elephant00|  楼主 | 2023-5-9 10:09 | 只看该作者
软件部分
源码是借鉴的 亲测能用 不得不说 站在巨人的肩膀上真的很舒服 现在分享主和OLED C文件 总工程文件评论区留下邮箱我会发送
  • //主c文件
  • #include "delay.h"
  • #include "sys.h"
  • #include "oled.h"
  • #include "bmp.h"
  • int main(void)
  •   {        u8 t;
  •                 delay_init();                     //延时函数初始化
  •                 NVIC_Configuration();          //设置NVIC中断
  •         //        delay_ms(8000);
  •                 OLED_Init();
  •                 OLED_Clear()          ;
  •                 t=' ';
  •                 //显示汉字
  •                 OLED_ShowCHinese(18,0,0);//
  •                 OLED_ShowCHinese(36,0,1);//
  •                 OLED_ShowCHinese(72,0,2);//
  •                 OLED_ShowCHinese(90,0,3);//
  •         while(1)
  •         {
  •                 OLED_Clear();
  •                 OLED_ShowCHinese(18,0,0);
  •                 OLED_ShowCHinese(36,0,1);
  •                 OLED_ShowCHinese(72,0,2);
  •                 OLED_ShowCHinese(90,0,3);
  •                 OLED_ShowString(6,3,"0.96' OLED TEST",16);
  •                 OLED_ShowString(0,6,"ASCII:",16);
  •                 OLED_ShowString(63,6,"CODE:",16);
  •                 OLED_ShowChar(48,6,t,16);//显示字符
  •                 t++;
  •                 if(t>'~')t=' ';
  •                 OLED_ShowNum(103,6,t,3,16);
  •                 delay_ms(8000);
  •                 delay_ms(8000);
  •                 delay_ms(8000);
  •                 delay_ms(8000);
  •                 delay_ms(8000);
  •                 OLED_DrawBMP(0,0,128,8,BMP1);  //显示图片
  •                 delay_ms(8000);
  •                 delay_ms(8000);
  •                 delay_ms(8000);
  •                 delay_ms(8000);
  •                 OLED_DrawBMP(0,0,128,8,BMP1);
  •                 delay_ms(8000);
  •                 delay_ms(8000);
  •                 delay_ms(8000);
  •                 delay_ms(8000);
  •         }
  • }
  • //oled c文件
  • void IIC_Start()
  • {
  •         OLED_SCLK_Set() ;
  •         OLED_SDIN_Set();
  •         OLED_SDIN_Clr();
  •         OLED_SCLK_Clr();
  • }
  • /**********************************************
  • //IIC Stop
  • **********************************************/
  • void IIC_Stop()
  • {
  • OLED_SCLK_Set() ;
  • //        OLED_SCLK_Clr();
  •         OLED_SDIN_Clr();
  •         OLED_SDIN_Set();
  • }
  • void IIC_Wait_Ack()
  • {
  •         //GPIOB->CRH &= 0XFFF0FFFF;        //设置PB12为上拉输入
  •         //GPIOB->CRH |= 0x00080000;
  • //        OLED_SDA = 1;
  • //        delay_us(1);
  •         //OLED_SCL = 1;
  •         //delay_us(50000);
  • /*        while(1)
  •         {
  •                 if(!OLED_SDA)                                //判断是否接收到应答
  •                 {
  •                         //GPIOB->CRH &= 0XFFF0FFFF;        //设置PB12为推挽输出
  •                         //GPIOB->CRH |= 0x00030000;
  •                         return;
  •                 }
  •         }
  • */
  •         OLED_SCLK_Set() ;
  •         OLED_SCLK_Clr();
  • }
  • /**********************************************
  • // IIC Write byte
  • **********************************************/
  • void Write_IIC_Byte(unsigned char IIC_Byte)
  • {
  •         unsigned char i;
  •         unsigned char m,da;
  •         da=IIC_Byte;
  •         OLED_SCLK_Clr();
  •         for(i=0;i<8;i++)
  •         {
  •                         m=da;
  •                 //        OLED_SCLK_Clr();
  •                 m=m&0x80;
  •                 if(m==0x80)
  •                 {OLED_SDIN_Set();}
  •                 else OLED_SDIN_Clr();
  •                         da=da<<1;
  •                 OLED_SCLK_Set();
  •                 OLED_SCLK_Clr();
  •                 }
  • }
  • void Write_IIC_Command(unsigned char IIC_Command)
  • {
  •    IIC_Start();
  •    Write_IIC_Byte(0x78);            //Slave address,SA0=0
  •         IIC_Wait_Ack();
  •    Write_IIC_Byte(0x00);                        //write command
  •         IIC_Wait_Ack();
  •    Write_IIC_Byte(IIC_Command);
  •         IIC_Wait_Ack();
  •    IIC_Stop();
  • }
  • /**********************************************
  • // IIC Write Data
  • **********************************************/
  • void Write_IIC_Data(unsigned char IIC_Data)
  • {
  •    IIC_Start();
  •    Write_IIC_Byte(0x78);                        //D/C#=0; R/W#=0
  •         IIC_Wait_Ack();
  •    Write_IIC_Byte(0x40);                        //write data
  •         IIC_Wait_Ack();
  •    Write_IIC_Byte(IIC_Data);
  •         IIC_Wait_Ack();
  •    IIC_Stop();
  • }
  • void OLED_WR_Byte(unsigned dat,unsigned cmd)
  • {
  •         if(cmd)
  •                         {
  •    Write_IIC_Data(dat);
  •                 }
  •         else {
  •    Write_IIC_Command(dat);
  •         }
  • }
  • /********************************************
  • // fill_Picture
  • ********************************************/
  • void fill_picture(unsigned char fill_Data)
  • {
  •         unsigned char m,n;
  •         for(m=0;m<8;m++)
  •         {
  •                 OLED_WR_Byte(0xb0+m,0);                //page0-page1
  •                 OLED_WR_Byte(0x00,0);                //low column start address
  •                 OLED_WR_Byte(0x10,0);                //high column start address
  •                 for(n=0;n<128;n++)
  •                         {
  •                                 OLED_WR_Byte(fill_Data,1);
  •                         }
  •         }
  • }
  • /***********************Delay****************************************/
  • void Delay_50ms(unsigned int Del_50ms)
  • {
  •         unsigned int m;
  •         for(;Del_50ms>0;Del_50ms--)
  •                 for(m=6245;m>0;m--);
  • }
  • void Delay_1ms(unsigned int Del_1ms)
  • {
  •         unsigned char j;
  •         while(Del_1ms--)
  •         {
  •                 for(j=0;j<123;j++);
  •         }
  • }
  • //坐标显示
  •         void OLED_Set_Pos(unsigned char x, unsigned char y)
  • {         OLED_WR_Byte(0xb0+y,OLED_CMD);
  •         OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
  •         OLED_WR_Byte((x&0x0f),OLED_CMD);
  • }
  • //开启OLED显示
  • void OLED_Display_On(void)
  • {
  •         OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDCÃüÁî
  •         OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ON
  •         OLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON
  • }
  • //关闭OLED显示
  • void OLED_Display_Off(void)
  • {
  •         OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDCÃüÁî
  •         OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFF
  •         OLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
  • }
  • //清屏函数
  • void OLED_Clear(void)
  • {
  •         u8 i,n;
  •         for(i=0;i<8;i++)
  •         {
  •                 OLED_WR_Byte (0xb0+i,OLED_CMD);    //ÉèÖÃÒ³µØÖ·£¨0~7£©
  •                 OLED_WR_Byte (0x00,OLED_CMD);      //ÉèÖÃÏÔʾλÖáªÁе͵ØÖ·
  •                 OLED_WR_Byte (0x10,OLED_CMD);      //ÉèÖÃÏÔʾλÖáªÁиߵØÖ·
  •                 for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA);
  •         } //更新显示
  • }
  • void OLED_On(void)
  • {
  •         u8 i,n;
  •         for(i=0;i<8;i++)
  •         {
  •                 OLED_WR_Byte (0xb0+i,OLED_CMD);    //ÉèÖÃÒ³µØÖ·£¨0~7£©
  •                 OLED_WR_Byte (0x00,OLED_CMD);      //ÉèÖÃÏÔʾλÖáªÁе͵ØÖ·
  •                 OLED_WR_Byte (0x10,OLED_CMD);      //ÉèÖÃÏÔʾλÖáªÁиߵØÖ·
  •                 for(n=0;n<128;n++)OLED_WR_Byte(1,OLED_DATA);
  •         } //更新显示
  • }
  • //在指定位置显示一个字符
  • //x:0~127
  • //y:0~63
  • //mode: 0反白显示 1正常显示
  • //size:选择字体16/12
  • void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size)
  • {
  •         unsigned char c=0,i=0;
  •                 c=chr-' ';//得到偏移后的值
  •                 if(x>Max_Column-1){x=0;y=y+2;}
  •                 if(Char_Size ==16)
  •                         {
  •                         OLED_Set_Pos(x,y);
  •                         for(i=0;i<8;i++)
  •                         OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
  •                         OLED_Set_Pos(x,y+1);
  •                         for(i=0;i<8;i++)
  •                         OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
  •                         }
  •                         else {
  •                                 OLED_Set_Pos(x,y);
  •                                 for(i=0;i<6;i++)
  •                                 OLED_WR_Byte(F6x8[c],OLED_DATA);
  •                         }
  • }
  • //m^n函数
  • u32 oled_pow(u8 m,u8 n)
  • {
  •         u32 result=1;
  •         while(n--)result*=m;
  •         return result;
  • }
  • //显示两个数字
  • //x,y :起点坐标
  • //len :数字的位数
  • //size:字体的大小
  • //mode:0填充模式 1叠加模式
  • //num:数值(0~4294967295);
  • void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size2)
  • {
  •         u8 t,temp;
  •         u8 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);
  •                                 continue;
  •                         }else enshow=1;
  •                 }
  •                  OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2);
  •         }
  • }
  • //显示一个字符
  • void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 Char_Size)
  • {
  •         unsigned char j=0;
  •         while (chr[j]!='\0')
  •         {                OLED_ShowChar(x,y,chr[j],Char_Size);
  •                         x+=8;
  •                 if(x>120){x=0;y+=2;}
  •                         j++;
  •         }
  • }
  • //显示汉字
  • void OLED_ShowCHinese(u8 x,u8 y,u8 no)
  • {
  •         u8 t,adder=0;
  •         OLED_Set_Pos(x,y);
  •     for(t=0;t<16;t++)
  •                 {
  •                                 OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);
  •                                 adder+=1;
  •      }
  •                 OLED_Set_Pos(x,y+1);
  •     for(t=0;t<16;t++)
  •                         {
  •                                 OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);
  •                                 adder+=1;
  •       }
  • }
  • /***********显示BMP图片*****************/
  • 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_WR_Byte(BMP[j++],OLED_DATA);
  •             }
  •         }
  • }
  • //初始化SSD1306
  • void OLED_Init(void)
  • {
  •          GPIO_InitTypeDef  GPIO_InitStructure;
  •          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOG, ENABLE);         //ʹÄÜPC,D,G¶Ë¿ÚʱÖÓ
  •         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_3|GPIO_Pin_8;         //PD3,PD6ÍÆÍìÊä³ö
  •          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
  •         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50HZ
  •          GPIO_Init(GPIOD, &GPIO_InitStructure);          //初始化GPIOD3,6
  •          GPIO_SetBits(GPIOD,GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_3|GPIO_Pin_8);        //PD3,PD6 Êä³ö¸ß
  • #if OLED_MODE==1
  •          GPIO_InitStructure.GPIO_Pin =0xFF; //PC0~7 推挽输出
  •          GPIO_Init(GPIOC, &GPIO_InitStructure);
  •          GPIO_SetBits(GPIOC,0xFF); //PC0~7输出高
  •          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;                                 //PG13,14,15 OUT推挽输出
  •          GPIO_Init(GPIOG, &GPIO_InitStructure);
  •          GPIO_SetBits(GPIOG,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);                                                 //PG13,14,15 OUT  输出高
  • #else
  •          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;                                 //PC0,1 OUT推挽输出
  •          GPIO_Init(GPIOC, &GPIO_InitStructure);
  •          GPIO_SetBits(GPIOC,GPIO_Pin_0|GPIO_Pin_1);                                                 //PC0,1 OUT  输出高
  •         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;                                 //PG15 OUT 推挽输出          RST
  •          GPIO_Init(GPIOG, &GPIO_InitStructure);
  •          GPIO_SetBits(GPIOG,GPIO_Pin_15);                                                 //PG15 OUT  输出高
  • #endif
  • delay_ms(200);
  • OLED_WR_Byte(0xAE,OLED_CMD);//--display off
  •         OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
  •         OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
  •         OLED_WR_Byte(0x40,OLED_CMD);//--set start line address
  •         OLED_WR_Byte(0xB0,OLED_CMD);//--set page address
  •         OLED_WR_Byte(0x81,OLED_CMD); // contract control
  •         OLED_WR_Byte(0xFF,OLED_CMD);//--128
  •         OLED_WR_Byte(0xA1,OLED_CMD);//set segment remap
  •         OLED_WR_Byte(0xA6,OLED_CMD);//--normal / reverse
  •         OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
  •         OLED_WR_Byte(0x3F,OLED_CMD);//--1/32 duty
  •         OLED_WR_Byte(0xC8,OLED_CMD);//Com scan direction
  •         OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset
  •         OLED_WR_Byte(0x00,OLED_CMD);//
  •         OLED_WR_Byte(0xD5,OLED_CMD);//set osc division
  •         OLED_WR_Byte(0x80,OLED_CMD);//
  •         OLED_WR_Byte(0xD8,OLED_CMD);//set area color mode off
  •         OLED_WR_Byte(0x05,OLED_CMD);//
  •         OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-Charge Period
  •         OLED_WR_Byte(0xF1,OLED_CMD);//
  •         OLED_WR_Byte(0xDA,OLED_CMD);//set com pin configuartion
  •         OLED_WR_Byte(0x12,OLED_CMD);//
  •         OLED_WR_Byte(0xDB,OLED_CMD);//set Vcomh
  •         OLED_WR_Byte(0x30,OLED_CMD);//
  •         OLED_WR_Byte(0x8D,OLED_CMD);//set charge pump enable
  •         OLED_WR_Byte(0x14,OLED_CMD);//
  •         OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
  • }


复制代码


使用特权

评论回复
板凳
elephant00|  楼主 | 2023-5-9 10:10 | 只看该作者
代码部分结束 总工程文件评论区留下邮箱我会发送
2020.12.3
又针对代码做出了一些改良 实现了通过按键实现翻页 按键部分是搬运的正点原子的代码 现贴出主函数
  • #include "delay.h"
  • #include "sys.h"
  • #include "oled.h"
  • #include "key.h"
  • int main(void)
  •   {
  •                 u8 key=0;
  •                 delay_init();                    //延时函数初始化
  •                 NVIC_Configuration();         //设置nvic中断
  •                 OLED_Init();                        //oled初始化
  •                 OLED_Clear();           //清屏
  •                 KEY_Init();             //按键初始化
  •                 OLED_ShowCHinese(18,0,0);//
  •                 OLED_ShowCHinese(36,0,1);//
  •                 OLED_ShowCHinese(72,0,0);//
  •                 OLED_ShowCHinese(90,0,1);//
  •                 while(1)
  •         {
  •                    key=KEY_Scan(0);        //µÃµ½¼üÖµ
  • //              if(key)
  • //                {
  •                         switch(key)
  •                         {
  •                         case WKUP_PRES:
  •                         OLED_Init();
  •                         OLED_Clear();
  •                     OLED_ShowCHinese(18,0,2);
  •                     OLED_ShowCHinese(36,0,3);
  •                     OLED_ShowCHinese(72,0,4);
  •                     OLED_ShowCHinese(90,0,5);
  •                         break;
  •                         case KEY1_PRES:
  •                         OLED_Init();
  •                         OLED_Clear();
  •                     OLED_ShowCHinese(18,0,7);
  •                     OLED_ShowCHinese(36,0,8);
  •                     OLED_ShowCHinese(72,0,9);
  •                     OLED_ShowCHinese(90,0,10);
  •                         break;
  •                         case KEY0_PRES:
  •                         break;
  •                         }
  • //                }else delay_ms(10);
  •         }
  • }


复制代码


效果如图








完结

使用特权

评论回复
评论
王栋春 2023-5-9 22:13 回复TA
围观了解一下,一直对软件非常抵触,学不会呀。 
地板
Undshing| | 2023-5-9 22:17 | 只看该作者
按键部分怎么做的啊

使用特权

评论回复
5
zps136631| | 2023-5-10 13:26 | 只看该作者
多谢分享,不错!
邮箱:xwzps1@126.com
谢谢!

使用特权

评论回复
6
baiyunping333| | 2024-1-11 17:15 | 只看该作者
baiyunping333@126.com 能给我也发一份吗

使用特权

评论回复
7
周半梅| | 2024-4-1 08:03 | 只看该作者

对于没有else的场景,使用ifPresent即可

使用特权

评论回复
8
Pulitzer| | 2024-4-1 09:06 | 只看该作者

每个Strategy交由Spring管理,并在构造后注册

使用特权

评论回复
9
童雨竹| | 2024-4-1 11:02 | 只看该作者

使用Optional简化if判空

使用特权

评论回复
10
Wordsworth| | 2024-4-1 12:05 | 只看该作者

不同的代码逻辑就代表了不同的策略

使用特权

评论回复
11
Clyde011| | 2024-4-1 13:08 | 只看该作者

对于优秀程序员来说,这不是好代码

使用特权

评论回复
12
公羊子丹| | 2024-4-1 14:01 | 只看该作者

通过对判断条件取反,代码在逻辑表达上会更加清晰

使用特权

评论回复
13
万图| | 2024-4-1 15:04 | 只看该作者

会以switch-case的方式出现

使用特权

评论回复
14
Uriah| | 2024-4-1 16:07 | 只看该作者

代码量小的时候用来做条件判断

使用特权

评论回复
15
帛灿灿| | 2024-4-1 18:03 | 只看该作者

不要根据不同的参数类型走不同的代码逻辑

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

914

主题

2368

帖子

4

粉丝