[APM32E1] 【APM32E103xE测评】+驱动OLED屏

[复制链接]
 楼主| yinwuqing110 发表于 2022-5-21 23:45 | 显示全部楼层 |阅读模式
    OLED屏在低功耗产品中应用比较广泛,该款屏幕模块尺寸为0.96英寸,主要由裸屏和底板PCB组成,裸屏由SSD1306驱动。这种小屏显示模块支持SPI、IIC通讯方式进行驱动,此次使用IIC通讯方式驱动。使用I2C接口时,SSD1306允许有最多两个7位的IIC地址,同样通过相应的IO口拉低拉高来切换,一般默认是0x3c,在屏幕模块的背面,可以看到一个I2C地址切换提示,需要改变模块I2C地址时,只需要把提示位置的电阻取下焊接到另外一端即可。要注意的是板上的IIC地址是加上了第零位读写位后的数值,即0x78 = 0x3c<<1,0x7A = 0x3d<<1。
     至于如何使用IIC与SSD1306进行时序的写入,某宝上免费提供参考资料,这里就不再赘述了,直接上部分应用代码啦!实际应用中GPIOB0连接模块的SCL引脚,GPIOB1连接模块的SDA引脚,使用“PCtoLCD2002”取模工具取模部分汉字与二进制图片。
  1. #include "main.h"
  2. #include "oled.h"
  3. #include "delay.h"
  4. #include "bmp.h"

  5. volatile uint32_t tick = 0;

  6. void Delay(void);

  7. int main(void)
  8. {
  9.                 u8 t;
  10.     APM_MINI_LEDInit(LED2);
  11.     APM_MINI_LEDInit(LED3);
  12.                 SysTick_Config(SystemCoreClock / 1000);
  13.     OLED_Init();                       
  14.                 OLED_Clear();
  15.                 t=' ';
  16.     while (1)
  17.     {
  18.       delay_ms(500);
  19.                         APM_MINI_LEDOn(LED2);
  20.                         APM_MINI_LEDOn(LED3);
  21.                         delay_ms(500);
  22.                         APM_MINI_LEDOff(LED2);
  23.                         APM_MINI_LEDOff(LED3);
  24.                        
  25.                         OLED_Clear();
  26.                         OLED_ShowCHinese(10,0,25);//欢
  27.                         OLED_ShowCHinese(18+10,0,26);//迎
  28.                         OLED_ShowCHinese(36+10,0,27);//使
  29.                         OLED_ShowCHinese(54+10,0,28);//用
  30.                         OLED_ShowString(6,3,"APM32E103ZE",16);
  31.                         OLED_ShowString(6,6,"2022-05-15",16);
  32.                         delay_ms(800);
  33.       OLED_Clear();
  34.                         OLED_ShowCHinese(10,0,20);//极
  35.                         OLED_ShowCHinese(18+10,0,21);//海
  36.                         OLED_ShowCHinese(36+10,0,22);//半
  37.                         OLED_ShowCHinese(54+10,0,23);//导
  38.                         OLED_ShowCHinese(72+10,0,24);//体
  39.                         OLED_ShowString(16,3,"Mini Board",16);
  40.                         OLED_ShowChar(48,6,t,16);//显示ASCII字符
  41.                         delay_ms(50);
  42.                         t++;
  43.                         if(t>'~')t=' ';
  44.                         OLED_ShowNum(103,6,t,3,16);//显示ASCII字符的码值        
  45.                         delay_ms(1000);
  46.                         OLED_Clear();
  47.                         OLED_DrawBMP(0,0,128,8,BMP2);  //图片显示(图片显示慎用,生成的字表较大,会占用较多空间,FLASH空间8K以下慎用)
  48.                         delay_ms(1000);
  49.     }
  50. }

  51. void Delay(void)
  52. {
  53.     volatile uint32_t delay = 0x3fffff;
  54.    
  55.     while(delay--);
  56. }
  1. #ifndef __OLED_H
  2. #define __OLED_H

  3. #include "apm32e10x.h"
  4. #include "apm32e10x_gpio.h"
  5. #include "apm32e10x_rcm.h"
  6. #include "stdlib.h"          
  7. #include "stdint.h"

  8. #define OLED_MODE 0
  9. #define SIZE 8
  10. #define XLevelL                0x00
  11. #define XLevelH                0x10
  12. #define Max_Column        128
  13. #define Max_Row                64
  14. #define        Brightness        0xFF
  15. #define X_WIDTH         128
  16. #define Y_WIDTH         64                                                              
  17. //-----------------OLED IIC端口定义----------------
  1. #include "oled.h"
  2. #include "stdlib.h"
  3. #include "oledfont.h"           
  4. #include "delay.h"

  5. /**********************************************
  6. //IIC Start
  7. **********************************************/
  8. void IIC_Start()
  9. {
  10.         OLED_SCLK_Set();
  11.         OLED_SDIN_Set();
  12.         OLED_SDIN_Clr();
  13.         OLED_SCLK_Clr();
  14. }

  15. /**********************************************
  16. //IIC Stop
  17. **********************************************/
  18. void IIC_Stop()
  19. {
  20.         OLED_SCLK_Set() ;
  21.         //OLED_SCLK_Clr();
  22.         OLED_SDIN_Clr();
  23.         OLED_SDIN_Set();
  24.        
  25. }

  26. void IIC_Wait_Ack()
  27. {
  28.         OLED_SCLK_Set() ;
  29.         OLED_SCLK_Clr();
  30. }
  31. /**********************************************
  32. // IIC Write byte
  33. **********************************************/

  34. void Write_IIC_Byte(unsigned char IIC_Byte)
  35. {
  36.         unsigned char i;
  37.         unsigned char m,da;
  38.         da=IIC_Byte;
  39.         OLED_SCLK_Clr();
  40.         for(i=0;i<8;i++)               
  41.         {
  42.                         m=da;
  43.                 m=m&0x80;
  44.                 if(m==0x80)
  45.                 {OLED_SDIN_Set();}
  46.                 else OLED_SDIN_Clr();
  47.                         da=da<<1;
  48.                 OLED_SCLK_Set();
  49.                 OLED_SCLK_Clr();
  50.                 }
  51. }
  52. /**********************************************
  53. // IIC Write Command
  54. **********************************************/
  55. void Write_IIC_Command(unsigned char IIC_Command)
  56. {
  57.    IIC_Start();
  58.    Write_IIC_Byte(0x78);            //Slave address,SA0=0
  59.         IIC_Wait_Ack();       
  60.    Write_IIC_Byte(0x00);                        //write command
  61.         IIC_Wait_Ack();       
  62.    Write_IIC_Byte(IIC_Command);
  63.         IIC_Wait_Ack();       
  64.    IIC_Stop();
  65. }
  66. /**********************************************
  67. // IIC Write Data
  68. **********************************************/
  69. void Write_IIC_Data(unsigned char IIC_Data)
  70. {
  71.    IIC_Start();
  72.    Write_IIC_Byte(0x78);                        //D/C#=0; R/W#=0
  73.         IIC_Wait_Ack();       
  74.    Write_IIC_Byte(0x40);                        //write data
  75.         IIC_Wait_Ack();       
  76.    Write_IIC_Byte(IIC_Data);
  77.         IIC_Wait_Ack();       
  78.    IIC_Stop();
  79. }
  80. void OLED_WR_Byte(unsigned dat,unsigned cmd)
  81. {
  82.         if(cmd)
  83.                         {

  84.    Write_IIC_Data(dat);
  85.    
  86.                 }
  87.         else {
  88.    Write_IIC_Command(dat);
  89.                
  90.         }


  91. }


  92. /********************************************
  93. // fill_Picture
  94. ********************************************/
  95. void fill_picture(unsigned char fill_Data)
  96. {
  97.         unsigned char m,n;
  98.         for(m=0;m<8;m++)
  99.         {
  100.                 OLED_WR_Byte(0xb0+m,0);                //page0-page1
  101.                 OLED_WR_Byte(0x00,0);                //low column start address
  102.                 OLED_WR_Byte(0x10,0);                //high column start address
  103.                 for(n=0;n<128;n++)
  104.                         {
  105.                                 OLED_WR_Byte(fill_Data,1);
  106.                         }
  107.         }
  108. }


  109. /***********************Delay****************************************/
  110. void Delay_50ms(unsigned int Del_50ms)
  111. {
  112.         unsigned int m;
  113.         for(;Del_50ms>0;Del_50ms--)
  114.                 for(m=6245;m>0;m--);
  115. }
  116. /*
  117. void Delay_1ms(unsigned int Del_1ms)
  118. {
  119.         unsigned char j;
  120.         while(Del_1ms--)
  121.         {       
  122.                 for(j=0;j<123;j++);
  123.         }
  124. }
  125. */
  126. //坐标设置

  127.         void OLED_Set_Pos(unsigned char x, unsigned char y)
  128. {         OLED_WR_Byte(0xb0+y,OLED_CMD);
  129.         OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
  130.         OLED_WR_Byte((x&0x0f),OLED_CMD);
  131. }             
  132. //开启OLED显示   
  133. void OLED_Display_On(void)
  134. {
  135.         OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
  136.         OLED_WR_Byte(0X14,OLED_CMD);  //DCDC ON
  137.         OLED_WR_Byte(0XAF,OLED_CMD);  //DISPLAY ON
  138. }
  139. //关闭OLED显示     
  140. void OLED_Display_Off(void)
  141. {
  142.         OLED_WR_Byte(0X8D,OLED_CMD);  //SET DCDC命令
  143.         OLED_WR_Byte(0X10,OLED_CMD);  //DCDC OFF
  144.         OLED_WR_Byte(0XAE,OLED_CMD);  //DISPLAY OFF
  145. }                                            

  146. void OLED_Clear(void)  
  147. {  
  148.         u8 i,n;                    
  149.         for(i=0;i<8;i++)  
  150.         {  
  151.                 OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)
  152.                 OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
  153.                 OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   
  154.                 for(n=0;n<128;n++)OLED_WR_Byte(0,OLED_DATA);
  155.         } //更新显示
  156. }
  157. void OLED_On(void)  
  158. {  
  159.         u8 i,n;                    
  160.         for(i=0;i<8;i++)  
  161.         {  
  162.                 OLED_WR_Byte (0xb0+i,OLED_CMD);    //设置页地址(0~7)
  163.                 OLED_WR_Byte (0x00,OLED_CMD);      //设置显示位置—列低地址
  164.                 OLED_WR_Byte (0x10,OLED_CMD);      //设置显示位置—列高地址   
  165.                 for(n=0;n<128;n++)OLED_WR_Byte(1,OLED_DATA);
  166.         } //更新显示
  167. }
  168. //在指定位置显示一个字符,包括部分字符
  169. //x:0~127
  170. //y:0~63
  171. //mode:0,反白显示;1,正常显示                                 
  172. //size:选择字体 16/12
  173. void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size)
  174. {             
  175.         unsigned char c=0,i=0;       
  176.                 c=chr-' ';//得到偏移后的值                       
  177.                 if(x>Max_Column-1){x=0;y=y+2;}
  178.                 if(Char_Size ==16)
  179.                         {
  180.                         OLED_Set_Pos(x,y);       
  181.                         for(i=0;i<8;i++)
  182.                         OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
  183.                         OLED_Set_Pos(x,y+1);
  184.                         for(i=0;i<8;i++)
  185.                         OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
  186.                         }
  187.                         else {       
  188.                                 OLED_Set_Pos(x,y);
  189.                                 for(i=0;i<6;i++)
  190.                                 OLED_WR_Byte(F6x8[c][i],OLED_DATA);
  191.                                
  192.                         }
  193. }
  194. //m^n函数
  195. u32 oled_pow(u8 m,u8 n)
  196. {
  197.         u32 result=1;         
  198.         while(n--)result*=m;   
  199.         return result;
  200. }                                  
  201. //显示2个数字
  202. //x,y :起点坐标         
  203. //len :数字的位数
  204. //size:字体大小
  205. //mode:模式        0,填充模式;1,叠加模式
  206. //num:数值(0~4294967295);                           
  207. void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size2)
  208. {                
  209.         u8 t,temp;
  210.         u8 enshow=0;                                                  
  211.         for(t=0;t<len;t++)
  212.         {
  213.                 temp=(num/oled_pow(10,len-t-1))%10;
  214.                 if(enshow==0&&t<(len-1))
  215.                 {
  216.                         if(temp==0)
  217.                         {
  218.                                 OLED_ShowChar(x+(size2/2)*t,y,' ',size2);
  219.                                 continue;
  220.                         }else enshow=1;
  221.                           
  222.                 }
  223.                  OLED_ShowChar(x+(size2/2)*t,y,temp+'0',size2);
  224.         }
  225. }
  226. //显示一个字符号串
  227. void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 Char_Size)
  228. {
  229.         unsigned char j=0;
  230.         while (chr[j]!='\0')
  231.         {                OLED_ShowChar(x,y,chr[j],Char_Size);
  232.                         x+=8;
  233.                 if(x>120){x=0;y+=2;}
  234.                         j++;
  235.         }
  236. }
  237. //显示汉字
  238. void OLED_ShowCHinese(u8 x,u8 y,u8 no)
  239. {                                  
  240.         u8 t,adder=0;
  241.         OLED_Set_Pos(x,y);       
  242.     for(t=0;t<16;t++)
  243.                 {
  244.                                 OLED_WR_Byte(Hzk[2*no][t],OLED_DATA);
  245.                                 adder+=1;
  246.      }       
  247.                 OLED_Set_Pos(x,y+1);       
  248.     for(t=0;t<16;t++)
  249.                         {       
  250.                                 OLED_WR_Byte(Hzk[2*no+1][t],OLED_DATA);
  251.                                 adder+=1;
  252.       }                                       
  253. }
  254. /***********功能描述:显示显示BMP图片128×64起始点坐标(x,y),x的范围0~127,y为页的范围0~7*****************/
  255. void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[])
  256. {        
  257. unsigned int j=0;
  258. unsigned char x,y;
  259.   
  260.   if(y1%8==0) y=y1/8;      
  261.   else y=y1/8+1;
  262.         for(y=y0;y<y1;y++)
  263.         {
  264.                 OLED_Set_Pos(x0,y);
  265.     for(x=x0;x<x1;x++)
  266.             {      
  267.                     OLED_WR_Byte(BMP[j++],OLED_DATA);                   
  268.             }
  269.         }
  270. }

  271. //初始化SSD1306                                            
  272. void OLED_Init(void)
  273. {        
  274.           GPIO_Config_T  configStruct;
  275.                 /* enable the OLED GPIO clock */
  276.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOB);
  277.     /* configure OLED GPIO pin */
  278.                 configStruct.pin = (GPIO_PIN_0 | GPIO_PIN_1);
  279.     configStruct.mode = GPIO_MODE_OUT_PP;
  280.     configStruct.speed = GPIO_SPEED_50MHz;
  281.           GPIO_Config(GPIOB, &configStruct);
  282.        
  283.           GPIO_SetBits(GPIOB,GPIO_PIN_0|GPIO_PIN_1);       
  284.        
  285.     delay_ms(800);
  286.     OLED_WR_Byte(0xAE,OLED_CMD);//--display off
  287.                 OLED_WR_Byte(0x00,OLED_CMD);//---set low column address
  288.                 OLED_WR_Byte(0x10,OLED_CMD);//---set high column address
  289.                 OLED_WR_Byte(0x40,OLED_CMD);//--set start line address  
  290.                 OLED_WR_Byte(0xB0,OLED_CMD);//--set page address
  291.                 OLED_WR_Byte(0x81,OLED_CMD); // contract control
  292.                 OLED_WR_Byte(0xFF,OLED_CMD);//--128   
  293.                 OLED_WR_Byte(0xA1,OLED_CMD);//set segment remap
  294.                 OLED_WR_Byte(0xA6,OLED_CMD);//--normal / reverse
  295.                 OLED_WR_Byte(0xA8,OLED_CMD);//--set multiplex ratio(1 to 64)
  296.                 OLED_WR_Byte(0x3F,OLED_CMD);//--1/32 duty
  297.                 OLED_WR_Byte(0xC8,OLED_CMD);//Com scan direction
  298.                 OLED_WR_Byte(0xD3,OLED_CMD);//-set display offset
  299.                 OLED_WR_Byte(0x00,OLED_CMD);//
  300.                
  301.                 OLED_WR_Byte(0xD5,OLED_CMD);//set osc division
  302.                 OLED_WR_Byte(0x80,OLED_CMD);//
  303.                
  304.                 OLED_WR_Byte(0xD8,OLED_CMD);//set area color mode off
  305.                 OLED_WR_Byte(0x05,OLED_CMD);//
  306.                
  307.                 OLED_WR_Byte(0xD9,OLED_CMD);//Set Pre-Charge Period
  308.                 OLED_WR_Byte(0xF1,OLED_CMD);//
  309.                
  310.                 OLED_WR_Byte(0xDA,OLED_CMD);//set com pin configuartion
  311.                 OLED_WR_Byte(0x12,OLED_CMD);//
  312.                
  313.                 OLED_WR_Byte(0xDB,OLED_CMD);//set Vcomh
  314.                 OLED_WR_Byte(0x30,OLED_CMD);//
  315.                
  316.                 OLED_WR_Byte(0x8D,OLED_CMD);//set charge pump enable
  317.                 OLED_WR_Byte(0x14,OLED_CMD);//
  318.                
  319.                 OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
  320. }  
       编译完成后,使用JLink的SWD方式下载到开发板中,重启开发板,显示效果如下:
效果_.gif

评论

好东西  发表于 2022-6-1 17:31
WoodData 发表于 2022-5-23 14:29 | 显示全部楼层
学习学习
liqingfeng123 发表于 2022-5-24 09:40 | 显示全部楼层
给力,好东西~
janewood 发表于 2022-5-28 12:53 | 显示全部楼层
SSD1306支持彩色屏幕吗
mollylawrence 发表于 2022-5-28 13:19 | 显示全部楼层
APM32E103和f103有区别吗  
pmp 发表于 2022-5-28 13:39 | 显示全部楼层
学习一下,谢谢分析的。  
dspmana 发表于 2022-5-28 14:18 | 显示全部楼层
主要是看单片机的性能。   
minzisc 发表于 2022-5-28 15:06 | 显示全部楼层
APM32E103可以吗?
rosemoore 发表于 2022-5-28 16:28 | 显示全部楼层
这个是spi的屏幕吗
wangdezhi 发表于 2022-5-28 17:07 | 显示全部楼层
可以获取所有的汉字字幕吗?
JunKook 发表于 2022-5-28 21:14 | 显示全部楼层
janewood 发表于 2022-5-28 12:53
SSD1306支持彩色屏幕吗

支持的
JunKook 发表于 2022-5-28 21:17 | 显示全部楼层
wangdezhi 发表于 2022-5-28 17:07
可以获取所有的汉字字幕吗?

用字模提取工具PCtoLCD2002可以获取
JunKook 发表于 2022-5-28 21:17 | 显示全部楼层
rosemoore 发表于 2022-5-28 16:28
这个是spi的屏幕吗

这个是IIC驱动
JunKook 发表于 2022-5-28 21:17 | 显示全部楼层
minzisc 发表于 2022-5-28 15:06
APM32E103可以吗?

极海全系列MCU均可以驱动OLED屏
JunKook 发表于 2022-5-28 21:19 | 显示全部楼层
mollylawrence 发表于 2022-5-28 13:19
APM32E103和f103有区别吗

极海103的E系列和F系列差异详见此文https://bbs.21ic.com/icview-3223260-1-1.html
caigang13 发表于 2022-6-1 19:07 来自手机 | 显示全部楼层
IIC驱动就是刷新频率慢了
AloneKaven 发表于 2022-11-4 21:45 | 显示全部楼层
SSD1306支持彩色屏幕吗?
Undshing 发表于 2023-1-3 16:07 | 显示全部楼层
主要是看单片机的性能
您需要登录后才可以回帖 登录 | 注册

本版积分规则

106

主题

1098

帖子

7

粉丝
快速回复 在线客服 返回列表 返回顶部

106

主题

1098

帖子

7

粉丝
快速回复 在线客服 返回列表 返回顶部