[STM32] 灵感手环第一步——0.96寸OLED显示实验(二)

[复制链接]
669|3
 楼主 | 2017-12-23 00:29 | 显示全部楼层 |阅读模式
本帖最后由 Andrew55 于 2017-12-23 00:39 编辑

首先是SPI.C,包含了对该模块的各种操作,就是对SPI 写进行符合OLED的包装。写字符,写数字,写字符串,可调显示字体大小,但是需要包含两个ASCII字库。

写完这个文件,就可以在主函数调用  OLED_ShowChinese() ,进行参数配置后,就可以显示了。
具体调用方式为:OLED_ShowChinese(32,0,0);//钱
这个里面前两个参数是进行显示坐标选择,第三个参数是选择你的字库里面第几个汉字的行数。比如我选择了 0,那么在我的字库头文件中前两个ASCII码表就是我要显示汉字的ASCII码表,这个码表是采用字模软件生成的。
  1. #include "spi.h"
  2. #include "word.h"  //字库头文件

  3. #define OLED_Order 0       //定义写命令
  4. #define OLED_Data  1        //定义写数据  

  5. //尽在内部调用函数
  6. static u32 oled_pow(u8 m,u8 n);
  7. static void OLED_GPIO_INIT(void);
  8. static void SPI_Write(u8 data, u8 Mode);
  9. static void OLED_Coord(u8 x, u8 y);  

  10. //使用管脚初始化
  11. static void OLED_GPIO_INIT(void)
  12. {
  13.     GPIO_InitTypeDef GPIO_InitStruct;  
  14.       
  15.     //开启GPIOD的时钟  
  16.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  17.     //设置GPIO的基本参数  
  18.     GPIO_InitStruct.GPIO_Pin = OLED_CS_PIN | OLED_RST_PIN | OLED_DC_PIN | OLED_D0_PIN | OLED_D1_PIN;  
  19.     GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;    //推挽输出  
  20.     GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;    //输出速度50MHz  
  21.       
  22.     GPIO_Init(OLED_PORT, &GPIO_InitStruct);  
  23.       
  24.     GPIO_SetBits(OLED_PORT, OLED_CS_PIN | OLED_RST_PIN | OLED_DC_PIN | OLED_D0_PIN | OLED_D1_PIN);  
  25. }

  26. /*    SPI写数据/命令
  27. *    Mode :OLED_Order:写命令   OLED_Data:写数据
  28. *    data :数据/命令
  29. */  
  30. static void SPI_Write(u8 data, u8 Mode)  
  31. {      
  32.     u8 i = 0;

  33.     if(Mode)  
  34.     {  
  35.         OLED_DC(1);        //DC引脚输入高,表示写数据  
  36.     }  
  37.     else  
  38.     {  
  39.         OLED_DC(0);        //DC引脚输入低,表示写命令  
  40.     }  
  41.     OLED_CS(0);            //CS引脚输入低,片选使能  
  42.     for(i = 0; i < 8; i++)  
  43.     {  
  44.         OLED_D0(0);        //D0引脚输入低  
  45.         if(data&0x80)    //判断传输的数据最高位为1还是0  
  46.         {  
  47.             OLED_D1(1);    //D1引脚输入高  
  48.         }  
  49.         else  
  50.         {  
  51.             OLED_D1(0);    //D1引脚输入低  
  52.         }  
  53.         OLED_D0(1);        //D1引脚输入高  
  54.         data<<=1;        //将数据左移一位  
  55.     }  
  56.     OLED_DC(1);            //DC引脚输入低  
  57.     OLED_CS(1);            //CS引脚输入高,片选失能  
  58. }  

  59. /*        设置OLED屏的显示坐标
  60. *      X : 表示OLED的水平坐标(0—127)
  61. *      Y : 表示OLED的页(0—7)     
  62. */  
  63. static void OLED_Coord(u8 x, u8 y)  
  64. {      
  65.     SPI_Write((0xb0 + y) ,OLED_Order);
  66.     SPI_Write((((x & 0xf0)>>4) | 0x10), OLED_Order);//高4位  
  67.     SPI_Write((x & 0x0f)|0x01, OLED_Order);//低4位  
  68. }  
  69. //清屏,一开始这里写错了,把写命令写成了写数据,导致清屏不正确,发现屏幕上有很多噪点,说明没有清屏成功。
  70. void OLED_Clear(void)  
  71. {  
  72.     u8 i = 0, j = 0;  

  73.     for(i = 0; i < 8; i++)  
  74.     {  
  75.         SPI_Write(0xb0 + i,OLED_Order);
  76.         SPI_Write(0x00,OLED_Order);
  77.         SPI_Write(0x10,OLED_Order);
  78.         for(j = 0; j < 128; j++)  
  79.         {  
  80.             SPI_Write(0x00, OLED_Data);  
  81.         }  
  82.     }  
  83. }  

  84. //关oled显示
  85. void OLED_Display_Off(void)  
  86. {
  87.     SPI_Write(0x8D,OLED_Order);
  88.     SPI_Write(0x10,OLED_Order);
  89.     SPI_Write(0xAE,OLED_Order);
  90. }  
  91. //开oled显示
  92. void OLED_Display_On(void)
  93. {  
  94.     //电荷泵设置(初始化时必须打开,否则看不到显示)
  95.     SPI_Write(0x8D, OLED_Order);  
  96.     SPI_Write(0x14, OLED_Order);//bit2   0:关闭        1:打开  
  97.     SPI_Write(0xAF, OLED_Order);//0xAF:开显示      
  98. }  

  99. //oled参数初始化
  100. void OLED_Init(void)  
  101. {  
  102.     OLED_GPIO_INIT();  //端口初始化
  103.       
  104.     OLED_RST(1);     
  105.     delay_ms(100);  
  106.     OLED_RST(0);  
  107.     delay_ms(100);  
  108.     OLED_RST(1);
  109.    
  110.     SPI_Write(0xAE, OLED_Order);//0xAE:关显示     
  111.       
  112.     SPI_Write(0x00, OLED_Order);//设置低列地址  
  113.     SPI_Write(0x10, OLED_Order);//设置高列地址  
  114.       
  115.     //设置行显示的开始地址(0-63)  
  116.     //40-47: (01xxxxx)  
  117.     SPI_Write(0x40, OLED_Order);
  118.       
  119.     //设置对比度  
  120.     SPI_Write(0x81, OLED_Order);
  121.     SPI_Write(0xff, OLED_Order);//这个值越大,屏幕越亮(和上条指令一起使用)(0x00-0xff)  
  122.       
  123.     SPI_Write(0xA1, OLED_Order);//0xA1: 左右反置,  0xA0: 正常显示(默认0xA0)  
  124.     SPI_Write(0xC8, OLED_Order);//0xC8: 上下反置,  0xC0: 正常显示(默认0xC0)  
  125.       
  126.     //0xA6: 表示正常显示(在面板上1表示点亮,0表示不亮)  
  127.     //0xA7: 表示逆显示(在面板上0表示点亮,1表示不亮)  
  128.     SPI_Write(0xA6, OLED_Order);  
  129.       
  130.     SPI_Write(0xA8, OLED_Order);//设置多路复用率(1-64)  
  131.     SPI_Write(0x3F, OLED_Order);//(0x01-0x3f)(默认为3f)  
  132.       
  133.       
  134.     //设置显示抵消移位映射内存计数器  
  135.     SPI_Write(0xD3, OLED_Order);  
  136.     SPI_Write(0x00, OLED_Order);//(0x00-0x3f)(默认为0x00)  
  137.       
  138.     //设置显示时钟分频因子/振荡器频率  
  139.     SPI_Write(0xD5, OLED_Order);  
  140.     //低4位定义显示时钟(屏幕的刷新时间)(默认:0000)分频因子= [3:0]+1  
  141.     //高4位定义振荡器频率(默认:1000)  
  142.     SPI_Write(0x80, OLED_Order);//  
  143.       
  144.     //时钟预充电周期  
  145.     SPI_Write(0xD9, OLED_Order);  
  146.     SPI_Write(0xF1, OLED_Order);//[3:0],PHASE 1;   [7:4] PHASE 2  
  147.       
  148.     //设置COM硬件应脚配置  
  149.     SPI_Write(0xDA, OLED_Order);  
  150.     SPI_Write(0x12, OLED_Order);//[5:4]  默认:01  
  151.       
  152.     SPI_Write(0xDB, OLED_Order);//  
  153.     SPI_Write(0x40, OLED_Order);//  
  154.       
  155.     //设置内存寻址方式  
  156.     SPI_Write(0x20, OLED_Order);  
  157.     //00: 表示水平寻址方式  
  158.     //01: 表示垂直寻址方式  
  159.     //10: 表示页寻址方式(默认方式)  
  160.     SPI_Write(0x02, OLED_Order);//      
  161.       
  162.     //电荷泵设置(初始化时必须打开,否则看不到显示)  
  163.     SPI_Write(0x8D, OLED_Order);  
  164.     SPI_Write(0x14, OLED_Order);//bit2   0:关闭        1:打开  
  165.       
  166.     //设置是否全部显示 0xA4: 禁止全部显示  
  167.     SPI_Write(0xA4, OLED_Order);  
  168.   
  169.     //0xA6: 表示正常显示(在面板上1表示点亮,0表示不亮)  
  170.     //0xA7: 表示逆显示(在面板上0表示点亮,1表示不亮)  
  171.     SPI_Write(0xA6, OLED_Order);//  
  172.       
  173.     SPI_Write(0xAF, OLED_Order);//0xAF:开显示     
  174.     SPI_Write(0xAF, OLED_Order); //不知道为什么要写两次
  175.    
  176.     OLED_Clear();
  177.     OLED_Coord(0,0);
  178. }  

  179. //显示汉字,设置坐标,
  180. void OLED_ShowChinese(u8 x, u8 y, u8 chinese)  
  181. {  
  182.     u8 t,adder=0;
  183.    
  184.     OLED_Coord(x,y);

  185.     for(t=0;t<16;t++)  //每行16个元素,一个字需要两行字符串
  186.     {
  187.         SPI_Write(Hzk[2*chinese][t],OLED_Data);
  188.         adder+=1;
  189.      }   
  190.    
  191.     OLED_Coord(x,y+1);
  192.      
  193.     for(t=0;t<16;t++)
  194.     {   
  195.         SPI_Write(Hzk[2*chinese+1][t],OLED_Data);
  196.         adder+=1;
  197.       }   
  198. }


  199. //在指定位置显示一个字符,包括部分字符
  200. //x:0~127
  201. //y:0~63
  202. //mode:0,反白显示;1,正常显示
  203. //size:选择字体 16/12
  204. void OLED_ShowChar(u8 x, u8 y, u8 chr)  
  205. {  
  206.     unsigned char c=0,   i=0;   
  207.    
  208.     c = chr - ' ';    //得到偏移后的值
  209.    
  210.         if(x > Max_Column - 1)
  211.             {x=0;y=y+2;}
  212.             
  213.         if(SIZE ==16)  //8*16字符
  214.         {
  215.             OLED_Coord(x,y);
  216.             
  217.             for(i=0;i<8;i++)
  218.                 SPI_Write(F8X16[c*16+i],OLED_Data);
  219.             
  220.             OLED_Coord(x,y+1);
  221.             
  222.             for(i=0;i<8;i++)
  223.                 SPI_Write(F8X16[c*16+i+8],OLED_Data);
  224.         }
  225.         else    //6*8字符
  226.         {   
  227.             OLED_Coord(x,y+1);
  228.             
  229.             for(i=0;i<6;i++)
  230.                 SPI_Write(F6x8[c][i],OLED_Data);
  231.             
  232.         }
  233. }  

  234. //显示字符串
  235. void OLED_Show_String(u8 x, u8 y, u8 *chr)
  236. {
  237.     u8 j=0;
  238.     while (chr[j]!='\0')
  239.     {
  240.         OLED_ShowChar(x,y,chr[j]);

  241.         x+= 8 ;

  242.         if(x>120){x=0;y+=2;}  //自动换行写

  243.         j++;
  244.     }
  245. }


  246. //m^n函数
  247. static u32 oled_pow(u8 m,u8 n)
  248. {
  249.     u32 result = 1;
  250.     while(n--)result*=m;   
  251.     return result;
  252. }

  253. //显示数字
  254. //x,y :起点坐标     
  255. //len :数字的位数
  256. //size:字体大小
  257. //mode:模式    0,填充模式;1,叠加模式
  258. //num:数值(0~4294967295);               
  259. void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size)
  260. {            
  261.     u8 t = 0, temp = 0;
  262.     u8 enshow=0;
  263.    
  264.     for(t=0;t<len;t++)
  265.     {
  266.         temp=(num/oled_pow(10,len-t-1))%10;
  267.         
  268.         if(enshow==0&&t<(len-1))
  269.         {
  270.             if(temp==0)
  271.             {
  272.                 OLED_ShowChar(x+(size/2)*t,y,' ');
  273.                 continue;
  274.             }else enshow=1;
  275.               
  276.         }
  277.          OLED_ShowChar(x+(size/2)*t,y,temp+'0');
  278.     }
  279. }
复制代码

char Hzk[][32]={{0x20,0x10,0x2C,0xE7,0x24,0x24,0x00,0x90,0x90,0xFF,0x90,0x49,0x4A,0x48,0x40,0x00},{0x01,0x01,0x01,0x7F,0x21,0x11,0x40,0x40,0x20,0x13,0x0C,0x14,0x22,0x41,0xF8,0x00},/*"钱",7*//* (16 X 16 , 宋体 )*/
使用PCtoLCD2002完美版进行取模。具体字模生成方式可参见中景园官方教程。



汉字生成为两行16进制码表。
显示效果:

好了,第一部分算是写完了。


| 2018-3-2 22:54 | 显示全部楼层
是不是后面的图片挂了?
| 2018-6-10 20:07 | 显示全部楼层
是的
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式
我要创建版块 申请成为版主

论坛热帖

关闭

热门推荐上一条 /5 下一条

快速回复 返回顶部 返回列表